Chromium Code Reviews| Index: third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
| diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
| index 8e99446dee9e8ad1b9c2214f17fc9ed79f334952..cc665a95d8e4f433b589de568dec396d959d7603 100644 |
| --- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
| +++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
| @@ -42,11 +42,16 @@ |
| #include "core/animation/animatable/AnimatableTransform.h" |
| #include "core/animation/animatable/AnimatableValueTestHelper.h" |
| #include "core/dom/Document.h" |
| +#include "core/layout/LayoutBox.h" |
| #include "core/layout/LayoutObject.h" |
| +#include "core/loader/EmptyClients.h" |
| +#include "core/paint/PaintLayer.h" |
| #include "core/testing/DummyPageHolder.h" |
| #include "platform/geometry/FloatBox.h" |
| #include "platform/geometry/IntSize.h" |
| #include "platform/graphics/filters/FilterOperations.h" |
| +#include "platform/graphics/paint/PaintArtifact.h" |
| +#include "platform/graphics/test/FakeGraphicsLayerFactory.h" |
| #include "platform/transforms/TransformOperations.h" |
| #include "platform/transforms/TranslateTransformOperation.h" |
| #include "public/platform/WebCompositorAnimation.h" |
| @@ -65,6 +70,15 @@ using ::testing::Ref; |
| using ::testing::Return; |
| using ::testing::_; |
| +class MockChromeClient : public EmptyChromeClient { |
| +public: |
| + MockChromeClient() {} |
| + GraphicsLayerFactory* graphicsLayerFactory() const override |
| + { |
| + return FakeGraphicsLayerFactory::instance(); |
| + } |
| +}; |
| + |
| class AnimationCompositorAnimationsTest : public AnimationCompositorAnimationsTestBase { |
| protected: |
| RefPtr<TimingFunction> m_linearTimingFunction; |
| @@ -82,11 +96,14 @@ protected: |
| RefPtrWillBePersistent<Document> m_document; |
| RefPtrWillBePersistent<Element> m_element; |
| Persistent<AnimationTimeline> m_timeline; |
| + OwnPtrWillBePersistent<MockChromeClient> m_chromeClient; |
| OwnPtr<DummyPageHolder> m_pageHolder; |
| WebCompositorSupportMock m_mockCompositor; |
| virtual void SetUp() |
| { |
| + m_chromeClient = adoptPtrWillBeNoop(new MockChromeClient); |
| + |
| AnimationCompositorAnimationsTestBase::SetUp(); |
| setCompositorForTesting(m_mockCompositor); |
| @@ -111,7 +128,12 @@ protected: |
| EXPECT_CALL(m_mockCompositor, createAnimationTimeline()) |
| .WillOnce(Return(new WebCompositorAnimationTimelineMock())); |
| } |
| - m_pageHolder = DummyPageHolder::create(); |
| + |
| + Page::PageClients clients; |
| + fillWithEmptyClients(clients); |
| + clients.chromeClient = m_chromeClient.get(); |
| + m_pageHolder = DummyPageHolder::create(IntSize(), &clients); |
| + |
| m_document = &m_pageHolder->document(); |
| m_document->animationClock().resetTimeForTesting(); |
| @@ -264,11 +286,38 @@ public: |
| m_document->compositorPendingAnimations().update(false); |
| m_timeline->serviceAnimations(TimingUpdateForAnimationFrame); |
| } |
| + |
| + void preCommit(Animation* animation) |
| + { |
| + WebFloatAnimationCurveMock* mockCurvePtr = new WebFloatAnimationCurveMock; |
| + ExpectationSet usesMockCurve; |
| + EXPECT_CALL(m_mockCompositor, createFloatAnimationCurve()) |
| + .WillOnce(Return(mockCurvePtr)); |
| + |
| + WebCompositorAnimationMock* mockAnimationPtr = new WebCompositorAnimationMock(WebCompositorAnimation::TargetPropertyOpacity); |
| + EXPECT_CALL(m_mockCompositor, createAnimation(Ref(*mockCurvePtr), WebCompositorAnimation::TargetPropertyOpacity, _, _)) |
| + .WillOnce(Return(mockAnimationPtr)); |
| + |
| + if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) { |
| + EXPECT_TRUE(m_timeline->compositorTimeline()); |
| + EXPECT_CALL(m_mockCompositor, createAnimationPlayer()) |
| + .WillOnce(Return(new WebCompositorAnimationPlayerMock())); |
| + } |
| + |
| + const int compositorGroup = 1; |
| + DisableCompositingQueryAsserts disabler; |
| + EXPECT_TRUE(animation->preCommit(compositorGroup, true)); |
| + |
| + if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) |
| + EXPECT_TRUE(animation->compositorPlayer()); |
| + |
| + EXPECT_TRUE(animation->hasActiveAnimationsOnCompositor()); |
| + } |
| }; |
| -class LayoutObjectProxy : public LayoutObject { |
| +class LayoutObjectProxy : public LayoutBox { |
| public: |
| - static LayoutObjectProxy* create(Node* node) |
| + static LayoutObjectProxy* create(ContainerNode* node) |
| { |
| return new LayoutObjectProxy(node); |
| } |
| @@ -279,12 +328,27 @@ public: |
| } |
| const char* name() const override { return nullptr; } |
| - void layout() override { } |
| + |
| + void createCompositedLayer() |
| + { |
| + RefPtr<ComputedStyle> computedStyle = ComputedStyle::create(); |
| + styleWillChange(StyleDifference(), *computedStyle.get()); |
| + setStyle(computedStyle); |
| + styleDidChange(StyleDifference(), nullptr); |
| + |
| + DisableCompositingQueryAsserts disabler; |
| + layer()->ensureCompositedLayerMapping(); |
| + } |
| private: |
| - explicit LayoutObjectProxy(Node* node) |
| - : LayoutObject(node) |
| + explicit LayoutObjectProxy(ContainerNode* node) |
| + : LayoutBox(node) |
| + { |
| + } |
| + |
| + PaintLayerType layerTypeRequired() const override |
| { |
| + return NormalPaintLayer; |
| } |
| }; |
| @@ -1175,12 +1239,51 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimationWithTiming |
| result[0].clear(); |
| } |
| +TEST_F(AnimationCompositorAnimationsTest, CancelCompositorAnimationIfAnimationDisposed) |
| +{ |
| + RefPtrWillBePersistent<Element> element = m_document->createElement("shared", ASSERT_NO_EXCEPTION); |
| + |
| + LayoutObjectProxy* layoutObject = LayoutObjectProxy::create(element.get()); |
| + element->setLayoutObject(layoutObject); |
| + layoutObject->createCompositedLayer(); |
| + |
| + AnimatableValueKeyframeVector keyFrames; |
| + keyFrames.append(createDefaultKeyframe(CSSPropertyOpacity, EffectModel::CompositeReplace, 0.0).get()); |
| + keyFrames.append(createDefaultKeyframe(CSSPropertyOpacity, EffectModel::CompositeReplace, 1.0).get()); |
| + EffectModel* animationEffect = AnimatableValueKeyframeEffectModel::create(keyFrames); |
| + |
| + Timing timing; |
| + timing.iterationDuration = 1.f; |
| + |
| + KeyframeEffect* keyframeEffect = KeyframeEffect::create(element.get(), animationEffect, timing); |
| + Animation* animation = m_timeline->play(keyframeEffect); |
| + EXPECT_TRUE(animation->isCandidateForAnimationOnCompositor()); |
| + |
| + preCommit(animation); |
| + |
| + animation->dispose(); |
| + animation->cancelAnimationOnCompositor(); |
|
Ian Vollick
2015/12/29 20:32:24
I may be misreading the purpose of this test -- it
loyso (OOO)
2015/12/29 23:54:25
That was just my assumption about the crash (ideas
|
| + |
| + EXPECT_FALSE(animation->hasActiveAnimationsOnCompositor()); |
| + |
| + simulateFrame(0); |
| + EXPECT_EQ(1U, element->elementAnimations()->animations().size()); |
| + simulateFrame(1.); |
| + |
| + element->setLayoutObject(nullptr); |
| + LayoutObjectProxy::dispose(layoutObject); |
| + |
| + Heap::collectAllGarbage(); |
| + EXPECT_TRUE(element->elementAnimations()->animations().isEmpty()); |
| +} |
| + |
| TEST_F(AnimationCompositorAnimationsTest, CancelIncompatibleCompositorAnimations) |
| { |
| RefPtrWillBePersistent<Element> element = m_document->createElement("shared", ASSERT_NO_EXCEPTION); |
| LayoutObjectProxy* layoutObject = LayoutObjectProxy::create(element.get()); |
| element->setLayoutObject(layoutObject); |
| + layoutObject->createCompositedLayer(); |
| AnimatableValueKeyframeVector keyFrames; |
| keyFrames.append(createDefaultKeyframe(CSSPropertyOpacity, EffectModel::CompositeReplace, 0.0).get()); |
| @@ -1194,18 +1297,15 @@ TEST_F(AnimationCompositorAnimationsTest, CancelIncompatibleCompositorAnimations |
| // The first animation for opacity is ok to run on compositor. |
| KeyframeEffect* keyframeEffect1 = KeyframeEffect::create(element.get(), animationEffect1, timing); |
| Animation* animation1 = m_timeline->play(keyframeEffect1); |
| - EXPECT_TRUE(CompositorAnimations::instance()->isCandidateForAnimationOnCompositor(timing, *element.get(), animation1, *animationEffect1, 1)); |
| + EXPECT_TRUE(animation1->isCandidateForAnimationOnCompositor()); |
| - // simulate KeyframeEffect::maybeStartAnimationOnCompositor |
| - Vector<int> compositorAnimationIds; |
| - compositorAnimationIds.append(1); |
| - keyframeEffect1->setCompositorAnimationIdsForTesting(compositorAnimationIds); |
| - EXPECT_TRUE(animation1->hasActiveAnimationsOnCompositor()); |
| + preCommit(animation1); |
| // The second animation for opacity is not ok to run on compositor. |
| KeyframeEffect* keyframeEffect2 = KeyframeEffect::create(element.get(), animationEffect2, timing); |
| Animation* animation2 = m_timeline->play(keyframeEffect2); |
| EXPECT_FALSE(CompositorAnimations::instance()->isCandidateForAnimationOnCompositor(timing, *element.get(), animation2, *animationEffect2, 1)); |
| + EXPECT_FALSE(animation2->isCandidateForAnimationOnCompositor()); |
| EXPECT_FALSE(animation2->hasActiveAnimationsOnCompositor()); |
| // A fallback to blink implementation needed, so cancel all compositor-side opacity animations for this element. |