Commit 60688ddc authored by David Bokan's avatar David Bokan Committed by Commit Bot

Fix tests for BlockHTMLParserOnStyleSheet

These tests fail when the BlockHTMLParserOnStyleSheet flag is turned on.
The reason is that, with this flag, there is no way to block rendering.
Fragment anchors currently defer some behavior while rendering is
blocked. When the flag ships, this will no longer be possible.

However, the behavior being checked by some of these tests can still
occur, just in a different order. This CL fixes these tests so that they
continue to guard the intended behavior. This generally means that the
fragment will now invoke but we test the behavior between this initial
invocation and a subsequent one by delaying the document load event.

Bug: 891767
Change-Id: I0564b1f487c48be2f5efbb1c6478e3375a71e518
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2020503
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735460}
parent 732778e5
......@@ -170,11 +170,11 @@ TEST_F(ProgrammaticScrollSimTest, NavigateToHash) {
)HTML");
main_resource.Finish();
css_resource.Complete();
Compositor().BeginFrame();
// Run pending tasks to fire the load event and close the document. This
// should cause the document to scroll to the hash.
test::RunPendingTasks();
Compositor().BeginFrame();
ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_EQ(3000, layout_viewport->GetScrollOffset().Height());
......
......@@ -53,43 +53,54 @@ TEST_F(ElementFragmentAnchorTest, FocusHandlerRunBeforeRaf) {
background-color: red;
}
</style>
<link rel="stylesheet" type="text/css" href="sheet.css">
<a id="anchorlink" href="#bottom">Link to bottom of the page</a>
<div style="height: 1000px;"></div>
<link rel="stylesheet" type="text/css" href="sheet.css">
<input id="bottom">Bottom of the page</input>
)HTML");
MainFrame().ExecuteScript(WebScriptSource(R"HTML(
document.getElementById("bottom").addEventListener('focus', () => {
requestAnimationFrame(() => {
document.body.style.backgroundColor = '#00FF00';
<script>
document.getElementById("bottom").addEventListener('focus', () => {
requestAnimationFrame(() => {
document.body.style.backgroundColor = '#00FF00';
});
});
});
)HTML"));
</script>
)HTML");
// We're still waiting on the stylesheet to load so the load event shouldn't
// yet dispatch and rendering is deferred.
ASSERT_FALSE(GetDocument().HaveRenderBlockingResourcesLoaded());
// yet dispatch.
ASSERT_FALSE(GetDocument().IsLoadCompleted());
// Click on the anchor element. This will cause a synchronous same-document
// navigation.
// navigation. The fragment shouldn't activate yet as parsing will be blocked
// due to the unloaded stylesheet.
auto* anchor =
To<HTMLAnchorElement>(GetDocument().getElementById("anchorlink"));
anchor->click();
ASSERT_EQ(GetDocument().body(), GetDocument().ActiveElement())
<< "Active element changed while rendering is blocked";
// Complete the CSS stylesheet load so the document can finish loading. The
// fragment should be activated at that point.
// Complete the CSS stylesheet load so the document can finish parsing.
css_resource.Complete("");
Compositor().BeginFrame();
test::RunPendingTasks();
ASSERT_FALSE(GetDocument().IsLoadCompleted());
ASSERT_TRUE(GetDocument().HaveRenderBlockingResourcesLoaded());
// Now that the document has fully parsed the anchor should invoke at this
// point.
ASSERT_EQ(GetDocument().getElementById("bottom"),
GetDocument().ActiveElement())
<< "Active element wasn't changed after rendering was unblocked.";
GetDocument().ActiveElement());
// The background color shouldn't yet be updated.
ASSERT_EQ(GetDocument()
.body()
->GetLayoutObject()
->Style()
->VisitedDependentColor(GetCSSPropertyBackgroundColor())
.NameForLayoutTreeAsText(),
Color(255, 0, 0).NameForLayoutTreeAsText());
Compositor().BeginFrame();
// Make sure the background color is updated from the rAF without requiring a
// second BeginFrame.
EXPECT_EQ(GetDocument()
.body()
->GetLayoutObject()
......@@ -220,23 +231,34 @@ TEST_F(ElementFragmentAnchorTest, AnchorRemovedBeforeBeginFrameCrash) {
"text/css");
LoadURL("https://example.com/test.html#anchor");
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<link rel="stylesheet" type="text/css" href="sheet.css">
<div style="height: 1000px;"></div>
<input id="anchor">Bottom of the page</input>
)HTML");
// We're still waiting on the stylesheet to load so the load event shouldn't
// yet dispatch and rendering is deferred. This will avoid invoking or
// focusing the fragment when it's first installed.
ASSERT_FALSE(GetDocument().HaveRenderBlockingResourcesLoaded());
ASSERT_FALSE(GetDocument().IsLoadCompleted());
ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor());
ASSERT_TRUE(static_cast<ElementFragmentAnchor*>(
GetDocument().View()->GetFragmentAnchor())
->anchor_node_);
if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<link rel="stylesheet" type="text/css" href="sheet.css">
<div style="height: 1000px;"></div>
<input id="anchor">Bottom of the page</input>
)HTML");
// We're still waiting on the stylesheet to load so the load event shouldn't
// yet dispatch and parsing is deferred. This will install the anchor.
ASSERT_FALSE(GetDocument().IsLoadCompleted());
ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor());
ASSERT_TRUE(static_cast<ElementFragmentAnchor*>(
GetDocument().View()->GetFragmentAnchor())
->anchor_node_);
} else {
main_resource.Complete(R"HTML(
<!DOCTYPE html>
<div style="height: 1000px;"></div>
<input id="anchor">Bottom of the page</input>
<link rel="stylesheet" type="text/css" href="sheet.css">
)HTML");
// We're still waiting on the stylesheet to load so the load event shouldn't
// yet dispatch and parsing is deferred. This will install the anchor.
ASSERT_FALSE(GetDocument().IsLoadCompleted());
ASSERT_FALSE(GetDocument().View()->GetFragmentAnchor());
}
// Remove the fragment anchor from the DOM and perform GC.
GetDocument().getElementById("anchor")->remove();
......@@ -244,18 +266,23 @@ TEST_F(ElementFragmentAnchorTest, AnchorRemovedBeforeBeginFrameCrash) {
isolate->RequestGarbageCollectionForTesting(
v8::Isolate::kFullGarbageCollection);
// Now that the element has been removed and GC'd, unblock rendering so we can
// produce a frame.
// Now that the element has been removed and GC'd, unblock parsing. The
// anchor should be installed at this point.
css_resource.Complete("");
ASSERT_TRUE(GetDocument().HaveRenderBlockingResourcesLoaded());
// We should still have a fragment anchor but its node pointer shoulld be
// gone since it's a WeakMember.
ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor());
ASSERT_FALSE(static_cast<ElementFragmentAnchor*>(
GetDocument().View()->GetFragmentAnchor())
->anchor_node_);
test::RunPendingTasks();
if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
// We should still have a fragment anchor but its node pointer should be
// gone since it's a WeakMember.
ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor());
ASSERT_FALSE(static_cast<ElementFragmentAnchor*>(
GetDocument().View()->GetFragmentAnchor())
->anchor_node_);
} else {
// The fragment shouldn't have installed since the targeted element was
// removed.
ASSERT_FALSE(GetDocument().View()->GetFragmentAnchor());
}
// We'd normally focus the fragment during BeginFrame. Make sure we don't
// crash since it's been GC'd.
......
......@@ -153,6 +153,10 @@ bool TextFragmentAnchor::Invoke() {
frame_->GetDocument()->Markers().RemoveMarkersOfTypes(
DocumentMarker::MarkerTypes::TextFragment());
// TODO(bokan): Once BlockHTMLParserOnStyleSheets is launched, there won't be
// a way for the user to scroll before we invoke and scroll the anchor. We
// should confirm if we can remove tracking this after that point or if we
// need a replacement metric.
if (user_scrolled_ && !did_scroll_into_view_)
metrics_->ScrollCancelled();
......
......@@ -199,6 +199,12 @@ TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) {
// Test that the ScrollCancelled metric gets reported when a user scroll cancels
// the scroll into view.
TEST_F(TextFragmentAnchorMetricsTest, ScrollCancelled) {
// This test isn't relevant with this flag enabled. When it's enabled,
// there's no way to block rendering and the fragment is installed and
// invoked as soon as parsing finishes which means the user cannot scroll
// before this point.
ScopedBlockHTMLParserOnStyleSheetsForTest block_parser(false);
SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css");
LoadURL("https://example.com/test.html#:~:text=test");
......
......@@ -825,6 +825,8 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) {
TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css");
SimSubresourceRequest img_request("https://example.com/test.png",
"image/png");
LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
......@@ -840,15 +842,41 @@ TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
</style>
<link rel=stylesheet href=test.css>
<p id="text">This is a test page</p>
<img src="test.png">
)HTML");
Compositor().PaintFrame();
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 100),
kUserScroll);
if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 100),
kUserScroll);
// Set the target text to visible and change its position to cause a layout
// and invoke the fragment anchor in the next begin frame.
css_request.Complete("p { visibility: visible; top: 1001px; }");
img_request.Complete("");
} else {
// Set the target text to visible and change its position to cause a layout
// and invoke the fragment anchor in the next begin frame.
css_request.Complete("p { visibility: visible; top: 1001px; }");
RunPendingTasks();
Compositor().BeginFrame();
Element& p = *GetDocument().getElementById("text");
// We should have invoked the fragment and scrolled the <p> into view, but
// load should not yet be complete due to the image.
EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)));
ASSERT_FALSE(GetDocument().IsLoadCompleted());
// Before invoking again, perform a user scroll. This should abort future
// scrolls during fragment invocation.
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 0),
kUserScroll);
ASSERT_FALSE(ViewportRect().Contains(BoundingRectInFrame(p)));
img_request.Complete("");
RunPendingTasks();
ASSERT_TRUE(GetDocument().IsLoadCompleted());
}
// Set the target text to visible and change its position to cause a layout
// and invoke the fragment anchor.
css_request.Complete("p { visibility: visible; top: 1001px; }");
RunAsyncMatchingTasks();
Compositor().BeginFrame();
......
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