Chromium Code Reviews| Index: third_party/WebKit/Source/web/tests/PaintInvalidationTest.cpp |
| diff --git a/third_party/WebKit/Source/web/tests/PaintInvalidationTest.cpp b/third_party/WebKit/Source/web/tests/PaintInvalidationTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..418adbfa500c6e897e4aff7c5ab77a9efc45fcca |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/web/tests/PaintInvalidationTest.cpp |
| @@ -0,0 +1,132 @@ |
| +// Copyright 2016 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 "core/frame/FrameView.h" |
| +#include "core/layout/LayoutView.h" |
| +#include "core/paint/PaintLayer.h" |
| +#include "core/paint/PaintLayerScrollableArea.h" |
| +#include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h" |
| +#include "platform/testing/TestingPlatformSupport.h" |
| +#include "platform/testing/UnitTestHelpers.h" |
| +#include "public/web/WebScriptSource.h" |
| +#include "public/web/WebSettings.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "web/WebLocalFrameImpl.h" |
| +#include "web/tests/sim/SimDisplayItemList.h" |
| +#include "web/tests/sim/SimRequest.h" |
| +#include "web/tests/sim/SimTest.h" |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +void enableViewport(WebSettings* settings) { |
| + settings->setViewportEnabled(true); |
| +} |
| + |
| +class PaintInvalidationTest : public SimTest { |
| + public: |
| + PaintInvalidationTest() : SimTest(enableViewport) |
| + { } |
| + |
| + protected: |
| + bool invalidationArrayContains(JSONArray* invalidations, LayoutObject& object) { |
|
pdr.
2017/02/23 18:24:33
This unittest is basically equivalent to a layout
bokan
2017/02/23 18:41:17
I don't mind deleting it if I can (I feel bad havi
pdr.
2017/02/23 19:42:07
Do we need to run the full lifecycle though? In ot
|
| + for (size_t i = 0; i < invalidations->size(); ++i) { |
| + JSONValue* value = invalidations->at(i); |
| + if (!value) |
| + continue; |
| + |
| + if (value->getType() != JSONValue::TypeObject) |
| + continue; |
| + |
| + JSONObject* invalidationPair = JSONObject::cast(value); |
| + DCHECK(invalidationPair); |
| + JSONValue* name = invalidationPair->get("object"); |
| + if (name && name->getType() == JSONValue::TypeString) { |
| + String nameString; |
| + name->asString(&nameString); |
| + if (nameString == object.debugName()) |
| + return true; |
| + } |
| + } |
| + |
| + return false; |
| + } |
| +}; |
| + |
| +class NoCompositingPlatform : public TestingPlatformSupport { |
| + public: |
| + NoCompositingPlatform() {} |
| + ~NoCompositingPlatform() override {} |
| + bool isThreadedAnimationEnabled() override { return false; } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(NoCompositingPlatform); |
| +}; |
| + |
| +TEST_F(PaintInvalidationTest, AnimatedTransformOverflowInvalidatesBackground) { |
| + // SimCompositor doesn't yet support animations ticked on the compositor so |
| + // ensure we tick it on the main thread. |
| + ScopedTestingPlatformSupport<NoCompositingPlatform> platform; |
| + |
| + v8::HandleScope handleScope(v8::Isolate::GetCurrent()); |
| + webView().resize(WebSize(800, 600)); |
| + SimRequest request("https://example.com/test.html", "text/html"); |
| + loadURL("https://example.com/test.html"); |
| + request.complete( |
| + "<!DOCTYPE html>" |
| + "<style type='text/css'>" |
| + " body, html {" |
| + " width: 95%;" |
| + " height: 95%;" |
| + " margin: 0px;" |
| + " }" |
| + " #container {" |
| + " width: 100%;" |
| + " height: 100%;" |
| + " transform-origin: 0% 100%;" |
| + " transform: rotateZ(0);" |
| + " transition: transform 1s;" |
| + " background-color: red;" |
| + " }" |
| + " #container.tilted {" |
| + " transform: rotateZ(45deg);" |
| + " }" |
| + "</style>" |
| + "<div id='container'></div>"); |
| + |
| + ScrollableArea* scrollableArea = document().view(); |
| + compositor().beginFrame(); |
| + ASSERT_EQ(scrollableArea->maximumScrollOffset().height(), 0); |
| + |
| + // Apply the tilted class so that the animated transition begins. |
| + mainFrame().executeScript(WebScriptSource( |
| + "document.querySelector('#container').className = 'tilted';")); |
| + |
| + // Tick one frame to ensure the animation is started. |
| + document().updateStyleAndLayoutTreeIgnorePendingStylesheets(); |
| + compositor().beginFrame(); |
| + |
| + // Reset paint invalidation tracking. |
| + document().view()->setTracksPaintInvalidations(false); |
| + document().view()->setTracksPaintInvalidations(true); |
| + |
| + // Tick ahead about half way through the animation. The animation isn't |
| + // finished but it should have caused overflow to be added so the main frame |
| + // is scrollable. |
| + document().updateStyleAndLayoutTreeIgnorePendingStylesheets(); |
| + compositor().beginFrame(0.5); |
| + ASSERT_GT(scrollableArea->maximumScrollOffset().height(), 100); |
| + |
| + // Ensure that we invalidated the LayoutView due to the new overflow so that |
| + // scrolling it into the viewport doesn't expose an unpainted region. |
| + std::unique_ptr<JSONArray> invalidations = |
| + document().view()->trackedObjectPaintInvalidationsAsJSON(); |
| + EXPECT_TRUE( |
| + invalidationArrayContains(invalidations.get(), *document().layoutView())); |
| +} |
| + |
| +} // namespace |
| + |
| +} // namespace blink |