Commit 3f72f104 authored by David Bokan's avatar David Bokan Committed by Commit Bot

Separate text fragment browsertests

These have grown large enough that it makes sense to split them out from
navigation browser tests into their own separate file.

This CL is a straightforward move with not changes to the tests
themselves.

Bug: None
Change-Id: Iba4759b4e8f5797d5a693775684312c8997bac12
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2160325Reviewed-by: default avatarCharlie Reis <creis@chromium.org>
Commit-Queue: David Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#762141}
parent b31b6019
...@@ -2061,345 +2061,6 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AboutSrcDocUsesBeginNavigation) { ...@@ -2061,345 +2061,6 @@ IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, AboutSrcDocUsesBeginNavigation) {
interceptor.Wait(1); // DidCommitNavigation is called. interceptor.Wait(1); // DidCommitNavigation is called.
} }
class TextFragmentAnchorBrowserTest : public NavigationBaseBrowserTest {
public:
TextFragmentAnchorBrowserTest() {
feature_list_.InitAndEnableFeature(features::kDocumentPolicy);
}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
NavigationBaseBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"TextFragmentIdentifiers");
}
// Simulates a click on the middle of the DOM element with the given |id|.
void ClickElementWithId(WebContents* web_contents, const std::string& id) {
// Get the center coordinates of the DOM element.
const int x = EvalJs(web_contents,
JsReplace("const bounds = "
"document.getElementById($1)."
"getBoundingClientRect();"
"Math.floor(bounds.left + bounds.width / 2)",
id))
.ExtractInt();
const int y = EvalJs(web_contents,
JsReplace("const bounds = "
"document.getElementById($1)."
"getBoundingClientRect();"
"Math.floor(bounds.top + bounds.height / 2)",
id))
.ExtractInt();
SimulateMouseClickAt(web_contents, 0, blink::WebMouseEvent::Button::kLeft,
gfx::Point(x, y));
}
void WaitForPageLoad(WebContents* contents) {
EXPECT_TRUE(WaitForLoadStop(contents));
EXPECT_TRUE(WaitForRenderFrameReady(contents->GetMainFrame()));
}
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(
shell()->web_contents()->GetRenderViewHost()->GetWidget());
}
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest, EnabledOnUserNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/target_text_link.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
RenderFrameSubmissionObserver frame_observer(main_contents);
// We need to wait until hit test data is available.
HitTestRegionObserver hittest_observer(GetWidgetHost()->GetFrameSinkId());
hittest_observer.WaitForHitTestData();
ClickElementWithId(main_contents, "link");
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
EnabledOnBrowserNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
EnabledOnUserGestureScriptNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/empty.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
RenderFrameSubmissionObserver frame_observer(main_contents);
// ExecuteScript executes with a user gesture
EXPECT_TRUE(ExecuteScript(main_contents,
"location = '" + target_text_url.spec() + "';"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledOnScriptNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/empty.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
main_contents, "location = '" + target_text_url.spec() + "';"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledOnScriptHistoryNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
GURL url(embedded_test_server()->GetURL("/empty.html"));
EXPECT_TRUE(NavigateToURL(shell(), target_text_url));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
frame_observer.WaitForScrollOffsetAtTop(false);
// Scroll the page back to top so scroll restoration does not scroll the
// target back into view.
EXPECT_TRUE(ExecuteScript(main_contents, "window.scrollTo(0, 0)"));
frame_observer.WaitForScrollOffsetAtTop(true);
EXPECT_TRUE(NavigateToURL(shell(), url));
TestNavigationObserver observer(main_contents);
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(main_contents, "history.back()"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
// Note: we use a scroll handler in the page to check whether any scrolls
// happened at all, rather than checking the current scroll offset. This is
// to ensure that if the offset is reset back to the top for other reasons
// (e.g. history restoration) we still fail this test. See
// https://crbug.com/1042986 for why this matters.
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
EnabledOnSameDocumentBrowserNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(false);
// Scroll the page back to top. Make sure we reset the |did_scroll| variable
// we'll use below to ensure the same-document navigation invokes the text
// fragment.
EXPECT_TRUE(ExecuteScript(main_contents, "window.scrollTo(0, 0)"));
frame_observer.WaitForScrollOffsetAtTop(true);
EXPECT_TRUE(ExecJs(main_contents, "did_scroll = false;"));
// Perform a same-document browser initiated navigation
GURL same_doc_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=some"));
EXPECT_TRUE(NavigateToURL(shell(), same_doc_url));
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledOnSameDocumentScriptNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(
embedded_test_server()->GetURL("/scrollable_page_with_content.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=some"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
main_contents, "location = '" + target_text_url.spec() + "';"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest, EnabledByDocumentPolicy) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/target.html");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/target.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
// Load the target document
TestNavigationManager navigation_manager(main_contents, url);
shell()->LoadURL(url);
// Start navigation
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
navigation_manager.ResumeNavigation();
// Send Document-Policy header
response.WaitForRequest();
response.Send(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Document-Policy: no-force-load-at-top\r\n"
"\r\n"
"<script>"
" let did_scroll = false;"
" window.addEventListener('scroll', () => {"
" did_scroll = true;"
" });"
"</script>"
"<p style='position: absolute; top: 10000px;'>Some text</p>");
response.Done();
EXPECT_TRUE(navigation_manager.WaitForResponse());
navigation_manager.ResumeNavigation();
navigation_manager.WaitForNavigationFinished();
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledByDocumentPolicy) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/target.html");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/target.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
// Load the target document
TestNavigationManager navigation_manager(main_contents, url);
shell()->LoadURL(url);
// Start navigation
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
navigation_manager.ResumeNavigation();
// Send Document-Policy header
response.WaitForRequest();
response.Send(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Document-Policy: force-load-at-top\r\n"
"\r\n"
"<script>"
" let did_scroll = false;"
" window.addEventListener('scroll', () => {"
" did_scroll = true;"
" });"
"</script>"
"<p style='position: absolute; top: 10000px;'>Some text</p>");
response.Done();
EXPECT_TRUE(navigation_manager.WaitForResponse());
navigation_manager.ResumeNavigation();
navigation_manager.WaitForNavigationFinished();
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
// Regression test for https://crbug.com/996044 // Regression test for https://crbug.com/996044
// 1) Navigate an iframe to srcdoc (about:srcdoc); // 1) Navigate an iframe to srcdoc (about:srcdoc);
// 2) Same-document navigation to about:srcdoc#1. // 2) Same-document navigation to about:srcdoc#1.
...@@ -3625,86 +3286,4 @@ IN_PROC_BROWSER_TEST_F(DocumentPolicyBrowserTest, ...@@ -3625,86 +3286,4 @@ IN_PROC_BROWSER_TEST_F(DocumentPolicyBrowserTest,
EXPECT_FALSE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop()); EXPECT_FALSE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
} }
class ForceLoadAtTopBrowserTest : public NavigationBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
NavigationBaseBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"ForceLoadAtTop");
}
};
// Test that scroll restoration is disabled with ForceLoadAtTop
IN_PROC_BROWSER_TEST_F(ForceLoadAtTopBrowserTest, ScrollRestorationDisabled) {
GURL url(
embedded_test_server()->GetURL("/scrollable_page_with_content.html"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Scroll down the page a bit
EXPECT_TRUE(ExecuteScript(main_contents, "window.scrollTo(0, 1000)"));
frame_observer.WaitForScrollOffsetAtTop(false);
// Navigate away
EXPECT_TRUE(ExecuteScript(main_contents, "window.location = 'about:blank'"));
EXPECT_TRUE(WaitForLoadStop(main_contents));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Navigate back
EXPECT_TRUE(ExecuteScript(main_contents, "history.back()"));
EXPECT_TRUE(WaitForLoadStop(main_contents));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(RenderWidgetHostImpl::From(
main_contents->GetRenderViewHost()->GetWidget()));
EXPECT_TRUE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
}
// Test that element fragment anchor scrolling is disabled with ForceLoadAtTop
IN_PROC_BROWSER_TEST_F(ForceLoadAtTopBrowserTest, FragmentAnchorDisabled) {
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#text"));
WebContents* main_contents = shell()->web_contents();
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(RenderWidgetHostImpl::From(
main_contents->GetRenderViewHost()->GetWidget()));
EXPECT_TRUE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
}
IN_PROC_BROWSER_TEST_F(ForceLoadAtTopBrowserTest, TextFragmentAnchorDisabled) {
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(RenderWidgetHostImpl::From(
main_contents->GetRenderViewHost()->GetWidget()));
EXPECT_TRUE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
}
} // namespace content } // namespace content
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "url/gurl.h"
namespace content {
class TextFragmentAnchorBrowserTest : public ContentBrowserTest {
public:
TextFragmentAnchorBrowserTest() {
feature_list_.InitAndEnableFeature(features::kDocumentPolicy);
}
protected:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
}
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"TextFragmentIdentifiers");
}
// Simulates a click on the middle of the DOM element with the given |id|.
void ClickElementWithId(WebContents* web_contents, const std::string& id) {
// Get the center coordinates of the DOM element.
const int x = EvalJs(web_contents,
JsReplace("const bounds = "
"document.getElementById($1)."
"getBoundingClientRect();"
"Math.floor(bounds.left + bounds.width / 2)",
id))
.ExtractInt();
const int y = EvalJs(web_contents,
JsReplace("const bounds = "
"document.getElementById($1)."
"getBoundingClientRect();"
"Math.floor(bounds.top + bounds.height / 2)",
id))
.ExtractInt();
SimulateMouseClickAt(web_contents, 0, blink::WebMouseEvent::Button::kLeft,
gfx::Point(x, y));
}
void WaitForPageLoad(WebContents* contents) {
EXPECT_TRUE(WaitForLoadStop(contents));
EXPECT_TRUE(WaitForRenderFrameReady(contents->GetMainFrame()));
}
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(
shell()->web_contents()->GetRenderViewHost()->GetWidget());
}
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest, EnabledOnUserNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/target_text_link.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
RenderFrameSubmissionObserver frame_observer(main_contents);
// We need to wait until hit test data is available.
HitTestRegionObserver hittest_observer(GetWidgetHost()->GetFrameSinkId());
hittest_observer.WaitForHitTestData();
ClickElementWithId(main_contents, "link");
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
EnabledOnBrowserNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
EnabledOnUserGestureScriptNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/empty.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
RenderFrameSubmissionObserver frame_observer(main_contents);
// ExecuteScript executes with a user gesture
EXPECT_TRUE(ExecuteScript(main_contents,
"location = '" + target_text_url.spec() + "';"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledOnScriptNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/empty.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
main_contents, "location = '" + target_text_url.spec() + "';"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledOnScriptHistoryNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
GURL url(embedded_test_server()->GetURL("/empty.html"));
EXPECT_TRUE(NavigateToURL(shell(), target_text_url));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
frame_observer.WaitForScrollOffsetAtTop(false);
// Scroll the page back to top so scroll restoration does not scroll the
// target back into view.
EXPECT_TRUE(ExecuteScript(main_contents, "window.scrollTo(0, 0)"));
frame_observer.WaitForScrollOffsetAtTop(true);
EXPECT_TRUE(NavigateToURL(shell(), url));
TestNavigationObserver observer(main_contents);
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(main_contents, "history.back()"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
// Note: we use a scroll handler in the page to check whether any scrolls
// happened at all, rather than checking the current scroll offset. This is
// to ensure that if the offset is reset back to the top for other reasons
// (e.g. history restoration) we still fail this test. See
// https://crbug.com/1042986 for why this matters.
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
EnabledOnSameDocumentBrowserNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(false);
// Scroll the page back to top. Make sure we reset the |did_scroll| variable
// we'll use below to ensure the same-document navigation invokes the text
// fragment.
EXPECT_TRUE(ExecuteScript(main_contents, "window.scrollTo(0, 0)"));
frame_observer.WaitForScrollOffsetAtTop(true);
EXPECT_TRUE(ExecJs(main_contents, "did_scroll = false;"));
// Perform a same-document browser initiated navigation
GURL same_doc_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=some"));
EXPECT_TRUE(NavigateToURL(shell(), same_doc_url));
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledOnSameDocumentScriptNavigation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(
embedded_test_server()->GetURL("/scrollable_page_with_content.html"));
GURL target_text_url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=some"));
EXPECT_TRUE(NavigateToURL(shell(), url));
WebContents* main_contents = shell()->web_contents();
TestNavigationObserver observer(main_contents);
EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
main_contents, "location = '" + target_text_url.spec() + "';"));
observer.Wait();
EXPECT_EQ(target_text_url, main_contents->GetLastCommittedURL());
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest, EnabledByDocumentPolicy) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/target.html");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/target.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
// Load the target document
TestNavigationManager navigation_manager(main_contents, url);
shell()->LoadURL(url);
// Start navigation
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
navigation_manager.ResumeNavigation();
// Send Document-Policy header
response.WaitForRequest();
response.Send(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Document-Policy: no-force-load-at-top\r\n"
"\r\n"
"<script>"
" let did_scroll = false;"
" window.addEventListener('scroll', () => {"
" did_scroll = true;"
" });"
"</script>"
"<p style='position: absolute; top: 10000px;'>Some text</p>");
response.Done();
EXPECT_TRUE(navigation_manager.WaitForResponse());
navigation_manager.ResumeNavigation();
navigation_manager.WaitForNavigationFinished();
WaitForPageLoad(main_contents);
frame_observer.WaitForScrollOffsetAtTop(
/*expected_scroll_offset_at_top=*/false);
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(true, EvalJs(main_contents, "did_scroll;"));
}
IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
DisabledByDocumentPolicy) {
net::test_server::ControllableHttpResponse response(embedded_test_server(),
"/target.html");
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/target.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
// Load the target document
TestNavigationManager navigation_manager(main_contents, url);
shell()->LoadURL(url);
// Start navigation
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
navigation_manager.ResumeNavigation();
// Send Document-Policy header
response.WaitForRequest();
response.Send(
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Document-Policy: force-load-at-top\r\n"
"\r\n"
"<script>"
" let did_scroll = false;"
" window.addEventListener('scroll', () => {"
" did_scroll = true;"
" });"
"</script>"
"<p style='position: absolute; top: 10000px;'>Some text</p>");
response.Done();
EXPECT_TRUE(navigation_manager.WaitForResponse());
navigation_manager.ResumeNavigation();
navigation_manager.WaitForNavigationFinished();
WaitForPageLoad(main_contents);
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(GetWidgetHost());
EXPECT_EQ(false, EvalJs(main_contents, "did_scroll;"));
}
class ForceLoadAtTopBrowserTest : public TextFragmentAnchorBrowserTest {
protected:
void SetUpOnMainThread() override {
TextFragmentAnchorBrowserTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
}
void SetUpCommandLine(base::CommandLine* command_line) override {
TextFragmentAnchorBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
"ForceLoadAtTop");
}
};
// Test that scroll restoration is disabled with ForceLoadAtTop
IN_PROC_BROWSER_TEST_F(ForceLoadAtTopBrowserTest, ScrollRestorationDisabled) {
GURL url(
embedded_test_server()->GetURL("/scrollable_page_with_content.html"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Scroll down the page a bit
EXPECT_TRUE(ExecuteScript(main_contents, "window.scrollTo(0, 1000)"));
frame_observer.WaitForScrollOffsetAtTop(false);
// Navigate away
EXPECT_TRUE(ExecuteScript(main_contents, "window.location = 'about:blank'"));
EXPECT_TRUE(WaitForLoadStop(main_contents));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Navigate back
EXPECT_TRUE(ExecuteScript(main_contents, "history.back()"));
EXPECT_TRUE(WaitForLoadStop(main_contents));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(RenderWidgetHostImpl::From(
main_contents->GetRenderViewHost()->GetWidget()));
EXPECT_TRUE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
}
// Test that element fragment anchor scrolling is disabled with ForceLoadAtTop
IN_PROC_BROWSER_TEST_F(ForceLoadAtTopBrowserTest, FragmentAnchorDisabled) {
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#text"));
WebContents* main_contents = shell()->web_contents();
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(RenderWidgetHostImpl::From(
main_contents->GetRenderViewHost()->GetWidget()));
EXPECT_TRUE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
}
IN_PROC_BROWSER_TEST_F(ForceLoadAtTopBrowserTest, TextFragmentAnchorDisabled) {
GURL url(embedded_test_server()->GetURL(
"/scrollable_page_with_content.html#:~:text=text"));
WebContents* main_contents = shell()->web_contents();
RenderFrameSubmissionObserver frame_observer(main_contents);
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_TRUE(WaitForRenderFrameReady(main_contents->GetMainFrame()));
// Wait a short amount of time to ensure the page does not scroll.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
RunUntilInputProcessed(RenderWidgetHostImpl::From(
main_contents->GetRenderViewHost()->GetWidget()));
EXPECT_TRUE(main_contents->GetMainFrame()->GetView()->IsScrollOffsetAtTop());
}
} // namespace content
...@@ -1066,6 +1066,7 @@ test("content_browsertests") { ...@@ -1066,6 +1066,7 @@ test("content_browsertests") {
"../browser/sms/sms_browsertest.cc", "../browser/sms/sms_browsertest.cc",
"../browser/snapshot_browsertest.cc", "../browser/snapshot_browsertest.cc",
"../browser/storage_partition_impl_browsertest.cc", "../browser/storage_partition_impl_browsertest.cc",
"../browser/text_fragment_browsertest.cc",
"../browser/tracing/background_tracing_manager_browsertest.cc", "../browser/tracing/background_tracing_manager_browsertest.cc",
"../browser/tracing/memory_instrumentation_browsertest.cc", "../browser/tracing/memory_instrumentation_browsertest.cc",
"../browser/tracing/memory_tracing_browsertest.cc", "../browser/tracing/memory_tracing_browsertest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment