1 // 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.
5 #include "base/command_line.h"
6 #include "base/feature_list.h"
7 #include "base/run_loop.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/test/metrics/histogram_tester.h"
10 #include "base/test/scoped_feature_list.h"
11 #include "base/test/test_timeouts.h"
12 #include "build/build_config.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
16 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
17 #include "chrome/browser/tab_contents/navigation_metrics_recorder.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_commands.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/location_bar/location_bar.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
24 #include "chrome/common/chrome_features.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/url_constants.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "components/network_session_configurator/common/network_switches.h"
31 #include "components/omnibox/browser/omnibox_view.h"
32 #include "components/prefs/pref_service.h"
33 #include "components/site_isolation/features.h"
34 #include "components/site_isolation/pref_names.h"
35 #include "components/ukm/test_ukm_recorder.h"
36 #include "components/url_formatter/url_formatter.h"
37 #include "components/variations/active_field_trials.h"
38 #include "components/variations/hashing.h"
39 #include "content/public/browser/context_menu_params.h"
40 #include "content/public/browser/download_manager_delegate.h"
41 #include "content/public/browser/navigation_entry.h"
42 #include "content/public/browser/navigation_handle.h"
43 #include "content/public/browser/notification_service.h"
44 #include "content/public/browser/reload_type.h"
45 #include "content/public/browser/render_frame_host.h"
46 #include "content/public/browser/render_process_host.h"
47 #include "content/public/browser/render_widget_host_view.h"
48 #include "content/public/browser/site_isolation_policy.h"
49 #include "content/public/browser/storage_partition.h"
50 #include "content/public/browser/web_contents_observer.h"
51 #include "content/public/common/content_features.h"
52 #include "content/public/common/content_switches.h"
53 #include "content/public/common/url_constants.h"
54 #include "content/public/test/browser_test.h"
55 #include "content/public/test/browser_test_utils.h"
56 #include "content/public/test/download_test_observer.h"
57 #include "content/public/test/navigation_handle_observer.h"
58 #include "content/public/test/test_navigation_observer.h"
59 #include "content/public/test/url_loader_interceptor.h"
60 #include "extensions/test/extension_test_message_listener.h"
61 #include "extensions/test/test_extension_dir.h"
62 #include "google_apis/gaia/gaia_switches.h"
63 #include "net/dns/mock_host_resolver.h"
64 #include "services/metrics/public/cpp/ukm_builders.h"
65 #include "services/network/public/cpp/features.h"
66 #include "testing/gmock/include/gmock/gmock.h"
67 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
69 using ::testing::IsEmpty;
70 using ::testing::UnorderedElementsAre;
72 class ChromeNavigationBrowserTest : public InProcessBrowserTest {
74 ChromeNavigationBrowserTest() {
75 scoped_feature_list_.InitAndEnableFeature(ukm::kUkmFeature);
77 ~ChromeNavigationBrowserTest() override {}
79 void SetUpCommandLine(base::CommandLine* command_line) override {
80 // Backgrounded renderer processes run at a lower priority, causing the
81 // tests to take more time to complete. Disable backgrounding so that the
82 // tests don't time out.
83 command_line->AppendSwitch(switches::kDisableRendererBackgrounding);
85 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
86 ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
89 void SetUpOnMainThread() override {
90 host_resolver()->AddRule("*", "127.0.0.1");
91 embedded_test_server()->StartAcceptingConnections();
94 void PreRunTestOnMainThread() override {
95 InProcessBrowserTest::PreRunTestOnMainThread();
96 test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
99 ukm::TestAutoSetUkmRecorder* test_ukm_recorder() {
100 return test_ukm_recorder_.get();
104 std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
105 base::test::ScopedFeatureList scoped_feature_list_;
107 DISALLOW_COPY_AND_ASSIGN(ChromeNavigationBrowserTest);
110 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
111 // Fails on chromium.memory/Linux Chromium OS ASan LSan:
112 // https://crbug.com/897879
113 #define MAYBE_TransientEntryPreservedOnMultipleNavigationsDuringInterstitial \
114 DISABLED_TransientEntryPreservedOnMultipleNavigationsDuringInterstitial
116 #define MAYBE_TransientEntryPreservedOnMultipleNavigationsDuringInterstitial \
117 TransientEntryPreservedOnMultipleNavigationsDuringInterstitial
120 // Tests that viewing frame source on a local file:// page with an iframe
121 // with a remote URL shows the correct tab title.
122 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, TestViewFrameSource) {
123 // The local page file:// URL.
124 GURL local_page_with_iframe_url = ui_test_utils::GetTestUrl(
125 base::FilePath(base::FilePath::kCurrentDirectory),
126 base::FilePath(FILE_PATH_LITERAL("iframe.html")));
128 // The non-file:// URL of the page to load in the iframe.
129 GURL iframe_target_url = embedded_test_server()->GetURL("/title1.html");
130 ui_test_utils::NavigateToURL(browser(), local_page_with_iframe_url);
131 content::WebContents* web_contents =
132 browser()->tab_strip_model()->GetActiveWebContents();
134 content::TestNavigationObserver observer(web_contents);
135 ASSERT_TRUE(content::ExecuteScript(
136 web_contents->GetMainFrame(),
137 base::StringPrintf("var iframe = document.getElementById('test');\n"
138 "iframe.setAttribute('src', '%s');\n",
139 iframe_target_url.spec().c_str())));
142 content::RenderFrameHost* frame =
143 content::ChildFrameAt(web_contents->GetMainFrame(), 0);
145 ASSERT_NE(frame, web_contents->GetMainFrame());
147 content::ContextMenuParams params;
148 params.page_url = local_page_with_iframe_url;
149 params.frame_url = frame->GetLastCommittedURL();
150 TestRenderViewContextMenu menu(frame, params);
152 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE, 0);
153 ASSERT_EQ(browser()->tab_strip_model()->count(), 2);
154 content::WebContents* new_web_contents =
155 browser()->tab_strip_model()->GetWebContentsAt(1);
156 ASSERT_NE(new_web_contents, web_contents);
157 EXPECT_TRUE(WaitForLoadStop(new_web_contents));
159 GURL view_frame_source_url(content::kViewSourceScheme + std::string(":") +
160 iframe_target_url.spec());
161 EXPECT_EQ(url_formatter::FormatUrl(view_frame_source_url),
162 new_web_contents->GetTitle());
165 // Base class for ctrl+click tests, which contains all the common functionality
166 // independent from which process the navigation happens in. Each subclass
167 // defines its own expectations depending on the conditions of the test.
168 class CtrlClickProcessTest : public ChromeNavigationBrowserTest {
170 virtual void VerifyProcessExpectations(
171 content::WebContents* main_contents,
172 content::WebContents* new_contents) = 0;
174 // Simulates ctrl-clicking an anchor with the given id in |main_contents|.
175 // Verifies that the new contents are in the correct process and separate
176 // BrowsingInstance from |main_contents|. Returns contents of the newly
178 content::WebContents* SimulateCtrlClick(content::WebContents* main_contents,
179 const char* id_of_anchor_to_click) {
180 // Ctrl-click the anchor/link in the page.
181 content::WebContents* new_contents = nullptr;
183 content::WebContentsAddedObserver new_tab_observer;
184 #if defined(OS_MACOSX)
185 const char* new_tab_click_script_template =
186 "simulateClick(\"%s\", { metaKey: true });";
188 const char* new_tab_click_script_template =
189 "simulateClick(\"%s\", { ctrlKey: true });";
191 std::string new_tab_click_script = base::StringPrintf(
192 new_tab_click_script_template, id_of_anchor_to_click);
193 EXPECT_TRUE(ExecuteScript(main_contents, new_tab_click_script));
195 // Wait for a new tab to appear (the whole point of this test).
196 new_contents = new_tab_observer.GetWebContents();
199 // Verify that the new tab has the right contents and is in the tab strip.
200 EXPECT_TRUE(WaitForLoadStop(new_contents));
201 EXPECT_LT(1, browser()->tab_strip_model()->count()); // More than 1 tab?
203 TabStripModel::kNoTab,
204 browser()->tab_strip_model()->GetIndexOfWebContents(new_contents));
205 GURL expected_url(embedded_test_server()->GetURL("/title1.html"));
206 EXPECT_EQ(expected_url, new_contents->GetLastCommittedURL());
208 VerifyProcessExpectations(main_contents, new_contents);
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);
219 // Verify that the new contents doesn't have a window.opener set.
220 bool window_opener_cast_to_bool = true;
221 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);
226 VerifyBrowsingInstanceExpectations(main_contents, new_contents);
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);
238 // Verify that there is only 1 active tab (with the right contents
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());
245 // Test what happens after ctrl-click. SimulateCtrlClick will verify
246 // that |new_contents1| is in the correct process and separate
247 // BrowsingInstance from |main_contents|.
248 content::WebContents* new_contents1 =
249 SimulateCtrlClick(main_contents, id_of_anchor_to_click);
251 // Test that each subsequent ctrl-click also gets the correct process.
252 content::WebContents* new_contents2 =
253 SimulateCtrlClick(main_contents, id_of_anchor_to_click);
254 EXPECT_FALSE(new_contents1->GetSiteInstance()->IsRelatedSiteInstance(
255 new_contents2->GetSiteInstance()));
256 VerifyProcessExpectations(new_contents1, new_contents2);
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(
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);
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).
278 class CtrlClickShouldEndUpInNewProcessTest : public CtrlClickProcessTest {
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()));
293 IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, NoTarget) {
294 TestCtrlClick("test-anchor-no-target");
297 IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, BlankTarget) {
298 TestCtrlClick("test-anchor-with-blank-target");
301 IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInNewProcessTest, SubframeTarget) {
302 TestCtrlClick("test-anchor-with-subframe-target");
305 // 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.
308 class CtrlClickShouldEndUpInSameProcessTest : public CtrlClickProcessTest {
310 void SetUpCommandLine(base::CommandLine* command_line) override {
311 CtrlClickProcessTest::SetUpCommandLine(command_line);
312 content::IsolateAllSitesForTesting(command_line);
313 content::RenderProcessHost::SetMaxRendererProcessCount(1);
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()));
330 IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, NoTarget) {
331 TestCtrlClick("test-anchor-no-target");
334 IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, BlankTarget) {
335 TestCtrlClick("test-anchor-with-blank-target");
338 IN_PROC_BROWSER_TEST_F(CtrlClickShouldEndUpInSameProcessTest, SubframeTarget) {
339 TestCtrlClick("test-anchor-with-subframe-target");
342 class ChromeNavigationPortMappedBrowserTest : public InProcessBrowserTest {
344 ChromeNavigationPortMappedBrowserTest() {}
345 ~ChromeNavigationPortMappedBrowserTest() override {}
347 void SetUpCommandLine(base::CommandLine* command_line) override {
348 ASSERT_TRUE(embedded_test_server()->Start());
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
355 base::NumberToString(embedded_test_server()->host_port_pair().port());
356 command_line->AppendSwitchASCII(
357 "host-resolver-rules",
358 "MAP * 127.0.0.1:" + port + ", EXCLUDE 127.0.0.1*");
362 DISALLOW_COPY_AND_ASSIGN(ChromeNavigationPortMappedBrowserTest);
365 // Test to verify that spoofing a URL via a redirect from a slightly malformed
366 // URL doesn't work. See also https://crbug.com/657720.
367 IN_PROC_BROWSER_TEST_F(ChromeNavigationPortMappedBrowserTest,
368 ContextMenuNavigationToInvalidUrl) {
369 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
371 "www.foo.com::/server-redirect?http%3A%2F%2Fbar.com%2Ftitle2.html");
373 // Navigate to an initial page, to ensure we have a committed document
374 // from which to perform a context menu initiated navigation.
375 ui_test_utils::NavigateToURL(browser(), initial_url);
376 content::WebContents* web_contents =
377 browser()->tab_strip_model()->GetActiveWebContents();
379 // This corresponds to "Open link in new tab".
380 content::ContextMenuParams params;
381 params.is_editable = false;
382 params.media_type = blink::ContextMenuDataMediaType::kNone;
383 params.page_url = initial_url;
384 params.link_url = new_tab_url;
386 ui_test_utils::TabAddedWaiter tab_add(browser());
388 TestRenderViewContextMenu menu(web_contents->GetMainFrame(), params);
390 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, 0);
392 // Wait for the new tab to be created and for loading to stop.
394 int index_of_new_tab = browser()->tab_strip_model()->count() - 1;
395 content::WebContents* new_web_contents =
396 browser()->tab_strip_model()->GetWebContentsAt(index_of_new_tab);
397 EXPECT_TRUE(WaitForLoadStop(new_web_contents));
399 // Verify that the final URL after the redirects gets committed.
400 EXPECT_EQ(GURL("http://bar.com/title2.html"),
401 new_web_contents->GetLastCommittedURL());
404 // Ensure that a failed navigation in a new tab will not leave an invalid
405 // visible URL, which may be formatted in an unsafe way in the omnibox.
406 // See https://crbug.com/850824.
407 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
408 ClearInvalidPendingURLOnFail) {
409 GURL initial_url = embedded_test_server()->GetURL(
410 "/frame_tree/invalid_link_to_new_window.html");
412 // Navigate to a page with a link that opens an invalid URL in a new window.
413 ui_test_utils::NavigateToURL(browser(), initial_url);
414 content::WebContents* main_contents =
415 browser()->tab_strip_model()->GetActiveWebContents();
417 // Simulate a click on the link and wait for the new window.
418 content::WebContentsAddedObserver new_tab_observer;
419 EXPECT_TRUE(ExecuteScript(main_contents, "simulateClick()"));
420 content::WebContents* new_contents = new_tab_observer.GetWebContents();
422 // The load in the new window should fail.
423 EXPECT_FALSE(WaitForLoadStop(new_contents));
425 // Ensure that there is no pending entry or visible URL.
426 EXPECT_EQ(nullptr, new_contents->GetController().GetPendingEntry());
427 EXPECT_EQ(GURL(), new_contents->GetVisibleURL());
430 // A test performing two simultaneous navigations, to ensure code in chrome/,
431 // such as tab helpers, can handle those cases.
432 // This test starts a browser-initiated cross-process navigation, which is
433 // delayed. At the same time, the renderer does a synchronous navigation
434 // through pushState, which will create a separate navigation and associated
435 // NavigationHandle. Afterwards, the original cross-process navigation is
436 // resumed and confirmed to properly commit.
437 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
438 SlowCrossProcessNavigationWithPushState) {
439 const GURL kURL1 = embedded_test_server()->GetURL("/title1.html");
440 const GURL kPushStateURL =
441 embedded_test_server()->GetURL("/title1.html#fragment");
442 const GURL kURL2 = embedded_test_server()->GetURL("/title2.html");
444 content::WebContents* web_contents =
445 browser()->tab_strip_model()->GetActiveWebContents();
447 // Navigate to the initial page.
448 ui_test_utils::NavigateToURL(browser(), kURL1);
450 // Start navigating to the second page.
451 content::TestNavigationManager manager(web_contents, kURL2);
452 content::NavigationHandleCommitObserver navigation_observer(web_contents,
454 web_contents->GetController().LoadURL(
455 kURL2, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
456 EXPECT_TRUE(manager.WaitForRequestStart());
458 // The current page does a PushState.
459 content::NavigationHandleCommitObserver push_state_observer(web_contents,
461 std::string push_state =
462 "history.pushState({}, \"title 1\", \"" + kPushStateURL.spec() + "\");";
463 EXPECT_TRUE(ExecuteScript(web_contents, push_state));
464 content::NavigationEntry* last_committed =
465 web_contents->GetController().GetLastCommittedEntry();
466 EXPECT_TRUE(last_committed);
467 EXPECT_EQ(kPushStateURL, last_committed->GetURL());
469 EXPECT_TRUE(push_state_observer.has_committed());
470 EXPECT_TRUE(push_state_observer.was_same_document());
471 EXPECT_TRUE(push_state_observer.was_renderer_initiated());
473 // Let the navigation finish. It should commit successfully.
474 manager.WaitForNavigationFinished();
475 last_committed = web_contents->GetController().GetLastCommittedEntry();
476 EXPECT_TRUE(last_committed);
477 EXPECT_EQ(kURL2, last_committed->GetURL());
479 EXPECT_TRUE(navigation_observer.has_committed());
480 EXPECT_FALSE(navigation_observer.was_same_document());
481 EXPECT_FALSE(navigation_observer.was_renderer_initiated());
484 // Check that if a page has an iframe that loads an error page, that error page
485 // does not inherit the Content Security Policy from the parent frame. See
486 // https://crbug.com/703801. This test is in chrome/ because error page
487 // behavior is only fully defined in chrome/.
488 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
489 ErrorPageDoesNotInheritCSP) {
491 embedded_test_server()->GetURL("/page_with_csp_and_error_iframe.html"));
492 content::WebContents* web_contents =
493 browser()->tab_strip_model()->GetActiveWebContents();
495 // Navigate to a page that disallows scripts via CSP and has an iframe that
496 // tries to load an invalid URL, which results in an error page.
497 GURL error_url("http://invalid.foo/");
498 content::NavigationHandleObserver observer(web_contents, error_url);
499 ui_test_utils::NavigateToURL(browser(), url);
500 EXPECT_TRUE(observer.has_committed());
501 EXPECT_TRUE(observer.is_error());
503 // The error page should not inherit the CSP directive that blocks all
504 // scripts from the parent frame, so this script should be allowed to
505 // execute. Since ExecuteScript will execute the passed-in script regardless
506 // of CSP, use a javascript: URL which does go through the CSP checks.
507 content::RenderFrameHost* error_host =
508 ChildFrameAt(web_contents->GetMainFrame(), 0);
509 std::string location;
510 EXPECT_TRUE(ExecuteScriptAndExtractString(
512 "location='javascript:domAutomationController.send(location.href)';",
514 EXPECT_EQ(location, content::kUnreachableWebDataURL);
516 // The error page should have a unique origin.
518 EXPECT_TRUE(ExecuteScriptAndExtractString(
519 error_host, "domAutomationController.send(self.origin);", &origin));
520 EXPECT_EQ("null", origin);
523 // Test that web pages can't navigate to an error page URL, either directly or
524 // via a redirect, and that web pages can't embed error pages in iframes.
525 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
526 NavigationToErrorURLIsDisallowed) {
527 content::WebContents* web_contents =
528 browser()->tab_strip_model()->GetActiveWebContents();
529 GURL url(embedded_test_server()->GetURL("/title1.html"));
530 ui_test_utils::NavigateToURL(browser(), url);
531 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
533 // Try navigating to the error page URL and make sure it is canceled and the
534 // old URL remains the last committed one.
535 GURL error_url(content::kUnreachableWebDataURL);
536 EXPECT_TRUE(ExecuteScript(web_contents,
537 "location.href = '" + error_url.spec() + "';"));
538 EXPECT_TRUE(content::WaitForLoadStop(web_contents));
539 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
541 // Also ensure that a page can't embed an iframe for an error page URL.
542 EXPECT_TRUE(ExecuteScript(web_contents,
543 "var frame = document.createElement('iframe');\n"
544 "frame.src = '" + error_url.spec() + "';\n"
545 "document.body.appendChild(frame);"));
546 EXPECT_TRUE(content::WaitForLoadStop(web_contents));
547 content::RenderFrameHost* subframe_host =
548 ChildFrameAt(web_contents->GetMainFrame(), 0);
549 // The new subframe should remain blank without a committed URL.
550 EXPECT_TRUE(subframe_host->GetLastCommittedURL().is_empty());
552 // Now try navigating to a URL that tries to redirect to the error page URL
553 // and make sure the navigation is ignored. Note that DidStopLoading will
554 // still fire, so TestNavigationObserver can be used to wait for it.
555 GURL redirect_to_error_url(
556 embedded_test_server()->GetURL("/server-redirect?" + error_url.spec()));
557 content::TestNavigationObserver observer(web_contents);
558 EXPECT_TRUE(ExecuteScript(
559 web_contents, "location.href = '" + redirect_to_error_url.spec() + "';"));
561 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
563 content::PAGE_TYPE_NORMAL,
564 web_contents->GetController().GetLastCommittedEntry()->GetPageType());
565 // Check the pending URL is not left in the address bar.
566 EXPECT_EQ(url, web_contents->GetVisibleURL());
569 // This test ensures that navigating to a page that returns an error code and
570 // an empty document still shows Chrome's helpful error page instead of the
572 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
573 EmptyDocumentWithErrorCode) {
574 GURL url(embedded_test_server()->GetURL("/empty_with_404.html"));
575 content::WebContents* web_contents =
576 browser()->tab_strip_model()->GetActiveWebContents();
578 // Wait for the navigation to complete. The empty document should trigger
579 // loading of the 404 error page, so check that the last committed entry was
580 // indeed for the error page.
581 content::TestNavigationObserver observer(web_contents);
583 ExecuteScript(web_contents, "location.href = '" + url.spec() + "';"));
585 EXPECT_FALSE(observer.last_navigation_succeeded());
586 EXPECT_EQ(url, web_contents->GetLastCommittedURL());
588 IsLastCommittedEntryOfPageType(web_contents, content::PAGE_TYPE_ERROR));
590 // Verify that the error page has correct content. This needs to wait for
591 // the error page content to be populated asynchronously by scripts after
595 EXPECT_TRUE(ExecuteScriptAndExtractString(
597 "domAutomationController.send("
598 " document.body ? document.body.innerText : '');",
600 if (content.find("HTTP ERROR 404") != std::string::npos)
602 base::RunLoop run_loop;
603 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
604 FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
609 // Test for https://crbug.com/866549#c2. It verifies that about:blank does not
610 // commit in the error page process when it is redirected to.
611 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
612 RedirectErrorPageReloadToAboutBlank) {
613 content::WebContents* web_contents =
614 browser()->tab_strip_model()->GetActiveWebContents();
615 GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
616 std::unique_ptr<content::URLLoaderInterceptor> url_interceptor =
617 content::URLLoaderInterceptor::SetupRequestFailForURL(
618 url, net::ERR_DNS_TIMED_OUT);
620 // Start off with navigation to a.com, which results in an error page.
622 content::TestNavigationObserver observer(web_contents);
623 ui_test_utils::NavigateToURL(browser(), url);
624 EXPECT_FALSE(observer.last_navigation_succeeded());
625 EXPECT_EQ(url, observer.last_navigation_url());
626 EXPECT_EQ(GURL(content::kUnreachableWebDataURL),
627 web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
630 // Install an extension, which will redirect all navigations to a.com URLs to
631 // about:blank. In general, web servers cannot redirect to about:blank, but
632 // extensions with webRequest API permissions can.
633 extensions::TestExtensionDir test_extension_dir;
634 test_extension_dir.WriteManifest(
636 "name": "Redirect a.com to about:blank",
637 "manifest_version": 2,
639 "permissions": ["webRequest", "webRequestBlocking", "*://a.com/*"],
640 "background": { "scripts": ["background.js"] }
642 test_extension_dir.WriteFile(
643 FILE_PATH_LITERAL("background.js"),
644 R"(chrome.webRequest.onBeforeRequest.addListener(function(d) {
645 console.log("onBeforeRequest: ", d);
646 return {redirectUrl:"about:blank"};
647 }, {urls: ["*://a.com/*"]}, ["blocking"]);
648 chrome.test.sendMessage('ready');
651 ExtensionTestMessageListener ready_listener("ready", false /* will_reply */);
652 extensions::ChromeTestExtensionLoader extension_loader(browser()->profile());
653 extension_loader.LoadExtension(test_extension_dir.UnpackedPath());
655 // Wait for the background page to load.
656 ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
658 // Remove the interceptor to allow a reload to succeed, which the extension
659 // will intercept and redirect. The navigation should complete successfully
660 // and commit in a process that is different than the error page one.
661 url_interceptor.reset();
663 content::TestNavigationObserver observer(web_contents);
664 EXPECT_TRUE(ExecuteScript(web_contents, "location.reload();"));
666 EXPECT_TRUE(observer.last_navigation_succeeded());
667 EXPECT_EQ(GURL(url::kAboutBlankURL), observer.last_navigation_url());
668 EXPECT_NE(GURL(content::kUnreachableWebDataURL),
669 web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL());
673 // This test covers a navigation that:
674 // 1. is initiated by a cross-site initiator,
675 // 2. gets redirected via webRequest API to about:blank.
676 // This is a regression test for https://crbug.com/1026738.
677 IN_PROC_BROWSER_TEST_F(
678 ChromeNavigationBrowserTest,
679 NavigationInitiatedByCrossSiteSubframeRedirectedToAboutBlank) {
680 const GURL kOpenerUrl(
681 embedded_test_server()->GetURL("opener.com", "/title1.html"));
682 const GURL kInitialPopupUrl(embedded_test_server()->GetURL(
684 "/frame_tree/page_with_two_frames_remote_and_local.html"));
685 const GURL kRedirectedUrl("https://redirected.com/no-such-path");
687 // 1. Install an extension, which will redirect all navigations to
688 // redirected.com URLs to about:blank. In general, web servers cannot
689 // redirect to about:blank, but extensions with declarativeWebRequest API
691 const char kManifest[] = R"(
693 "name": "Test for Bug1026738 - about:blank flavour",
695 "manifest_version": 2,
697 "scripts": ["background.js"]
699 "permissions": ["webRequest", "webRequestBlocking", "<all_urls>"]
702 const char kRulesScript[] = R"(
703 chrome.webRequest.onBeforeRequest.addListener(function(d) {
704 console.log("onBeforeRequest: ", d);
705 return {redirectUrl: "about:blank"};
706 }, {urls: ["*://redirected.com/*"]}, ["blocking"]);
707 chrome.test.sendMessage('ready');
709 extensions::TestExtensionDir ext_dir;
710 ext_dir.WriteManifest(kManifest);
711 ext_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kRulesScript);
712 ExtensionTestMessageListener ready_listener("ready", false /* will_reply */);
713 extensions::ChromeTestExtensionLoader extension_loader(browser()->profile());
714 scoped_refptr<const extensions::Extension> extension =
715 extension_loader.LoadExtension(ext_dir.UnpackedPath());
716 ASSERT_TRUE(extension);
717 ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
718 content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
719 ->FlushNetworkInterfaceForTesting();
721 // 2. Open a popup containing a cross-site subframe.
722 ui_test_utils::NavigateToURL(browser(), kOpenerUrl);
723 content::RenderFrameHost* opener =
724 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
725 EXPECT_EQ(kOpenerUrl, opener->GetLastCommittedURL());
726 EXPECT_EQ(url::Origin::Create(kOpenerUrl), opener->GetLastCommittedOrigin());
727 content::WebContents* popup = nullptr;
729 content::WebContentsAddedObserver popup_observer;
730 ASSERT_TRUE(content::ExecJs(
732 content::JsReplace("window.open($1, 'my-popup')", kInitialPopupUrl)));
733 popup = popup_observer.GetWebContents();
734 EXPECT_TRUE(WaitForLoadStop(popup));
737 // 3. Find the cross-site subframes in the popup.
738 content::RenderFrameHost* popup_root = popup->GetMainFrame();
739 content::RenderFrameHost* cross_site_subframe =
740 content::ChildFrameAt(popup_root, 0);
741 ASSERT_TRUE(cross_site_subframe);
742 EXPECT_NE(cross_site_subframe->GetLastCommittedOrigin(),
743 popup_root->GetLastCommittedOrigin());
744 EXPECT_NE(cross_site_subframe->GetLastCommittedOrigin(),
745 opener->GetLastCommittedOrigin());
746 if (content::AreAllSitesIsolatedForTesting()) {
747 EXPECT_NE(cross_site_subframe->GetSiteInstance(),
748 popup_root->GetSiteInstance());
749 EXPECT_NE(cross_site_subframe->GetSiteInstance(),
750 opener->GetSiteInstance());
752 scoped_refptr<content::SiteInstance> old_popup_site_instance =
753 popup_root->GetSiteInstance();
754 scoped_refptr<content::SiteInstance> old_subframe_site_instance =
755 cross_site_subframe->GetSiteInstance();
757 // 4. Initiate popup navigation from the cross-site subframe.
758 // Note that the extension from step 1 above will redirect
759 // this navigation to an about:blank URL.
761 // This step would have hit the CHECK from https://crbug.com/1026738.
762 content::TestNavigationObserver nav_observer(popup, 1);
763 ASSERT_TRUE(ExecJs(cross_site_subframe,
764 content::JsReplace("top.location = $1", kRedirectedUrl)));
766 EXPECT_EQ(url::kAboutBlankURL, popup->GetLastCommittedURL());
768 // 5. Verify that the about:blank URL is hosted in the same process
769 // as the navigation initiator (and separate from the opener and the old
771 if (content::AreAllSitesIsolatedForTesting()) {
772 EXPECT_NE(opener->GetSiteInstance(), popup->GetSiteInstance());
773 EXPECT_NE(old_popup_site_instance.get(), popup->GetSiteInstance());
774 EXPECT_EQ(old_subframe_site_instance.get(), popup->GetSiteInstance());
775 EXPECT_NE(url::kAboutBlankURL,
776 popup->GetSiteInstance()->GetSiteURL().scheme());
777 EXPECT_NE(url::kDataScheme,
778 popup->GetSiteInstance()->GetSiteURL().scheme());
780 EXPECT_EQ(opener->GetSiteInstance(), popup->GetSiteInstance());
781 EXPECT_EQ(old_popup_site_instance.get(), popup->GetSiteInstance());
782 EXPECT_EQ(old_subframe_site_instance.get(), popup->GetSiteInstance());
783 EXPECT_NE(url::kAboutBlankURL,
784 popup->GetSiteInstance()->GetSiteURL().scheme());
785 EXPECT_NE(url::kDataScheme,
786 popup->GetSiteInstance()->GetSiteURL().scheme());
789 // 6. Verify the origin of the about:blank URL in the popup.
791 // Blink calculates the origin of an about:blank frame based on the
792 // opener-or-parent (rather than based on the navigation initiator's origin
793 // as required by the spec).
794 // TODO(lukasza): https://crbug.com/585649: Once Blink is fixed, adjust test
795 // expectations below to make sure the initiator's origin has been committed.
796 // Consider also adding verification that the about:blank page can be scripted
797 // by other frames with the initiator's origin.
798 if (content::AreAllSitesIsolatedForTesting()) {
799 // If the opener is a blink::RemoteFrame, then Blink uses an opaque origin.
800 EXPECT_TRUE(popup->GetMainFrame()->GetLastCommittedOrigin().opaque());
802 EXPECT_EQ(url::Origin::Create(kOpenerUrl),
803 popup->GetMainFrame()->GetLastCommittedOrigin());
807 // This test covers a navigation that:
808 // 1. is initiated by a cross-site initiator,
809 // 2. gets redirected via webRequest API to a data: URL
810 // This covers a scenario similar to the one that led to crashes in
811 // https://crbug.com/1026738.
812 IN_PROC_BROWSER_TEST_F(
813 ChromeNavigationBrowserTest,
814 NavigationInitiatedByCrossSiteSubframeRedirectedToDataUrl) {
815 const GURL kOpenerUrl(
816 embedded_test_server()->GetURL("opener.com", "/title1.html"));
817 const GURL kInitialPopupUrl(embedded_test_server()->GetURL(
819 "/frame_tree/page_with_two_frames_remote_and_local.html"));
820 const GURL kRedirectedUrl("https://redirected.com/no-such-path");
821 const GURL kRedirectTargetUrl(
822 "data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E");
824 // 1. Install an extension, which will redirect all navigations to
825 // redirected.com URLs to a data: URL. In general, web servers cannot
826 // redirect to data: URLs, but extensions with declarativeWebRequest API
828 const char kManifest[] = R"(
830 "name": "Test for Bug1026738 - data: URL flavour",
832 "manifest_version": 2,
834 "scripts": ["background.js"]
836 "permissions": ["webRequest", "webRequestBlocking", "<all_urls>"]
839 const char kRulesScriptTemplate[] = R"(
840 chrome.webRequest.onBeforeRequest.addListener(function(d) {
841 console.log("onBeforeRequest: ", d);
842 return {redirectUrl: $1};
843 }, {urls: ["*://redirected.com/*"]}, ["blocking"]);
844 chrome.test.sendMessage('ready');
846 extensions::TestExtensionDir ext_dir;
847 ext_dir.WriteManifest(kManifest);
849 FILE_PATH_LITERAL("background.js"),
850 content::JsReplace(kRulesScriptTemplate, kRedirectTargetUrl));
851 ExtensionTestMessageListener ready_listener("ready", false /* will_reply */);
852 extensions::ChromeTestExtensionLoader extension_loader(browser()->profile());
853 scoped_refptr<const extensions::Extension> extension =
854 extension_loader.LoadExtension(ext_dir.UnpackedPath());
855 ASSERT_TRUE(extension);
856 ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
857 content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
858 ->FlushNetworkInterfaceForTesting();
860 // 2. Open a popup containing a cross-site subframe.
861 ui_test_utils::NavigateToURL(browser(), kOpenerUrl);
862 content::RenderFrameHost* opener =
863 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
864 EXPECT_EQ(kOpenerUrl, opener->GetLastCommittedURL());
865 EXPECT_EQ(url::Origin::Create(kOpenerUrl), opener->GetLastCommittedOrigin());
866 content::WebContents* popup = nullptr;
868 content::WebContentsAddedObserver popup_observer;
869 ASSERT_TRUE(content::ExecJs(
871 content::JsReplace("window.open($1, 'my-popup')", kInitialPopupUrl)));
872 popup = popup_observer.GetWebContents();
873 EXPECT_TRUE(WaitForLoadStop(popup));
876 // 3. Find the cross-site subframes in the popup.
877 EXPECT_EQ(3u, popup->GetAllFrames().size());
878 content::RenderFrameHost* popup_root = popup->GetMainFrame();
879 content::RenderFrameHost* cross_site_subframe = popup->GetAllFrames()[1];
880 EXPECT_NE(cross_site_subframe->GetLastCommittedOrigin(),
881 popup_root->GetLastCommittedOrigin());
882 EXPECT_NE(cross_site_subframe->GetLastCommittedOrigin(),
883 opener->GetLastCommittedOrigin());
884 if (content::AreAllSitesIsolatedForTesting()) {
885 EXPECT_NE(cross_site_subframe->GetSiteInstance(),
886 popup_root->GetSiteInstance());
887 EXPECT_NE(cross_site_subframe->GetSiteInstance(),
888 opener->GetSiteInstance());
890 scoped_refptr<content::SiteInstance> old_popup_site_instance =
891 popup_root->GetSiteInstance();
893 // 4. Initiate popup navigation from the cross-site subframe.
894 // Note that the extension from step 1 above will redirect
895 // this navigation to a data: URL.
897 // This step might hit the CHECK in GetOriginForURLLoaderFactory once we start
898 // enforcing opaque origins with no precursor in CanAccessDataForOrigin.
899 content::TestNavigationObserver nav_observer(popup, 1);
900 ASSERT_TRUE(ExecJs(cross_site_subframe,
901 content::JsReplace("top.location = $1", kRedirectedUrl)));
903 EXPECT_EQ(kRedirectTargetUrl, popup->GetLastCommittedURL());
904 EXPECT_TRUE(popup->GetMainFrame()->GetLastCommittedOrigin().opaque());
906 // 5. Verify that with site-per-process the data: URL is hosted in a brand
907 // new, separate process (separate from the opener and the previous popup
909 if (content::AreAllSitesIsolatedForTesting()) {
910 EXPECT_NE(opener->GetSiteInstance(), popup->GetSiteInstance());
911 EXPECT_NE(old_popup_site_instance.get(), popup->GetSiteInstance());
912 EXPECT_EQ(url::kDataScheme,
913 popup->GetSiteInstance()->GetSiteURL().scheme());
915 EXPECT_EQ(opener->GetSiteInstance(), popup->GetSiteInstance());
916 EXPECT_EQ(old_popup_site_instance.get(), popup->GetSiteInstance());
917 EXPECT_NE(url::kDataScheme,
918 popup->GetSiteInstance()->GetSiteURL().scheme());
922 class SignInIsolationBrowserTest : public ChromeNavigationBrowserTest {
924 SignInIsolationBrowserTest()
925 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
926 ~SignInIsolationBrowserTest() override {}
928 void SetUp() override {
929 https_server_.ServeFilesFromSourceDirectory("chrome/test/data");
930 ASSERT_TRUE(https_server_.InitializeAndListen());
931 ChromeNavigationBrowserTest::SetUp();
934 void SetUpCommandLine(base::CommandLine* command_line) override {
935 // Override the sign-in URL so that it includes correct port from the test
937 command_line->AppendSwitchASCII(
938 ::switches::kGaiaUrl,
939 https_server()->GetURL("accounts.google.com", "/").spec());
941 // Ignore cert errors so that the sign-in URL can be loaded from a site
942 // other than localhost (the EmbeddedTestServer serves a certificate that
943 // is valid for localhost).
944 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
946 ChromeNavigationBrowserTest::SetUpCommandLine(command_line);
949 void SetUpOnMainThread() override {
950 https_server_.StartAcceptingConnections();
951 ChromeNavigationBrowserTest::SetUpOnMainThread();
954 net::EmbeddedTestServer* https_server() { return &https_server_; }
957 net::EmbeddedTestServer https_server_;
959 DISALLOW_COPY_AND_ASSIGN(SignInIsolationBrowserTest);
962 // This test ensures that the sign-in origin requires a dedicated process. It
963 // only ensures that the sign-in origin is added as an isolated origin at
964 // chrome/ layer; IsolatedOriginTest provides the main test coverage of origins
965 // whitelisted for process isolation. See https://crbug.com/739418.
966 IN_PROC_BROWSER_TEST_F(SignInIsolationBrowserTest, NavigateToSignInPage) {
967 const GURL first_url =
968 embedded_test_server()->GetURL("google.com", "/title1.html");
969 const GURL signin_url =
970 https_server()->GetURL("accounts.google.com", "/title1.html");
971 ui_test_utils::NavigateToURL(browser(), first_url);
972 content::WebContents* web_contents =
973 browser()->tab_strip_model()->GetActiveWebContents();
974 scoped_refptr<content::SiteInstance> first_instance(
975 web_contents->GetMainFrame()->GetSiteInstance());
977 // Make sure that a renderer-initiated navigation to the sign-in page swaps
979 content::TestNavigationManager manager(web_contents, signin_url);
981 ExecuteScript(web_contents, "location = '" + signin_url.spec() + "';"));
982 manager.WaitForNavigationFinished();
983 EXPECT_NE(web_contents->GetMainFrame()->GetSiteInstance(), first_instance);
986 class WebstoreIsolationBrowserTest : public ChromeNavigationBrowserTest {
988 WebstoreIsolationBrowserTest()
989 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
990 ~WebstoreIsolationBrowserTest() override {}
992 void SetUp() override {
993 https_server_.ServeFilesFromSourceDirectory("chrome/test/data");
994 ASSERT_TRUE(https_server_.InitializeAndListen());
995 ChromeNavigationBrowserTest::SetUp();
998 void SetUpCommandLine(base::CommandLine* command_line) override {
999 // Override the webstore URL.
1000 command_line->AppendSwitchASCII(
1001 ::switches::kAppsGalleryURL,
1002 https_server()->GetURL("chrome.foo.com", "/frame_tree").spec());
1004 // Ignore cert errors so that the webstore URL can be loaded from a site
1005 // other than localhost (the EmbeddedTestServer serves a certificate that
1006 // is valid for localhost).
1007 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
1009 ChromeNavigationBrowserTest::SetUpCommandLine(command_line);
1012 void SetUpOnMainThread() override {
1013 https_server_.StartAcceptingConnections();
1014 ChromeNavigationBrowserTest::SetUpOnMainThread();
1017 net::EmbeddedTestServer* https_server() { return &https_server_; }
1020 net::EmbeddedTestServer https_server_;
1022 DISALLOW_COPY_AND_ASSIGN(WebstoreIsolationBrowserTest);
1025 // Make sure that Chrome Web Store origins are isolated from the rest of their
1026 // foo.com site. See https://crbug.com/939108.
1027 IN_PROC_BROWSER_TEST_F(WebstoreIsolationBrowserTest, WebstorePopupIsIsolated) {
1028 const GURL first_url = https_server()->GetURL("foo.com", "/title1.html");
1029 ui_test_utils::NavigateToURL(browser(), first_url);
1030 content::WebContents* web_contents =
1031 browser()->tab_strip_model()->GetActiveWebContents();
1033 // Open a popup for chrome.foo.com and ensure that it's isolated in a
1034 // different SiteInstance and process from the rest of foo.com. Note that
1035 // we're opening a URL that does *not* match the web store URL due to a
1036 // different path, so there will be no BrowsingInstance swap, and window.open
1037 // is still expected to return a valid window reference.
1038 content::TestNavigationObserver popup_waiter(nullptr, 1);
1039 popup_waiter.StartWatchingNewWebContents();
1040 const GURL webstore_origin_url =
1041 https_server()->GetURL("chrome.foo.com", "/title1.html");
1042 EXPECT_TRUE(content::EvalJs(
1044 content::JsReplace("!!window.open($1);", webstore_origin_url))
1046 popup_waiter.Wait();
1047 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1048 content::WebContents* popup =
1049 browser()->tab_strip_model()->GetActiveWebContents();
1050 EXPECT_NE(popup, web_contents);
1051 EXPECT_TRUE(content::WaitForLoadStop(popup));
1053 scoped_refptr<content::SiteInstance> popup_instance(
1054 popup->GetMainFrame()->GetSiteInstance());
1055 EXPECT_NE(web_contents->GetMainFrame()->GetSiteInstance(), popup_instance);
1056 EXPECT_NE(web_contents->GetMainFrame()->GetSiteInstance()->GetProcess(),
1057 popup_instance->GetProcess());
1059 // Also navigate the popup to the full web store URL and confirm that this
1060 // causes a BrowsingInstance swap.
1061 const GURL webstore_url =
1062 https_server()->GetURL("chrome.foo.com", "/frame_tree/simple.htm");
1063 content::TestNavigationManager manager(popup, webstore_url);
1065 ExecuteScript(popup, "location = '" + webstore_url.spec() + "';"));
1066 manager.WaitForNavigationFinished();
1067 EXPECT_NE(popup->GetMainFrame()->GetSiteInstance(), popup_instance);
1068 EXPECT_NE(popup->GetMainFrame()->GetSiteInstance(),
1069 web_contents->GetMainFrame()->GetSiteInstance());
1070 EXPECT_FALSE(popup->GetMainFrame()->GetSiteInstance()->IsRelatedSiteInstance(
1071 popup_instance.get()));
1072 EXPECT_FALSE(popup->GetMainFrame()->GetSiteInstance()->IsRelatedSiteInstance(
1073 web_contents->GetMainFrame()->GetSiteInstance()));
1076 // Helper class. Track one navigation and tell whether a response from the
1077 // server has been received or not. It is useful for discerning navigations
1078 // blocked after or before the request has been sent.
1079 class WillProcessResponseObserver : public content::WebContentsObserver {
1081 explicit WillProcessResponseObserver(content::WebContents* web_contents,
1083 : content::WebContentsObserver(web_contents), url_(url) {}
1084 ~WillProcessResponseObserver() override {}
1086 bool WillProcessResponseCalled() { return will_process_response_called_; }
1090 bool will_process_response_called_ = false;
1092 // Is used to set |will_process_response_called_| to true when
1093 // NavigationThrottle::WillProcessResponse() is called.
1094 class WillProcessResponseObserverThrottle
1095 : public content::NavigationThrottle {
1097 WillProcessResponseObserverThrottle(content::NavigationHandle* handle,
1098 bool* will_process_response_called)
1099 : NavigationThrottle(handle),
1100 will_process_response_called_(will_process_response_called) {}
1102 const char* GetNameForLogging() override {
1103 return "WillProcessResponseObserverThrottle";
1107 bool* will_process_response_called_;
1108 NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
1109 *will_process_response_called_ = true;
1110 return NavigationThrottle::PROCEED;
1114 // WebContentsObserver
1115 void DidStartNavigation(content::NavigationHandle* handle) override {
1116 if (handle->GetURL() == url_) {
1117 handle->RegisterThrottleForTesting(
1118 std::make_unique<WillProcessResponseObserverThrottle>(
1119 handle, &will_process_response_called_));
1124 // In HTTP/HTTPS documents, check that no request with the "ftp:" scheme are
1125 // submitted to load an iframe.
1126 // See https://crbug.com/757809.
1127 // Note: This test couldn't be a content_browsertests, since there would be
1128 // no handler defined for the "ftp" protocol in
1129 // URLRequestJobFactoryImpl::protocol_handler_map_.
1130 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, BlockLegacySubresources) {
1131 net::SpawnedTestServer ftp_server(net::SpawnedTestServer::TYPE_FTP,
1132 GetChromeTestDataDir());
1133 ASSERT_TRUE(ftp_server.Start());
1135 GURL main_url_http(embedded_test_server()->GetURL("/iframe.html"));
1136 GURL iframe_url_http(embedded_test_server()->GetURL("/simple.html"));
1137 GURL iframe_url_ftp(ftp_server.GetURL("simple.html"));
1138 GURL redirect_url(embedded_test_server()->GetURL("/server-redirect?"));
1145 {main_url_http, iframe_url_http, true},
1146 {main_url_http, iframe_url_ftp, false},
1148 for (const auto& test_case : kTestCases) {
1149 // Blocking the request should work, even after a redirect.
1150 for (bool redirect : {false, true}) {
1152 redirect ? GURL(redirect_url.spec() + test_case.iframe_url.spec())
1153 : test_case.iframe_url;
1154 SCOPED_TRACE(::testing::Message()
1156 << "- main_url = " << test_case.main_url << std::endl
1157 << "- iframe_url = " << iframe_url << std::endl);
1159 ui_test_utils::NavigateToURL(browser(), test_case.main_url);
1160 content::WebContents* web_contents =
1161 browser()->tab_strip_model()->GetActiveWebContents();
1162 content::NavigationHandleObserver navigation_handle_observer(web_contents,
1164 WillProcessResponseObserver will_process_response_observer(web_contents,
1166 EXPECT_TRUE(NavigateIframeToURL(web_contents, "test", iframe_url));
1168 if (test_case.allowed) {
1169 EXPECT_TRUE(will_process_response_observer.WillProcessResponseCalled());
1170 EXPECT_FALSE(navigation_handle_observer.is_error());
1171 EXPECT_EQ(test_case.iframe_url,
1172 navigation_handle_observer.last_committed_url());
1175 will_process_response_observer.WillProcessResponseCalled());
1176 EXPECT_TRUE(navigation_handle_observer.is_error());
1177 EXPECT_EQ(net::ERR_ABORTED,
1178 navigation_handle_observer.net_error_code());
1184 // Check that it's possible to navigate to a chrome scheme URL from a crashed
1185 // tab. See https://crbug.com/764641.
1186 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, ChromeSchemeNavFromSadTab) {
1187 // Kill the renderer process.
1188 content::RenderProcessHost* process = browser()
1190 ->GetActiveWebContents()
1193 content::RenderProcessHostWatcher crash_observer(
1194 process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
1195 process->Shutdown(-1);
1196 crash_observer.Wait();
1198 // Attempt to navigate to a chrome://... URL.
1199 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
1202 // Check that a browser-initiated navigation to a cross-site URL that then
1203 // redirects to a pdf hosted on another site works.
1204 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, CrossSiteRedirectionToPDF) {
1205 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
1206 https_server.AddDefaultHandlers(GetChromeTestDataDir());
1207 ASSERT_TRUE(https_server.Start());
1209 GURL initial_url = embedded_test_server()->GetURL("/title1.html");
1210 GURL pdf_url = embedded_test_server()->GetURL("/pdf/test.pdf");
1211 GURL cross_site_redirecting_url =
1212 https_server.GetURL("/server-redirect?" + pdf_url.spec());
1213 ui_test_utils::NavigateToURL(browser(), initial_url);
1214 ui_test_utils::NavigateToURL(browser(), cross_site_redirecting_url);
1215 EXPECT_EQ(pdf_url, browser()
1217 ->GetActiveWebContents()
1218 ->GetLastCommittedURL());
1221 // Check that clicking on a link doesn't carry the transient user activation
1222 // from the original page to the navigated page (crbug.com/865243).
1223 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1224 WindowOpenBlockedAfterClickNavigation) {
1225 // Navigate to a test page with links.
1226 ui_test_utils::NavigateToURL(browser(),
1227 embedded_test_server()->GetURL("/links.html"));
1229 // Click to navigate to title1.html.
1230 content::WebContents* main_contents =
1231 browser()->tab_strip_model()->GetActiveWebContents();
1232 content::TestNavigationObserver observer(main_contents);
1233 ASSERT_TRUE(ExecuteScript(main_contents,
1234 "document.getElementById('title1').click();"));
1237 // Make sure popup attempt fails due to lack of transient user activation.
1238 bool opened = false;
1239 EXPECT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractBool(
1240 main_contents, "window.domAutomationController.send(!!window.open());",
1242 EXPECT_FALSE(opened);
1244 EXPECT_EQ(embedded_test_server()->GetURL("/title1.html"),
1245 main_contents->GetLastCommittedURL());
1246 EXPECT_EQ(1, browser()->tab_strip_model()->count());
1249 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1250 OpenerNavigation_DownloadPolicy_Disallowed) {
1251 browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
1253 ui_test_utils::NavigateToURL(
1254 browser(), embedded_test_server()->GetURL("a.com", "/title1.html"));
1257 bool opened = false;
1258 content::WebContents* opener =
1259 browser()->tab_strip_model()->GetActiveWebContents();
1260 const char* kScriptFormat =
1261 "window.domAutomationController.send(!!window.open('%s'));";
1262 GURL popup_url = embedded_test_server()->GetURL("b.com", "/title1.html");
1263 content::TestNavigationObserver popup_waiter(nullptr, 1);
1264 popup_waiter.StartWatchingNewWebContents();
1265 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1266 opener, base::StringPrintf(kScriptFormat, popup_url.spec().c_str()),
1268 EXPECT_TRUE(opened);
1269 popup_waiter.Wait();
1270 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1272 // Using the popup, navigate its opener to a download.
1273 base::HistogramTester histograms;
1274 content::WebContents* popup =
1275 browser()->tab_strip_model()->GetActiveWebContents();
1276 EXPECT_NE(popup, opener);
1277 EXPECT_TRUE(WaitForLoadStop(popup));
1279 content::ConsoleObserverDelegate console_observer(
1281 "Navigating a cross-origin opener to a download (*) is deprecated*");
1282 opener->SetDelegate(&console_observer);
1283 EXPECT_TRUE(content::ExecuteScript(
1285 "window.opener.location ='data:html/text;base64,'+btoa('payload');"));
1287 console_observer.Wait();
1288 histograms.ExpectBucketCount(
1289 "Blink.UseCounter.Features",
1290 blink::mojom::WebFeature::kOpenerNavigationDownloadCrossOrigin, 1);
1292 // Ensure that no download happened.
1293 std::vector<download::DownloadItem*> download_items;
1294 content::DownloadManager* manager =
1295 content::BrowserContext::GetDownloadManager(browser()->profile());
1296 manager->GetAllDownloads(&download_items);
1297 EXPECT_TRUE(download_items.empty());
1300 // Opener navigations from a same-origin popup should be allowed.
1301 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1302 OpenerNavigation_DownloadPolicy_Allowed) {
1303 browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
1305 ui_test_utils::NavigateToURL(
1306 browser(), embedded_test_server()->GetURL("a.com", "/title1.html"));
1309 bool opened = false;
1310 content::WebContents* opener =
1311 browser()->tab_strip_model()->GetActiveWebContents();
1312 const char* kScriptFormat =
1313 "window.domAutomationController.send(!!window.open('%s'));";
1314 GURL popup_url = embedded_test_server()->GetURL("a.com", "/title1.html");
1315 content::TestNavigationObserver popup_waiter(nullptr, 1);
1316 popup_waiter.StartWatchingNewWebContents();
1317 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1318 opener, base::StringPrintf(kScriptFormat, popup_url.spec().c_str()),
1320 EXPECT_TRUE(opened);
1321 popup_waiter.Wait();
1322 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1324 // Using the popup, navigate its opener to a download.
1325 base::HistogramTester histograms;
1326 content::WebContents* popup =
1327 browser()->tab_strip_model()->GetActiveWebContents();
1328 EXPECT_NE(popup, opener);
1329 EXPECT_TRUE(WaitForLoadStop(popup));
1331 content::DownloadTestObserverInProgress observer(
1332 content::BrowserContext::GetDownloadManager(browser()->profile()),
1333 1 /* wait_count */);
1334 EXPECT_TRUE(content::ExecuteScript(
1336 "window.opener.location ='data:html/text;base64,'+btoa('payload');"));
1337 observer.WaitForFinished();
1339 histograms.ExpectBucketCount(
1340 "Blink.UseCounter.Features",
1341 blink::mojom::WebFeature::kOpenerNavigationDownloadCrossOrigin, 0);
1343 // Delete any pending download.
1344 std::vector<download::DownloadItem*> download_items;
1345 content::DownloadManager* manager =
1346 content::BrowserContext::GetDownloadManager(browser()->profile());
1347 manager->GetAllDownloads(&download_items);
1348 for (auto* item : download_items) {
1349 if (!item->IsDone())
1354 // Test which verifies that a noopener link/window.open() properly focus the
1355 // newly opened tab. See https://crbug.com/912348.
1356 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1357 NoopenerCorrectlyFocusesNewTab) {
1358 content::WebContents* main_contents =
1359 browser()->tab_strip_model()->GetActiveWebContents();
1361 // Navigate to a test page with links.
1363 content::TestNavigationObserver observer(main_contents);
1364 ui_test_utils::NavigateToURL(
1366 embedded_test_server()->GetURL("/click-noreferrer-links.html"));
1368 EXPECT_TRUE(observer.last_navigation_succeeded());
1371 // Click a link with noopener that navigates in a new window.
1372 content::WebContents* link_web_contents = nullptr;
1374 ui_test_utils::AllBrowserTabAddedWaiter tab_added;
1376 content::ExecJs(main_contents, "clickSameSiteNoOpenerTargetedLink();"));
1377 link_web_contents = tab_added.Wait();
1380 EXPECT_NE(main_contents, link_web_contents);
1381 EXPECT_TRUE(link_web_contents->GetRenderWidgetHostView()->HasFocus());
1383 // Execute window.open() with noopener.
1384 content::WebContents* open_web_contents = nullptr;
1386 ui_test_utils::AllBrowserTabAddedWaiter tab_added;
1387 EXPECT_TRUE(content::ExecJs(
1388 main_contents, content::JsReplace("window.open($1, 'bar', 'noopener');",
1389 embedded_test_server()->GetURL(
1390 "a.com", "/title1.html"))));
1391 open_web_contents = tab_added.Wait();
1394 EXPECT_NE(main_contents, open_web_contents);
1395 EXPECT_NE(link_web_contents, open_web_contents);
1396 EXPECT_TRUE(open_web_contents->GetRenderWidgetHostView()->HasFocus());
1399 // Tests the ukm entry logged when the navigation entry is marked as skippable
1400 // on back/forward button on doing a renderer initiated navigation without ever
1401 // getting a user activation.
1402 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1403 NoUserActivationSetSkipOnBackForward) {
1404 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1405 ui_test_utils::NavigateToURL(browser(), skippable_url);
1407 GURL redirected_url(embedded_test_server()->GetURL("/title2.html"));
1409 // Navigate to a new document from the renderer without a user gesture.
1410 content::WebContents* main_contents =
1411 browser()->tab_strip_model()->GetActiveWebContents();
1412 content::TestNavigationObserver observer(main_contents);
1413 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1414 main_contents, "location = '" + redirected_url.spec() + "';"));
1416 EXPECT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1419 using Entry = ukm::builders::HistoryManipulationIntervention;
1420 const auto& ukm_entries =
1421 test_ukm_recorder()->GetEntriesByName(Entry::kEntryName);
1422 EXPECT_EQ(1u, ukm_entries.size());
1423 test_ukm_recorder()->ExpectEntrySourceHasUrl(ukm_entries[0], skippable_url);
1425 // Verify the metric where user tries to go specifically to a skippable entry
1426 // using long press.
1427 base::HistogramTester histogram;
1428 std::unique_ptr<BackForwardMenuModel> back_model(
1429 std::make_unique<BackForwardMenuModel>(
1430 browser(), BackForwardMenuModel::ModelType::kBackward));
1431 back_model->set_test_web_contents(main_contents);
1432 back_model->ActivatedAt(0);
1433 histogram.ExpectBucketCount(
1434 "Navigation.BackForward.NavigatingToEntryMarkedToBeSkipped", true, 1);
1437 // Same as above except the navigation is cross-site.
1438 IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest,
1439 NoUserActivationSetSkipOnBackForwardCrossSite) {
1440 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1441 ui_test_utils::NavigateToURL(browser(), skippable_url);
1443 GURL redirected_url(
1444 embedded_test_server()->GetURL("foo.com", "/title2.html"));
1446 // Navigate to a new document from the renderer without a user gesture.
1447 content::WebContents* main_contents =
1448 browser()->tab_strip_model()->GetActiveWebContents();
1449 content::TestNavigationObserver observer(main_contents);
1450 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1451 main_contents, "location = '" + redirected_url.spec() + "';"));
1453 EXPECT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1457 using Entry = ukm::builders::HistoryManipulationIntervention;
1458 const auto& ukm_entries =
1459 test_ukm_recorder()->GetEntriesByName(Entry::kEntryName);
1460 EXPECT_EQ(1u, ukm_entries.size());
1461 test_ukm_recorder()->ExpectEntrySourceHasUrl(ukm_entries[0], skippable_url);
1464 // TODO(csharrison): These tests should become tentative WPT, once the feature
1465 // is enabled by default.
1466 using NavigationConsumingTest = ChromeNavigationBrowserTest;
1468 // The fullscreen API is spec'd to require a user activation (aka user gesture),
1469 // so use that API to test if navigation consumes the activation.
1470 // https://fullscreen.spec.whatwg.org/#allowed-to-request-fullscreen
1471 IN_PROC_BROWSER_TEST_F(NavigationConsumingTest,
1472 NavigationConsumesUserGesture_Fullscreen) {
1473 ui_test_utils::NavigateToURL(
1475 embedded_test_server()->GetURL("/navigation_consumes_gesture.html"));
1476 content::WebContents* contents =
1477 browser()->tab_strip_model()->GetActiveWebContents();
1479 // Normally, fullscreen should work, as long as there is a user gesture.
1480 bool is_fullscreen = false;
1481 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1482 contents, "document.body.webkitRequestFullscreen();", &is_fullscreen));
1483 EXPECT_TRUE(is_fullscreen);
1485 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1486 contents, "document.webkitExitFullscreen();", &is_fullscreen));
1487 EXPECT_FALSE(is_fullscreen);
1489 // However, starting a navigation should consume the gesture. Fullscreen
1490 // should not work afterwards. Make sure the navigation is synchronously
1491 // started via click().
1492 std::string script = R"(
1493 document.getElementsByTagName('a')[0].click();
1494 document.body.webkitRequestFullscreen();
1497 // Use the TestNavigationManager to ensure the navigation is not finished
1498 // before fullscreen can occur.
1499 content::TestNavigationManager nav_manager(
1500 contents, embedded_test_server()->GetURL("/title1.html"));
1502 content::ExecuteScriptAndExtractBool(contents, script, &is_fullscreen));
1503 EXPECT_FALSE(is_fullscreen);
1506 // Similar to the fullscreen test above, but checks that popups are successfully
1507 // blocked if spawned after a navigation.
1508 IN_PROC_BROWSER_TEST_F(NavigationConsumingTest,
1509 NavigationConsumesUserGesture_Popups) {
1510 ui_test_utils::NavigateToURL(browser(),
1511 embedded_test_server()->GetURL("/links.html"));
1512 content::WebContents* contents =
1513 browser()->tab_strip_model()->GetActiveWebContents();
1515 // Normally, a popup should open fine if it is associated with a user gesture.
1516 bool did_open = false;
1517 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1518 contents, "window.domAutomationController.send(!!window.open());",
1520 EXPECT_TRUE(did_open);
1522 // Starting a navigation should consume a gesture, but make sure that starting
1523 // a same-document navigation doesn't do the consuming.
1524 std::string same_document_script = R"(
1525 document.getElementById("ref").click();
1526 window.domAutomationController.send(!!window.open());
1528 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1529 contents, same_document_script, &did_open));
1530 EXPECT_TRUE(did_open);
1532 // If the navigation is to a different document, the gesture should be
1533 // successfully consumed.
1534 std::string different_document_script = R"(
1535 document.getElementById("title1").click();
1536 window.domAutomationController.send(!!window.open());
1538 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
1539 contents, different_document_script, &did_open));
1540 EXPECT_FALSE(did_open);
1543 // Regression test for https://crbug.com/856779, where a navigation to a
1544 // top-level, same process frame in another tab fails to focus that tab.
1545 IN_PROC_BROWSER_TEST_F(NavigationConsumingTest, TargetNavigationFocus) {
1546 content::WebContents* opener =
1547 browser()->tab_strip_model()->GetActiveWebContents();
1548 ui_test_utils::NavigateToURL(
1549 browser(), embedded_test_server()->GetURL("/link_with_target.html"));
1552 content::TestNavigationObserver new_tab_observer(nullptr, 1);
1553 new_tab_observer.StartWatchingNewWebContents();
1554 ASSERT_TRUE(ExecuteScript(
1555 opener, "document.getElementsByTagName('a')[0].click();"));
1556 new_tab_observer.Wait();
1559 content::WebContents* new_contents =
1560 browser()->tab_strip_model()->GetActiveWebContents();
1561 EXPECT_NE(new_contents, opener);
1563 // Re-focusing the opener and clicking again should re-focus the popup.
1564 opener->GetDelegate()->ActivateContents(opener);
1565 EXPECT_EQ(opener, browser()->tab_strip_model()->GetActiveWebContents());
1567 content::TestNavigationObserver new_tab_observer(new_contents, 1);
1568 ASSERT_TRUE(ExecuteScript(
1569 opener, "document.getElementsByTagName('a')[0].click();"));
1570 new_tab_observer.Wait();
1572 EXPECT_EQ(new_contents, browser()->tab_strip_model()->GetActiveWebContents());
1575 using HistoryManipulationInterventionBrowserTest = ChromeNavigationBrowserTest;
1577 // Tests that chrome::GoBack does nothing if all the previous entries are marked
1578 // as skippable and the back button is disabled.
1579 IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1580 AllEntriesSkippableBackButtonDisabled) {
1581 // Create a new tab to avoid confusion from having a NTP navigation entry.
1582 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1583 ui_test_utils::NavigateToURLWithDisposition(
1584 browser(), skippable_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
1585 ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
1587 content::WebContents* main_contents =
1588 browser()->tab_strip_model()->GetActiveWebContents();
1590 // Navigate to a new document from the renderer without a user gesture.
1591 GURL redirected_url(embedded_test_server()->GetURL("/title2.html"));
1592 content::TestNavigationManager manager(main_contents, redirected_url);
1593 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1594 main_contents, "location = '" + redirected_url.spec() + "';"));
1595 manager.WaitForNavigationFinished();
1596 ASSERT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1597 ASSERT_EQ(2, main_contents->GetController().GetEntryCount());
1599 // Attempting to go back should do nothing.
1600 ASSERT_FALSE(chrome::CanGoBack(browser()));
1601 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1602 ASSERT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1604 // Back command should be disabled.
1605 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1608 // Tests that chrome::GoBack is successful if there is at least one entry not
1609 // marked as skippable and the back button should be enabled.
1610 IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1611 AllEntriesNotSkippableBackButtonEnabled) {
1612 // Navigate to a URL in the same tab. Note that at the start of the test this
1613 // tab already has about:blank.
1614 GURL skippable_url(embedded_test_server()->GetURL("/title1.html"));
1615 ui_test_utils::NavigateToURL(browser(), skippable_url);
1617 content::WebContents* main_contents =
1618 browser()->tab_strip_model()->GetActiveWebContents();
1620 // Navigate to a new document from the renderer without a user gesture.
1621 GURL redirected_url(embedded_test_server()->GetURL("/title2.html"));
1622 content::TestNavigationManager manager(main_contents, redirected_url);
1623 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1624 main_contents, "location = '" + redirected_url.spec() + "';"));
1625 manager.WaitForNavigationFinished();
1626 ASSERT_EQ(redirected_url, main_contents->GetLastCommittedURL());
1627 ASSERT_EQ(3, main_contents->GetController().GetEntryCount());
1629 // Back command should be enabled.
1630 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1632 // Attempting to go back should skip |skippable_url| and go to about:blank.
1633 ASSERT_TRUE(chrome::CanGoBack(browser()));
1634 content::TestNavigationObserver observer(main_contents);
1635 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1637 ASSERT_EQ(GURL("about:blank"), main_contents->GetLastCommittedURL());
1640 // Tests that a main frame hosting pdf does not get skipped because of history
1641 // manipulation intervention if there was a user gesture.
1642 IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1643 PDFDoNotSkipOnBackForwardDueToUserGesture) {
1644 GURL pdf_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
1645 ui_test_utils::NavigateToURL(browser(), pdf_url);
1647 GURL url(embedded_test_server()->GetURL("/title2.html"));
1649 // Navigate to a new document from the renderer with a user gesture.
1650 content::WebContents* main_contents =
1651 browser()->tab_strip_model()->GetActiveWebContents();
1652 content::TestNavigationObserver observer(main_contents);
1653 EXPECT_TRUE(ExecuteScript(main_contents, "location = '" + url.spec() + "';"));
1655 EXPECT_EQ(url, main_contents->GetLastCommittedURL());
1657 // Since pdf_url initiated a navigation with a user gesture, it will
1658 // not be skipped. Going back should be allowed and should navigate to
1660 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1662 ASSERT_TRUE(chrome::CanGoBack(browser()));
1663 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1664 EXPECT_TRUE(content::WaitForLoadStop(main_contents));
1665 ASSERT_EQ(pdf_url, main_contents->GetLastCommittedURL());
1668 // Tests that a main frame hosting pdf gets skipped because of history
1669 // manipulation intervention if there was no user gesture.
1670 IN_PROC_BROWSER_TEST_F(HistoryManipulationInterventionBrowserTest,
1671 PDFSkipOnBackForwardNoUserGesture) {
1672 GURL pdf_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
1673 ui_test_utils::NavigateToURL(browser(), pdf_url);
1675 GURL url(embedded_test_server()->GetURL("/title2.html"));
1677 // Navigate to a new document from the renderer without a user gesture.
1678 content::WebContents* main_contents =
1679 browser()->tab_strip_model()->GetActiveWebContents();
1680 content::TestNavigationObserver observer(main_contents);
1681 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
1682 main_contents, "location = '" + url.spec() + "';"));
1684 EXPECT_EQ(url, main_contents->GetLastCommittedURL());
1686 // Since pdf_url initiated a navigation without a user gesture, it will
1687 // be skipped. Going back should be allowed and should navigate to
1689 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BACK));
1691 ASSERT_TRUE(chrome::CanGoBack(browser()));
1692 chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
1693 EXPECT_TRUE(content::WaitForLoadStop(main_contents));
1694 ASSERT_EQ(GURL("about:blank"), main_contents->GetLastCommittedURL());
1697 // This test class turns on the mode where sites where the user enters a
1698 // password are dynamically added to the list of sites requiring a dedicated
1699 // process. It also disables strict site isolation so that the effects of
1700 // password isolation can be observed.
1701 class SiteIsolationForPasswordSitesBrowserTest
1702 : public ChromeNavigationBrowserTest {
1704 SiteIsolationForPasswordSitesBrowserTest() {
1705 feature_list_.InitWithFeatures(
1706 {site_isolation::features::kSiteIsolationForPasswordSites},
1707 {features::kSitePerProcess});
1710 std::vector<std::string> GetSavedIsolatedSites() {
1711 return GetSavedIsolatedSites(browser()->profile());
1714 std::vector<std::string> GetSavedIsolatedSites(Profile* profile) {
1715 PrefService* prefs = profile->GetPrefs();
1717 prefs->GetList(site_isolation::prefs::kUserTriggeredIsolatedOrigins);
1718 std::vector<std::string> sites;
1719 for (const base::Value& value : list->GetList())
1720 sites.push_back(value.GetString());
1724 bool HasSyntheticTrial(const std::string& trial_name) {
1725 std::vector<std::string> synthetic_trials;
1726 variations::GetSyntheticTrialGroupIdsAsString(&synthetic_trials);
1727 std::string trial_hash =
1728 base::StringPrintf("%x", variations::HashName(trial_name));
1730 std::find_if(synthetic_trials.begin(), synthetic_trials.end(),
1731 [trial_hash](const auto& trial) {
1732 return base::StartsWith(trial, trial_hash,
1733 base::CompareCase::SENSITIVE);
1735 return it != synthetic_trials.end();
1738 bool IsInSyntheticTrialGroup(const std::string& trial_name,
1739 const std::string& trial_group) {
1740 std::vector<std::string> synthetic_trials;
1741 variations::GetSyntheticTrialGroupIdsAsString(&synthetic_trials);
1742 std::string expected_entry =
1743 base::StringPrintf("%x-%x", variations::HashName(trial_name),
1744 variations::HashName(trial_group));
1745 return std::find(synthetic_trials.begin(), synthetic_trials.end(),
1746 expected_entry) != synthetic_trials.end();
1749 const std::string kSiteIsolationSyntheticTrialName = "SiteIsolationActive";
1750 const std::string kOOPIFSyntheticTrialName = "OutOfProcessIframesActive";
1751 const std::string kSyntheticTrialGroup = "Enabled";
1754 void SetUpCommandLine(base::CommandLine* command_line) override {
1755 ChromeNavigationBrowserTest::SetUpCommandLine(command_line);
1757 // This simulates a whitelist of isolated sites.
1758 std::string origin_list =
1759 embedded_test_server()->GetURL("isolated1.com", "/").spec() + "," +
1760 embedded_test_server()->GetURL("isolated2.com", "/").spec();
1761 command_line->AppendSwitchASCII(switches::kIsolateOrigins, origin_list);
1763 // Allow HTTPS server to be used on sites other than localhost.
1764 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
1768 base::test::ScopedFeatureList feature_list_;
1771 // Verifies that a site gets process-isolated after a password is typed on a
1772 // page from that site.
1773 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1774 SiteIsIsolatedAfterEnteringPassword) {
1775 // This test requires dynamic isolated origins to be enabled.
1776 if (!content::SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
1779 GURL url(embedded_test_server()->GetURL("sub.foo.com",
1780 "/password/password_form.html"));
1781 ui_test_utils::NavigateToURL(browser(), url);
1782 content::WebContents* contents =
1783 browser()->tab_strip_model()->GetActiveWebContents();
1785 // foo.com should not be isolated to start with. Verify that a cross-site
1786 // iframe does not become an OOPIF.
1788 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1789 std::string kAppendIframe = R"(
1790 var i = document.createElement('iframe');
1792 document.body.appendChild(i);)";
1793 EXPECT_TRUE(ExecJs(contents, kAppendIframe));
1794 GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title1.html"));
1795 EXPECT_TRUE(NavigateIframeToURL(contents, "child", bar_url));
1796 content::RenderFrameHost* child = ChildFrameAt(contents->GetMainFrame(), 0);
1797 EXPECT_FALSE(child->IsCrossProcessSubframe());
1799 // Fill a form and submit through a <input type="submit"> button.
1800 content::TestNavigationObserver observer(contents);
1801 std::string kFillAndSubmit =
1802 "document.getElementById('username_field').value = 'temp';"
1803 "document.getElementById('password_field').value = 'random';"
1804 "document.getElementById('input_submit_button').click()";
1805 EXPECT_TRUE(content::ExecJs(contents, kFillAndSubmit));
1808 // Since there were no script references from other windows, we should've
1809 // swapped BrowsingInstances and put the result of the form submission into a
1810 // dedicated process, locked to foo.com. Check that a cross-site iframe now
1811 // becomes an OOPIF.
1813 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1814 EXPECT_TRUE(ExecJs(contents, kAppendIframe));
1815 EXPECT_TRUE(NavigateIframeToURL(contents, "child", bar_url));
1816 child = ChildFrameAt(contents->GetMainFrame(), 0);
1817 EXPECT_TRUE(child->IsCrossProcessSubframe());
1819 // Open a fresh tab (also forcing a new BrowsingInstance), navigate to
1820 // foo.com, and verify that a cross-site iframe becomes an OOPIF.
1821 AddBlankTabAndShow(browser());
1822 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1823 content::WebContents* new_contents =
1824 browser()->tab_strip_model()->GetActiveWebContents();
1825 EXPECT_NE(new_contents, contents);
1827 ui_test_utils::NavigateToURL(browser(), url);
1828 EXPECT_TRUE(ExecJs(new_contents, kAppendIframe));
1829 EXPECT_TRUE(NavigateIframeToURL(new_contents, "child", bar_url));
1830 content::RenderFrameHost* new_child =
1831 ChildFrameAt(new_contents->GetMainFrame(), 0);
1832 EXPECT_TRUE(new_child->IsCrossProcessSubframe());
1835 // This test checks that the synthetic field trial is activated properly after
1836 // a navigation to an isolated origin commits in a main frame.
1837 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1838 SyntheticTrialFromMainFrame) {
1839 content::WebContents* web_contents =
1840 browser()->tab_strip_model()->GetActiveWebContents();
1842 NavigationMetricsRecorder* recorder =
1843 content::WebContentsUserData<NavigationMetricsRecorder>::FromWebContents(
1845 recorder->EnableSiteIsolationSyntheticTrialForTesting();
1847 EXPECT_FALSE(HasSyntheticTrial(kSiteIsolationSyntheticTrialName));
1848 EXPECT_FALSE(HasSyntheticTrial(kOOPIFSyntheticTrialName));
1850 // Browse to a page with some iframes without involving any isolated origins.
1851 GURL unisolated_url(embedded_test_server()->GetURL(
1852 "a.com", "/cross_site_iframe_factory.html?a(b,c(a))"));
1853 ui_test_utils::NavigateToURL(browser(), unisolated_url);
1854 EXPECT_FALSE(HasSyntheticTrial(kSiteIsolationSyntheticTrialName));
1856 // Now browse to an isolated origin.
1858 embedded_test_server()->GetURL("isolated1.com", "/title1.html"));
1859 ui_test_utils::NavigateToURL(browser(), isolated_url);
1860 EXPECT_TRUE(IsInSyntheticTrialGroup(kSiteIsolationSyntheticTrialName,
1861 kSyntheticTrialGroup));
1863 // The OOPIF synthetic trial shouldn't be activated, since the isolated
1864 // oriign page doesn't have any OOPIFs.
1866 IsInSyntheticTrialGroup(kOOPIFSyntheticTrialName, kSyntheticTrialGroup));
1869 // This test checks that the synthetic field trials for both site isolation and
1870 // encountering OOPIFs are activated properly after a navigation to an isolated
1871 // origin commits in a subframe.
1872 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1873 SyntheticTrialFromSubframe) {
1874 content::WebContents* web_contents =
1875 browser()->tab_strip_model()->GetActiveWebContents();
1877 NavigationMetricsRecorder* recorder =
1878 content::WebContentsUserData<NavigationMetricsRecorder>::FromWebContents(
1880 recorder->EnableSiteIsolationSyntheticTrialForTesting();
1882 EXPECT_FALSE(HasSyntheticTrial(kSiteIsolationSyntheticTrialName));
1883 EXPECT_FALSE(HasSyntheticTrial(kOOPIFSyntheticTrialName));
1885 // Browse to a page with an isolated origin on one of the iframes.
1886 GURL isolated_url(embedded_test_server()->GetURL(
1887 "a.com", "/cross_site_iframe_factory.html?a(b,c,isolated2,d)"));
1888 ui_test_utils::NavigateToURL(browser(), isolated_url);
1889 EXPECT_TRUE(IsInSyntheticTrialGroup(kSiteIsolationSyntheticTrialName,
1890 kSyntheticTrialGroup));
1892 IsInSyntheticTrialGroup(kOOPIFSyntheticTrialName, kSyntheticTrialGroup));
1895 // Verifies that persistent isolated sites survive restarts. Part 1.
1896 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1897 PRE_IsolatedSitesPersistAcrossRestarts) {
1898 // There shouldn't be any saved isolated origins to start with.
1899 EXPECT_THAT(GetSavedIsolatedSites(), IsEmpty());
1901 // Isolate saved.com and saved2.com persistently.
1902 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1903 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1904 GURL saved2_url(embedded_test_server()->GetURL("saved2.com", "/title1.html"));
1905 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved2_url);
1907 // Check that saved.com utilizes a dedicated process in future navigations.
1908 // Open a new tab to force creation of a new BrowsingInstance.
1909 AddBlankTabAndShow(browser());
1910 ui_test_utils::NavigateToURL(browser(), saved_url);
1911 content::WebContents* contents =
1912 browser()->tab_strip_model()->GetActiveWebContents();
1914 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1916 // Check that saved.com and saved2.com were saved to disk.
1917 EXPECT_THAT(GetSavedIsolatedSites(),
1918 UnorderedElementsAre("http://saved.com", "http://saved2.com"));
1921 // Verifies that process-isolated sites persist across restarts. Part 2.
1922 // This runs after Part 1 above and in the same profile. Part 1 has already
1923 // added "saved.com" as a persisted isolated origin, so this part verifies that
1924 // it requires a dedicated process after restart.
1925 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1926 IsolatedSitesPersistAcrossRestarts) {
1927 // Check that saved.com and saved2.com are still saved to disk.
1928 EXPECT_THAT(GetSavedIsolatedSites(),
1929 UnorderedElementsAre("http://saved.com", "http://saved2.com"));
1931 // Check that these sites utilize a dedicated process after restarting, but a
1932 // non-isolated foo.com URL does not.
1933 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1934 GURL saved2_url(embedded_test_server()->GetURL("saved2.com", "/title2.html"));
1935 GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title3.html"));
1936 ui_test_utils::NavigateToURL(browser(), saved_url);
1937 content::WebContents* contents =
1938 browser()->tab_strip_model()->GetActiveWebContents();
1940 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1941 ui_test_utils::NavigateToURL(browser(), saved2_url);
1943 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1944 ui_test_utils::NavigateToURL(browser(), foo_url);
1946 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1949 // Verify that trying to isolate a site multiple times will only save it to
1951 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1952 IsolatedSiteIsSavedOnlyOnce) {
1953 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1954 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1955 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1956 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1957 EXPECT_THAT(GetSavedIsolatedSites(),
1958 UnorderedElementsAre("http://saved.com"));
1961 // Check that Incognito doesn't inherit saved isolated origins from its
1962 // original profile, and that any isolated origins added in Incognito don't
1963 // affect the original profile.
1964 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
1965 IncognitoWithIsolatedSites) {
1966 // Isolate saved.com and verify it's been saved to disk.
1967 GURL saved_url(embedded_test_server()->GetURL("saved.com", "/title1.html"));
1968 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
1969 EXPECT_THAT(GetSavedIsolatedSites(),
1970 UnorderedElementsAre("http://saved.com"));
1972 // Create an incognito browser and browse to saved.com. Verify that it's
1973 // *not* isolated in incognito.
1975 // TODO(alexmos): This might change in the future if we decide to inherit
1976 // main profile's isolated origins in incognito. See
1977 // https://crbug.com/905513.
1978 Browser* incognito = CreateIncognitoBrowser();
1979 ui_test_utils::NavigateToURL(incognito, saved_url);
1980 content::WebContents* contents =
1981 incognito->tab_strip_model()->GetActiveWebContents();
1983 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1985 // Add an isolated site in incognito, and verify that while future
1986 // navigations to this site in incognito require a dedicated process,
1987 // navigations to this site in the main profile do not require a dedicated
1988 // process, and the site is not persisted for either the main or incognito
1990 GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
1991 content::SiteInstance::StartIsolatingSite(incognito->profile(), foo_url);
1993 AddBlankTabAndShow(incognito);
1994 ui_test_utils::NavigateToURL(incognito, foo_url);
1995 contents = incognito->tab_strip_model()->GetActiveWebContents();
1997 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
1999 AddBlankTabAndShow(browser());
2000 ui_test_utils::NavigateToURL(browser(), foo_url);
2001 contents = browser()->tab_strip_model()->GetActiveWebContents();
2003 contents->GetMainFrame()->GetSiteInstance()->RequiresDedicatedProcess());
2005 EXPECT_THAT(GetSavedIsolatedSites(browser()->profile()),
2006 testing::Not(testing::Contains("http://foo.com")));
2007 EXPECT_THAT(GetSavedIsolatedSites(incognito->profile()),
2008 testing::Not(testing::Contains("http://foo.com")));
2011 // Verify that serving a Clear-Site-Data header does not clear saved isolated
2012 // sites. Saved isolated sites should only be cleared by user-initiated
2014 IN_PROC_BROWSER_TEST_F(SiteIsolationForPasswordSitesBrowserTest,
2015 ClearSiteDataDoesNotClearSavedIsolatedSites) {
2016 // Start an HTTPS server, as Clear-Site-Data is only available on HTTPS URLs.
2017 net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
2018 https_server.AddDefaultHandlers(GetChromeTestDataDir());
2019 ASSERT_TRUE(https_server.Start());
2021 // Isolate saved.com and verify it's been saved to disk.
2022 GURL saved_url(https_server.GetURL("saved.com", "/clear_site_data.html"));
2023 content::SiteInstance::StartIsolatingSite(browser()->profile(), saved_url);
2024 EXPECT_THAT(GetSavedIsolatedSites(),
2025 UnorderedElementsAre("https://saved.com"));
2027 // Navigate to a URL that serves a Clear-Site-Data header for cache, cookies,
2028 // and DOM storage. This is the most that a Clear-Site-Data header could
2029 // clear, and this should not clear saved isolated sites.
2030 ui_test_utils::NavigateToURL(browser(), saved_url);
2031 EXPECT_THAT(GetSavedIsolatedSites(),
2032 UnorderedElementsAre("https://saved.com"));