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 |