123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- // Copyright 2014 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 "ui/compositor/layer_owner.h"
- #include <utility>
- #include "base/memory/raw_ptr.h"
- #include "base/test/null_task_runner.h"
- #include "cc/animation/animation.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/compositor/compositor.h"
- #include "ui/compositor/layer.h"
- #include "ui/compositor/layer_animation_observer.h"
- #include "ui/compositor/layer_animator.h"
- #include "ui/compositor/layer_delegate.h"
- #include "ui/compositor/scoped_animation_duration_scale_mode.h"
- #include "ui/compositor/scoped_layer_animation_settings.h"
- #include "ui/compositor/test/test_context_factories.h"
- #include "ui/gfx/native_widget_types.h"
- namespace ui {
- namespace {
- // An animation observer that confirms upon animation completion, that the
- // compositor is not null.
- class TestLayerAnimationObserver : public ImplicitAnimationObserver {
- public:
- explicit TestLayerAnimationObserver(Layer* layer) : layer_(layer) {}
- TestLayerAnimationObserver(const TestLayerAnimationObserver&) = delete;
- TestLayerAnimationObserver& operator=(const TestLayerAnimationObserver&) =
- delete;
- ~TestLayerAnimationObserver() override = default;
- // ImplicitAnimationObserver:
- void OnImplicitAnimationsCompleted() override {
- EXPECT_NE(nullptr, layer_->GetCompositor());
- }
- private:
- raw_ptr<Layer> layer_;
- };
- class LayerOwnerForTesting : public LayerOwner {
- public:
- explicit LayerOwnerForTesting(std::unique_ptr<Layer> layer) {
- SetLayer(std::move(layer));
- }
- void DestroyLayerForTesting() { DestroyLayer(); }
- };
- // Test fixture for LayerOwner tests that require a ui::Compositor.
- class LayerOwnerTestWithCompositor : public testing::Test {
- public:
- LayerOwnerTestWithCompositor();
- LayerOwnerTestWithCompositor(const LayerOwnerTestWithCompositor&) = delete;
- LayerOwnerTestWithCompositor& operator=(const LayerOwnerTestWithCompositor&) =
- delete;
- ~LayerOwnerTestWithCompositor() override;
- void SetUp() override;
- void TearDown() override;
- protected:
- ui::Compositor* compositor() { return compositor_.get(); }
- private:
- std::unique_ptr<ui::TestContextFactories> context_factories_;
- std::unique_ptr<ui::Compositor> compositor_;
- };
- LayerOwnerTestWithCompositor::LayerOwnerTestWithCompositor() {
- }
- LayerOwnerTestWithCompositor::~LayerOwnerTestWithCompositor() {
- }
- void LayerOwnerTestWithCompositor::SetUp() {
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- new base::NullTaskRunner();
- const bool enable_pixel_output = false;
- context_factories_ =
- std::make_unique<ui::TestContextFactories>(enable_pixel_output);
- compositor_ = std::make_unique<ui::Compositor>(
- context_factories_->GetContextFactory()->AllocateFrameSinkId(),
- context_factories_->GetContextFactory(), task_runner,
- false /* enable_pixel_canvas */);
- compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
- }
- void LayerOwnerTestWithCompositor::TearDown() {
- compositor_.reset();
- context_factories_.reset();
- }
- } // namespace
- TEST_F(LayerOwnerTestWithCompositor, RecreateRootLayerWithCompositor) {
- LayerOwnerForTesting owner(std::make_unique<Layer>());
- Layer* layer = owner.layer();
- compositor()->SetRootLayer(layer);
- std::unique_ptr<Layer> layer_copy = owner.RecreateLayer();
- EXPECT_EQ(compositor(), owner.layer()->GetCompositor());
- EXPECT_EQ(owner.layer(), compositor()->root_layer());
- EXPECT_EQ(nullptr, layer_copy->GetCompositor());
- }
- // Tests that recreating the root layer, while one of its children is animating,
- // properly updates the compositor. So that compositor is not null for observers
- // of animations being cancelled.
- TEST_F(LayerOwnerTestWithCompositor, RecreateRootLayerDuringAnimation) {
- LayerOwnerForTesting owner(std::make_unique<Layer>());
- Layer* layer = owner.layer();
- compositor()->SetRootLayer(layer);
- std::unique_ptr<Layer> child(new Layer);
- child->SetBounds(gfx::Rect(0, 0, 100, 100));
- layer->Add(child.get());
- // This observer checks that the compositor of |child| is not null upon
- // animation completion.
- std::unique_ptr<TestLayerAnimationObserver> observer(
- new TestLayerAnimationObserver(child.get()));
- std::unique_ptr<ui::ScopedAnimationDurationScaleMode> long_duration_animation(
- new ui::ScopedAnimationDurationScaleMode(
- ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
- {
- ui::ScopedLayerAnimationSettings animation(child->GetAnimator());
- animation.SetTransitionDuration(base::Milliseconds(1000));
- animation.AddObserver(observer.get());
- gfx::Transform transform;
- transform.Scale(0.5f, 0.5f);
- child->SetTransform(transform);
- }
- std::unique_ptr<Layer> layer_copy = owner.RecreateLayer();
- }
- // Tests that recreating a non-root layer, while one of its children is
- // animating, properly updates the compositor. So that compositor is not null
- // for observers of animations being cancelled.
- TEST_F(LayerOwnerTestWithCompositor, RecreateNonRootLayerDuringAnimation) {
- std::unique_ptr<Layer> root_layer(new Layer);
- compositor()->SetRootLayer(root_layer.get());
- LayerOwnerForTesting owner(std::make_unique<Layer>());
- Layer* layer = owner.layer();
- root_layer->Add(layer);
- std::unique_ptr<Layer> child(new Layer);
- child->SetBounds(gfx::Rect(0, 0, 100, 100));
- layer->Add(child.get());
- // This observer checks that the compositor of |child| is not null upon
- // animation completion.
- std::unique_ptr<TestLayerAnimationObserver> observer(
- new TestLayerAnimationObserver(child.get()));
- std::unique_ptr<ui::ScopedAnimationDurationScaleMode> long_duration_animation(
- new ui::ScopedAnimationDurationScaleMode(
- ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
- {
- ui::ScopedLayerAnimationSettings animation(child->GetAnimator());
- animation.SetTransitionDuration(base::Milliseconds(1000));
- animation.AddObserver(observer.get());
- gfx::Transform transform;
- transform.Scale(0.5f, 0.5f);
- child->SetTransform(transform);
- }
- std::unique_ptr<Layer> layer_copy = owner.RecreateLayer();
- }
- // Tests that if LayerOwner-derived class destroys layer, then
- // LayerAnimator's animation becomes detached from compositor timeline.
- TEST_F(LayerOwnerTestWithCompositor, DetachTimelineOnAnimatorDeletion) {
- std::unique_ptr<Layer> root_layer(new Layer);
- compositor()->SetRootLayer(root_layer.get());
- LayerOwnerForTesting owner(std::make_unique<Layer>());
- Layer* layer = owner.layer();
- layer->SetOpacity(0.5f);
- root_layer->Add(layer);
- scoped_refptr<cc::Animation> animation =
- layer->GetAnimator()->GetAnimationForTesting();
- EXPECT_TRUE(animation);
- EXPECT_TRUE(animation->animation_timeline());
- // Destroying layer/animator must detach animator's animation from timeline.
- owner.DestroyLayerForTesting();
- EXPECT_FALSE(animation->animation_timeline());
- }
- // Tests that if we run threaded opacity animation on already added layer
- // then LayerAnimator's animation becomes attached to timeline.
- TEST_F(LayerOwnerTestWithCompositor,
- AttachTimelineIfAnimatorCreatedAfterSetCompositor) {
- std::unique_ptr<Layer> root_layer(new Layer);
- compositor()->SetRootLayer(root_layer.get());
- LayerOwnerForTesting owner(std::make_unique<Layer>());
- Layer* layer = owner.layer();
- root_layer->Add(layer);
- layer->SetOpacity(0.5f);
- scoped_refptr<cc::Animation> animation =
- layer->GetAnimator()->GetAnimationForTesting();
- EXPECT_TRUE(animation);
- EXPECT_TRUE(animation->animation_timeline());
- }
- namespace {
- class TestLayerDelegate : public LayerDelegate {
- public:
- explicit TestLayerDelegate(ui::LayerOwner* owner) : owner_(owner) {}
- TestLayerDelegate(TestLayerDelegate&) = delete;
- TestLayerDelegate& operator=(TestLayerDelegate&) = delete;
- ~TestLayerDelegate() override = default;
- // LayerDelegate:
- void OnPaintLayer(const PaintContext& context) override {}
- void OnDeviceScaleFactorChanged(float old_device_scale_factor,
- float new_device_scale_factor) override {}
- void OnLayerBoundsChanged(const gfx::Rect& old_bounds,
- PropertyChangeReason reason) override {
- owner_->RecreateLayer();
- }
- private:
- raw_ptr<ui::LayerOwner> owner_;
- };
- } // namespace
- // Test if recreating a layer in OnLayerBoundsChanged will not
- // cause a use-after-free.
- TEST_F(LayerOwnerTestWithCompositor, DeleteOnLayerBoundsChanged) {
- LayerOwnerForTesting owner(std::make_unique<Layer>());
- TestLayerDelegate delegate(&owner);
- owner.layer()->set_delegate(&delegate);
- owner.layer()->SetBounds(gfx::Rect(100, 100));
- }
- } // namespace ui
|