blob: 3610625afa1e72b0b3628643761812ffc2504d1c [file] [log] [blame]
// Copyright 2018 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 "cc/layers/picture_layer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
namespace blink {
class MainThreadScrollingReasonsTest
: public testing::Test,
public testing::WithParamInterface<bool>,
private ScopedBlinkGenPropertyTreesForTest {
public:
MainThreadScrollingReasonsTest()
: ScopedBlinkGenPropertyTreesForTest(GetParam()),
base_url_("http://www.test.com/") {
helper_.InitializeWithSettings(&ConfigureSettings);
GetWebView()->MainFrameWidget()->Resize(IntSize(320, 240));
// macOS attaches main frame scrollbars to the VisualViewport so the
// VisualViewport layers need to be initialized.
GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
WebFrameWidgetBase* main_frame_widget =
GetWebView()->MainFrameImpl()->FrameWidgetImpl();
main_frame_widget->SetRootGraphicsLayer(GetWebView()
->MainFrameImpl()
->GetFrame()
->View()
->GetLayoutView()
->Compositor()
->RootGraphicsLayer());
}
~MainThreadScrollingReasonsTest() override {
Platform::Current()
->GetURLLoaderMockFactory()
->UnregisterAllURLsAndClearMemoryCache();
}
void NavigateTo(const std::string& url) {
frame_test_helpers::LoadFrame(GetWebView()->MainFrameImpl(), url);
}
void LoadHTML(const std::string& html) {
frame_test_helpers::LoadHTMLString(GetWebView()->MainFrameImpl(), html,
url_test_helpers::ToKURL("about:blank"));
}
void ForceFullCompositingUpdate() {
GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
}
void RegisterMockedHttpURLLoad(const std::string& file_name) {
url_test_helpers::RegisterMockedURLLoadFromBase(
WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
WebString::FromUTF8(file_name));
}
uint32_t GetViewMainThreadScrollingReasons() const {
// Pre-BlinkGenPropertyTrees, main thread scrolling reasons are set on
// cc::Layer in ScrollingCoordinator.
if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
auto* layer = GetFrame()->View()->LayoutViewport()->LayerForScrolling();
return layer->CcLayer()->GetMainThreadScrollingReasons();
}
// With BlinkGenPropertyTrees, main thread scrolling reasons are calculated
// in the blink property tree builder and set on set on scroll nodes.
const auto* scroll = GetFrame()
->View()
->GetLayoutView()
->FirstFragment()
.PaintProperties()
->Scroll();
return scroll->GetMainThreadScrollingReasons();
}
WebViewImpl* GetWebView() const { return helper_.GetWebView(); }
LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); }
protected:
std::string base_url_;
private:
static void ConfigureSettings(WebSettings* settings) {
settings->SetPreferCompositingToLCDTextEnabled(true);
}
frame_test_helpers::WebViewHelper helper_;
};
INSTANTIATE_TEST_CASE_P(All, MainThreadScrollingReasonsTest, testing::Bool());
TEST_P(MainThreadScrollingReasonsTest,
FixedPositionLosingBackingShouldTriggerMainThreadScroll) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
RegisterMockedHttpURLLoad("fixed-position-losing-backing.html");
NavigateTo(base_url_ + "fixed-position-losing-backing.html");
ForceFullCompositingUpdate();
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
Element* fixed_pos = GetFrame()->GetDocument()->getElementById("fixed");
fixed_pos->SetInlineStyleProperty(CSSPropertyTransform, CSSValueNone);
ForceFullCompositingUpdate();
EXPECT_TRUE(GetViewMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest,
CustomScrollbarShouldTriggerMainThreadScroll) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
GetWebView()->SetDeviceScaleFactor(2.f);
RegisterMockedHttpURLLoad("custom_scrollbar.html");
NavigateTo(base_url_ + "custom_scrollbar.html");
ForceFullCompositingUpdate();
Document* document = GetFrame()->GetDocument();
Element* container = document->getElementById("container");
Element* content = document->getElementById("content");
DCHECK_EQ(container->getAttribute(html_names::kClassAttr),
"custom_scrollbar");
DCHECK(container);
DCHECK(content);
LayoutObject* layout_object = container->GetLayoutObject();
ASSERT_TRUE(layout_object->IsBox());
LayoutBox* box = ToLayoutBox(layout_object);
ASSERT_TRUE(box->UsesCompositedScrolling());
CompositedLayerMapping* composited_layer_mapping =
box->Layer()->GetCompositedLayerMapping();
// When Blink generates property trees, the main thread reasons are stored in
// scroll nodes instead of being set on the custom scrollbar layer, so we use
// the scrolling contents layer to access the main thread scrolling reasons.
GraphicsLayer* layer =
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()
? composited_layer_mapping->ScrollingContentsLayer()
: composited_layer_mapping->LayerForVerticalScrollbar();
ASSERT_TRUE(layer);
EXPECT_TRUE(layer->CcLayer()->GetMainThreadScrollingReasons());
EXPECT_TRUE(layer->CcLayer()->GetMainThreadScrollingReasons() &
MainThreadScrollingReason::kCustomScrollbarScrolling);
// remove custom scrollbar class, the scrollbar is expected to scroll on
// impl thread as it is an overlay scrollbar.
container->removeAttribute("class");
ForceFullCompositingUpdate();
layer = RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()
? composited_layer_mapping->ScrollingContentsLayer()
: composited_layer_mapping->LayerForVerticalScrollbar();
EXPECT_FALSE(layer->CcLayer()->GetMainThreadScrollingReasons());
EXPECT_FALSE(layer->CcLayer()->GetMainThreadScrollingReasons() &
MainThreadScrollingReason::kCustomScrollbarScrolling);
}
TEST_P(MainThreadScrollingReasonsTest,
BackgroundAttachmentFixedShouldTriggerMainThreadScroll) {
RegisterMockedHttpURLLoad("iframe-background-attachment-fixed.html");
RegisterMockedHttpURLLoad("iframe-background-attachment-fixed-inner.html");
RegisterMockedHttpURLLoad("white-1x1.png");
NavigateTo(base_url_ + "iframe-background-attachment-fixed.html");
ForceFullCompositingUpdate();
Element* iframe = GetFrame()->GetDocument()->getElementById("iframe");
ASSERT_TRUE(iframe);
LayoutObject* layout_object = iframe->GetLayoutObject();
ASSERT_TRUE(layout_object);
ASSERT_TRUE(layout_object->IsLayoutEmbeddedContent());
LayoutEmbeddedContent* layout_embedded_content =
ToLayoutEmbeddedContent(layout_object);
ASSERT_TRUE(layout_embedded_content);
LocalFrameView* inner_frame_view =
ToLocalFrameView(layout_embedded_content->ChildFrameView());
ASSERT_TRUE(inner_frame_view);
auto* inner_layout_view = inner_frame_view->GetLayoutView();
ASSERT_TRUE(inner_layout_view);
PaintLayerCompositor* inner_compositor = inner_layout_view->Compositor();
ASSERT_TRUE(inner_compositor->InCompositingMode());
GraphicsLayer* scroll_layer =
inner_frame_view->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
ASSERT_TRUE(cc_scroll_layer->GetMainThreadScrollingReasons() &
MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
// Remove fixed background-attachment should make the iframe
// scroll on cc.
auto* iframe_doc = ToHTMLIFrameElement(iframe)->contentDocument();
iframe = iframe_doc->getElementById("scrollable");
ASSERT_TRUE(iframe);
iframe->removeAttribute("class");
ForceFullCompositingUpdate();
layout_object = iframe->GetLayoutObject();
ASSERT_TRUE(layout_object);
scroll_layer =
layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
ASSERT_FALSE(cc_scroll_layer->GetMainThreadScrollingReasons() &
MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
// Force main frame to scroll on main thread. All its descendants
// should scroll on main thread as well.
Element* element = GetFrame()->GetDocument()->getElementById("scrollable");
element->setAttribute(
"style",
"background-image: url('white-1x1.png'); background-attachment: fixed;",
ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
layout_object = iframe->GetLayoutObject();
ASSERT_TRUE(layout_object);
scroll_layer =
layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
ASSERT_TRUE(cc_scroll_layer->GetMainThreadScrollingReasons() &
MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
}
// Upon resizing the content size, the main thread scrolling reason
// kHasNonLayerViewportConstrainedObject should be updated on all frames
TEST_P(MainThreadScrollingReasonsTest,
RecalculateMainThreadScrollingReasonsUponResize) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
RegisterMockedHttpURLLoad("has-non-layer-viewport-constrained-objects.html");
NavigateTo(base_url_ + "has-non-layer-viewport-constrained-objects.html");
ForceFullCompositingUpdate();
// When the main document is not scrollable, there should be no reasons.
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
// When the div forces the document to be scrollable, it should scroll on main
// thread.
Element* element = GetFrame()->GetDocument()->getElementById("scrollable");
element->setAttribute("style",
"overflow:scroll;height:2000px;will-change:transform;",
ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
EXPECT_TRUE(
GetViewMainThreadScrollingReasons() &
MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects);
// The main thread scrolling reason should be reset upon the following change.
element->setAttribute("style",
"overflow:scroll;height:200px;will-change:transform;",
ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest, StickyTriggersMainThreadScroll) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
LoadHTML(
"<body style='height: 1200px'>"
"<div style='position: sticky; top: 0'>sticky</div>");
ForceFullCompositingUpdate();
EXPECT_EQ(MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects,
GetViewMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest, FastScrollingCanBeDisabledWithSetting) {
GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600));
LoadHTML("<div id='spacer' style='height: 1000px'></div>");
GetWebView()->GetSettings()->SetThreadedScrollingEnabled(false);
GetFrame()->View()->SetNeedsPaintPropertyUpdate();
ForceFullCompositingUpdate();
// Main scrolling should be enabled with the setting override.
EXPECT_TRUE(GetViewMainThreadScrollingReasons());
// Main scrolling should also propagate to inner viewport layer.
cc::Layer* inner_viewport_scroll_layer =
GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer();
ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
EXPECT_TRUE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest, FastScrollingForFixedPosition) {
RegisterMockedHttpURLLoad("fixed-position.html");
NavigateTo(base_url_ + "fixed-position.html");
ForceFullCompositingUpdate();
// Fixed position should not fall back to main thread scrolling.
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest, FastScrollingForStickyPosition) {
RegisterMockedHttpURLLoad("sticky-position.html");
NavigateTo(base_url_ + "sticky-position.html");
ForceFullCompositingUpdate();
// Sticky position should not fall back to main thread scrolling.
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest, FastScrollingByDefault) {
GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600));
LoadHTML("<div id='spacer' style='height: 1000px'></div>");
ForceFullCompositingUpdate();
// Fast scrolling should be enabled by default.
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
cc::Layer* inner_viewport_scroll_layer =
GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer();
ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
EXPECT_FALSE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons());
}
TEST_P(MainThreadScrollingReasonsTest,
ScrollbarsForceMainThreadOrHaveCompositorScrollbarLayer) {
RegisterMockedHttpURLLoad("trivial-scroller.html");
NavigateTo(base_url_ + "trivial-scroller.html");
ForceFullCompositingUpdate();
Document* document = GetFrame()->GetDocument();
Element* scrollable_element = document->getElementById("scroller");
DCHECK(scrollable_element);
LayoutObject* layout_object = scrollable_element->GetLayoutObject();
ASSERT_TRUE(layout_object->IsBox());
LayoutBox* box = ToLayoutBox(layout_object);
ASSERT_TRUE(box->UsesCompositedScrolling());
CompositedLayerMapping* composited_layer_mapping =
box->Layer()->GetCompositedLayerMapping();
GraphicsLayer* scrollbar_graphics_layer =
composited_layer_mapping->LayerForVerticalScrollbar();
ASSERT_TRUE(scrollbar_graphics_layer);
bool has_cc_scrollbar_layer = !scrollbar_graphics_layer->DrawsContent();
EXPECT_TRUE(
has_cc_scrollbar_layer ||
scrollbar_graphics_layer->CcLayer()->GetMainThreadScrollingReasons());
}
class NonCompositedMainThreadScrollingReasonsTest
: public MainThreadScrollingReasonsTest {
static const uint32_t kLCDTextRelatedReasons =
MainThreadScrollingReason::kHasOpacityAndLCDText |
MainThreadScrollingReason::kHasTransformAndLCDText |
MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText |
MainThreadScrollingReason::kIsNotStackingContextAndLCDText;
protected:
NonCompositedMainThreadScrollingReasonsTest() {
RegisterMockedHttpURLLoad("two_scrollable_area.html");
NavigateTo(base_url_ + "two_scrollable_area.html");
}
void TestNonCompositedReasons(const std::string& target,
const uint32_t reason) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
Element* container = document->getElementById("scroller1");
container->setAttribute("class", target.c_str(), ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())
->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
reason);
Element* container2 = document->getElementById("scroller2");
PaintLayerScrollableArea* scrollable_area2 =
ToLayoutBoxModelObject(container2->GetLayoutObject())
->GetScrollableArea();
ASSERT_TRUE(scrollable_area2);
// Different scrollable area should remain unaffected.
EXPECT_FALSE(
scrollable_area2->GetNonCompositedMainThreadScrollingReasons() &
reason);
LocalFrameView* frame_view = GetFrame()->View();
ASSERT_TRUE(frame_view);
EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason);
// Remove attribute from the scroller 1 would lead to scroll on impl.
container->removeAttribute("class");
ForceFullCompositingUpdate();
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
reason);
EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason);
// Add target attribute would again lead to scroll on main thread
container->setAttribute("class", target.c_str(), ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
reason);
EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason);
if ((reason & kLCDTextRelatedReasons) &&
!(reason & ~kLCDTextRelatedReasons)) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
ForceFullCompositingUpdate();
EXPECT_FALSE(
scrollable_area->GetNonCompositedMainThreadScrollingReasons());
EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons());
}
}
};
INSTANTIATE_TEST_CASE_P(All,
NonCompositedMainThreadScrollingReasonsTest,
testing::Bool());
TEST_P(NonCompositedMainThreadScrollingReasonsTest, TransparentTest) {
TestNonCompositedReasons("transparent",
MainThreadScrollingReason::kHasOpacityAndLCDText);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, TransformTest) {
TestNonCompositedReasons("transform",
MainThreadScrollingReason::kHasTransformAndLCDText);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, BackgroundNotOpaqueTest) {
TestNonCompositedReasons(
"background-not-opaque",
MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, ClipTest) {
TestNonCompositedReasons("clip",
MainThreadScrollingReason::kHasClipRelatedProperty);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, ClipPathTest) {
uint32_t clip_reason = MainThreadScrollingReason::kHasClipRelatedProperty;
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
// Test ancestor with ClipPath
Element* element = document->body();
element->setAttribute(html_names::kStyleAttr,
"clip-path:circle(115px at 20px 20px);");
Element* container = document->getElementById("scroller1");
ASSERT_TRUE(container);
ForceFullCompositingUpdate();
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
clip_reason);
EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
// Remove clip path from ancestor.
element->removeAttribute(html_names::kStyleAttr);
ForceFullCompositingUpdate();
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
clip_reason);
EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
// Test descendant with ClipPath
element = document->getElementById("content1");
ASSERT_TRUE(element);
element->setAttribute(html_names::kStyleAttr,
"clip-path:circle(115px at 20px 20px);");
ForceFullCompositingUpdate();
EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
clip_reason);
EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
// Remove clip path from descendant.
element->removeAttribute(html_names::kStyleAttr);
ForceFullCompositingUpdate();
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
clip_reason);
EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, LCDTextEnabledTest) {
TestNonCompositedReasons("transparent",
MainThreadScrollingReason::kHasOpacityAndLCDText);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, BoxShadowTest) {
TestNonCompositedReasons(
"box-shadow", MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer);
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest, StackingContextTest) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
Element* container = document->getElementById("scroller1");
ASSERT_TRUE(container);
ForceFullCompositingUpdate();
// If a scroller contains all its children, it's not a stacking context.
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
MainThreadScrollingReason::kIsNotStackingContextAndLCDText);
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
ForceFullCompositingUpdate();
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() &
MainThreadScrollingReason::kIsNotStackingContextAndLCDText);
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
// Adding "contain: paint" to force a stacking context leads to promotion.
container->setAttribute("style", "contain: paint", ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons());
}
TEST_P(NonCompositedMainThreadScrollingReasonsTest,
CompositedWithLCDTextRelatedReasonsTest) {
// With "will-change:transform" we composite elements with
// LCDTextRelatedReasons only. For elements with other
// NonCompositedReasons, we don't create scrollingLayer for their
// CompositedLayerMapping therefore they don't get composited.
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
Element* container = document->getElementById("scroller1");
ASSERT_TRUE(container);
container->setAttribute("class", "composited transparent",
ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons());
Element* container2 = document->getElementById("scroller2");
ASSERT_TRUE(container2);
container2->setAttribute("class", "composited border-radius",
ASSERT_NO_EXCEPTION);
ForceFullCompositingUpdate();
PaintLayerScrollableArea* scrollable_area2 =
ToLayoutBoxModelObject(container2->GetLayoutObject())
->GetScrollableArea();
ASSERT_TRUE(scrollable_area2);
ASSERT_TRUE(scrollable_area2->UsesCompositedScrolling());
}
} // namespace blink