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) { ...@@ -170,11 +170,11 @@ TEST_F(ProgrammaticScrollSimTest, NavigateToHash) {
)HTML"); )HTML");
main_resource.Finish(); main_resource.Finish();
css_resource.Complete(); css_resource.Complete();
Compositor().BeginFrame();
// Run pending tasks to fire the load event and close the document. This // Run pending tasks to fire the load event and close the document. This
// should cause the document to scroll to the hash. // should cause the document to scroll to the hash.
test::RunPendingTasks(); test::RunPendingTasks();
Compositor().BeginFrame();
ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport(); ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_EQ(3000, layout_viewport->GetScrollOffset().Height()); EXPECT_EQ(3000, layout_viewport->GetScrollOffset().Height());
......
...@@ -53,43 +53,54 @@ TEST_F(ElementFragmentAnchorTest, FocusHandlerRunBeforeRaf) { ...@@ -53,43 +53,54 @@ TEST_F(ElementFragmentAnchorTest, FocusHandlerRunBeforeRaf) {
background-color: red; background-color: red;
} }
</style> </style>
<link rel="stylesheet" type="text/css" href="sheet.css">
<a id="anchorlink" href="#bottom">Link to bottom of the page</a> <a id="anchorlink" href="#bottom">Link to bottom of the page</a>
<div style="height: 1000px;"></div> <div style="height: 1000px;"></div>
<link rel="stylesheet" type="text/css" href="sheet.css">
<input id="bottom">Bottom of the page</input> <input id="bottom">Bottom of the page</input>
)HTML"); <script>
document.getElementById("bottom").addEventListener('focus', () => {
MainFrame().ExecuteScript(WebScriptSource(R"HTML( requestAnimationFrame(() => {
document.getElementById("bottom").addEventListener('focus', () => { document.body.style.backgroundColor = '#00FF00';
requestAnimationFrame(() => { });
document.body.style.backgroundColor = '#00FF00';
}); });
}); </script>
)HTML")); )HTML");
// We're still waiting on the stylesheet to load so the load event shouldn't // We're still waiting on the stylesheet to load so the load event shouldn't
// yet dispatch and rendering is deferred. // yet dispatch.
ASSERT_FALSE(GetDocument().HaveRenderBlockingResourcesLoaded());
ASSERT_FALSE(GetDocument().IsLoadCompleted()); ASSERT_FALSE(GetDocument().IsLoadCompleted());
// Click on the anchor element. This will cause a synchronous same-document // 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 = auto* anchor =
To<HTMLAnchorElement>(GetDocument().getElementById("anchorlink")); To<HTMLAnchorElement>(GetDocument().getElementById("anchorlink"));
anchor->click(); anchor->click();
ASSERT_EQ(GetDocument().body(), GetDocument().ActiveElement()) ASSERT_EQ(GetDocument().body(), GetDocument().ActiveElement())
<< "Active element changed while rendering is blocked"; << "Active element changed while rendering is blocked";
// Complete the CSS stylesheet load so the document can finish loading. The // Complete the CSS stylesheet load so the document can finish parsing.
// fragment should be activated at that point.
css_resource.Complete(""); css_resource.Complete("");
Compositor().BeginFrame(); test::RunPendingTasks();
ASSERT_FALSE(GetDocument().IsLoadCompleted()); // Now that the document has fully parsed the anchor should invoke at this
ASSERT_TRUE(GetDocument().HaveRenderBlockingResourcesLoaded()); // point.
ASSERT_EQ(GetDocument().getElementById("bottom"), ASSERT_EQ(GetDocument().getElementById("bottom"),
GetDocument().ActiveElement()) GetDocument().ActiveElement());
<< "Active element wasn't changed after rendering was unblocked.";
// 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() EXPECT_EQ(GetDocument()
.body() .body()
->GetLayoutObject() ->GetLayoutObject()
...@@ -220,23 +231,34 @@ TEST_F(ElementFragmentAnchorTest, AnchorRemovedBeforeBeginFrameCrash) { ...@@ -220,23 +231,34 @@ TEST_F(ElementFragmentAnchorTest, AnchorRemovedBeforeBeginFrameCrash) {
"text/css"); "text/css");
LoadURL("https://example.com/test.html#anchor"); LoadURL("https://example.com/test.html#anchor");
main_resource.Complete(R"HTML( if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
<!DOCTYPE html> main_resource.Complete(R"HTML(
<link rel="stylesheet" type="text/css" href="sheet.css"> <!DOCTYPE html>
<div style="height: 1000px;"></div> <link rel="stylesheet" type="text/css" href="sheet.css">
<input id="anchor">Bottom of the page</input> <div style="height: 1000px;"></div>
)HTML"); <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 // We're still waiting on the stylesheet to load so the load event shouldn't
// focusing the fragment when it's first installed. // yet dispatch and parsing is deferred. This will install the anchor.
ASSERT_FALSE(GetDocument().HaveRenderBlockingResourcesLoaded()); ASSERT_FALSE(GetDocument().IsLoadCompleted());
ASSERT_FALSE(GetDocument().IsLoadCompleted()); ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor());
ASSERT_TRUE(static_cast<ElementFragmentAnchor*>(
ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor()); GetDocument().View()->GetFragmentAnchor())
ASSERT_TRUE(static_cast<ElementFragmentAnchor*>( ->anchor_node_);
GetDocument().View()->GetFragmentAnchor()) } else {
->anchor_node_); 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. // Remove the fragment anchor from the DOM and perform GC.
GetDocument().getElementById("anchor")->remove(); GetDocument().getElementById("anchor")->remove();
...@@ -244,18 +266,23 @@ TEST_F(ElementFragmentAnchorTest, AnchorRemovedBeforeBeginFrameCrash) { ...@@ -244,18 +266,23 @@ TEST_F(ElementFragmentAnchorTest, AnchorRemovedBeforeBeginFrameCrash) {
isolate->RequestGarbageCollectionForTesting( isolate->RequestGarbageCollectionForTesting(
v8::Isolate::kFullGarbageCollection); v8::Isolate::kFullGarbageCollection);
// Now that the element has been removed and GC'd, unblock rendering so we can // Now that the element has been removed and GC'd, unblock parsing. The
// produce a frame. // anchor should be installed at this point.
css_resource.Complete(""); css_resource.Complete("");
test::RunPendingTasks();
ASSERT_TRUE(GetDocument().HaveRenderBlockingResourcesLoaded());
if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
// We should still have a fragment anchor but its node pointer shoulld be // We should still have a fragment anchor but its node pointer should be
// gone since it's a WeakMember. // gone since it's a WeakMember.
ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor()); ASSERT_TRUE(GetDocument().View()->GetFragmentAnchor());
ASSERT_FALSE(static_cast<ElementFragmentAnchor*>( ASSERT_FALSE(static_cast<ElementFragmentAnchor*>(
GetDocument().View()->GetFragmentAnchor()) GetDocument().View()->GetFragmentAnchor())
->anchor_node_); ->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 // We'd normally focus the fragment during BeginFrame. Make sure we don't
// crash since it's been GC'd. // crash since it's been GC'd.
......
...@@ -153,6 +153,10 @@ bool TextFragmentAnchor::Invoke() { ...@@ -153,6 +153,10 @@ bool TextFragmentAnchor::Invoke() {
frame_->GetDocument()->Markers().RemoveMarkersOfTypes( frame_->GetDocument()->Markers().RemoveMarkersOfTypes(
DocumentMarker::MarkerTypes::TextFragment()); 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_) if (user_scrolled_ && !did_scroll_into_view_)
metrics_->ScrollCancelled(); metrics_->ScrollCancelled();
......
...@@ -199,6 +199,12 @@ TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) { ...@@ -199,6 +199,12 @@ TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) {
// Test that the ScrollCancelled metric gets reported when a user scroll cancels // Test that the ScrollCancelled metric gets reported when a user scroll cancels
// the scroll into view. // the scroll into view.
TEST_F(TextFragmentAnchorMetricsTest, ScrollCancelled) { 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"); SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css"); SimSubresourceRequest css_request("https://example.com/test.css", "text/css");
LoadURL("https://example.com/test.html#:~:text=test"); LoadURL("https://example.com/test.html#:~:text=test");
......
...@@ -825,6 +825,8 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) { ...@@ -825,6 +825,8 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) {
TEST_F(TextFragmentAnchorTest, ScrollCancelled) { TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
SimRequest request("https://example.com/test.html#:~:text=test", "text/html"); SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css"); 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"); LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML( request.Complete(R"HTML(
<!DOCTYPE html> <!DOCTYPE html>
...@@ -840,15 +842,41 @@ TEST_F(TextFragmentAnchorTest, ScrollCancelled) { ...@@ -840,15 +842,41 @@ TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
</style> </style>
<link rel=stylesheet href=test.css> <link rel=stylesheet href=test.css>
<p id="text">This is a test page</p> <p id="text">This is a test page</p>
<img src="test.png">
)HTML"); )HTML");
Compositor().PaintFrame(); Compositor().PaintFrame();
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 100), if (!RuntimeEnabledFeatures::BlockHTMLParserOnStyleSheetsEnabled()) {
kUserScroll); 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(); RunAsyncMatchingTasks();
Compositor().BeginFrame(); 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