layer_owner_unittest.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/compositor/layer_owner.h"
  5. #include <utility>
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/test/null_task_runner.h"
  8. #include "cc/animation/animation.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. #include "ui/compositor/compositor.h"
  11. #include "ui/compositor/layer.h"
  12. #include "ui/compositor/layer_animation_observer.h"
  13. #include "ui/compositor/layer_animator.h"
  14. #include "ui/compositor/layer_delegate.h"
  15. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  16. #include "ui/compositor/scoped_layer_animation_settings.h"
  17. #include "ui/compositor/test/test_context_factories.h"
  18. #include "ui/gfx/native_widget_types.h"
  19. namespace ui {
  20. namespace {
  21. // An animation observer that confirms upon animation completion, that the
  22. // compositor is not null.
  23. class TestLayerAnimationObserver : public ImplicitAnimationObserver {
  24. public:
  25. explicit TestLayerAnimationObserver(Layer* layer) : layer_(layer) {}
  26. TestLayerAnimationObserver(const TestLayerAnimationObserver&) = delete;
  27. TestLayerAnimationObserver& operator=(const TestLayerAnimationObserver&) =
  28. delete;
  29. ~TestLayerAnimationObserver() override = default;
  30. // ImplicitAnimationObserver:
  31. void OnImplicitAnimationsCompleted() override {
  32. EXPECT_NE(nullptr, layer_->GetCompositor());
  33. }
  34. private:
  35. raw_ptr<Layer> layer_;
  36. };
  37. class LayerOwnerForTesting : public LayerOwner {
  38. public:
  39. explicit LayerOwnerForTesting(std::unique_ptr<Layer> layer) {
  40. SetLayer(std::move(layer));
  41. }
  42. void DestroyLayerForTesting() { DestroyLayer(); }
  43. };
  44. // Test fixture for LayerOwner tests that require a ui::Compositor.
  45. class LayerOwnerTestWithCompositor : public testing::Test {
  46. public:
  47. LayerOwnerTestWithCompositor();
  48. LayerOwnerTestWithCompositor(const LayerOwnerTestWithCompositor&) = delete;
  49. LayerOwnerTestWithCompositor& operator=(const LayerOwnerTestWithCompositor&) =
  50. delete;
  51. ~LayerOwnerTestWithCompositor() override;
  52. void SetUp() override;
  53. void TearDown() override;
  54. protected:
  55. ui::Compositor* compositor() { return compositor_.get(); }
  56. private:
  57. std::unique_ptr<ui::TestContextFactories> context_factories_;
  58. std::unique_ptr<ui::Compositor> compositor_;
  59. };
  60. LayerOwnerTestWithCompositor::LayerOwnerTestWithCompositor() {
  61. }
  62. LayerOwnerTestWithCompositor::~LayerOwnerTestWithCompositor() {
  63. }
  64. void LayerOwnerTestWithCompositor::SetUp() {
  65. scoped_refptr<base::SingleThreadTaskRunner> task_runner =
  66. new base::NullTaskRunner();
  67. const bool enable_pixel_output = false;
  68. context_factories_ =
  69. std::make_unique<ui::TestContextFactories>(enable_pixel_output);
  70. compositor_ = std::make_unique<ui::Compositor>(
  71. context_factories_->GetContextFactory()->AllocateFrameSinkId(),
  72. context_factories_->GetContextFactory(), task_runner,
  73. false /* enable_pixel_canvas */);
  74. compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
  75. }
  76. void LayerOwnerTestWithCompositor::TearDown() {
  77. compositor_.reset();
  78. context_factories_.reset();
  79. }
  80. } // namespace
  81. TEST_F(LayerOwnerTestWithCompositor, RecreateRootLayerWithCompositor) {
  82. LayerOwnerForTesting owner(std::make_unique<Layer>());
  83. Layer* layer = owner.layer();
  84. compositor()->SetRootLayer(layer);
  85. std::unique_ptr<Layer> layer_copy = owner.RecreateLayer();
  86. EXPECT_EQ(compositor(), owner.layer()->GetCompositor());
  87. EXPECT_EQ(owner.layer(), compositor()->root_layer());
  88. EXPECT_EQ(nullptr, layer_copy->GetCompositor());
  89. }
  90. // Tests that recreating the root layer, while one of its children is animating,
  91. // properly updates the compositor. So that compositor is not null for observers
  92. // of animations being cancelled.
  93. TEST_F(LayerOwnerTestWithCompositor, RecreateRootLayerDuringAnimation) {
  94. LayerOwnerForTesting owner(std::make_unique<Layer>());
  95. Layer* layer = owner.layer();
  96. compositor()->SetRootLayer(layer);
  97. std::unique_ptr<Layer> child(new Layer);
  98. child->SetBounds(gfx::Rect(0, 0, 100, 100));
  99. layer->Add(child.get());
  100. // This observer checks that the compositor of |child| is not null upon
  101. // animation completion.
  102. std::unique_ptr<TestLayerAnimationObserver> observer(
  103. new TestLayerAnimationObserver(child.get()));
  104. std::unique_ptr<ui::ScopedAnimationDurationScaleMode> long_duration_animation(
  105. new ui::ScopedAnimationDurationScaleMode(
  106. ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
  107. {
  108. ui::ScopedLayerAnimationSettings animation(child->GetAnimator());
  109. animation.SetTransitionDuration(base::Milliseconds(1000));
  110. animation.AddObserver(observer.get());
  111. gfx::Transform transform;
  112. transform.Scale(0.5f, 0.5f);
  113. child->SetTransform(transform);
  114. }
  115. std::unique_ptr<Layer> layer_copy = owner.RecreateLayer();
  116. }
  117. // Tests that recreating a non-root layer, while one of its children is
  118. // animating, properly updates the compositor. So that compositor is not null
  119. // for observers of animations being cancelled.
  120. TEST_F(LayerOwnerTestWithCompositor, RecreateNonRootLayerDuringAnimation) {
  121. std::unique_ptr<Layer> root_layer(new Layer);
  122. compositor()->SetRootLayer(root_layer.get());
  123. LayerOwnerForTesting owner(std::make_unique<Layer>());
  124. Layer* layer = owner.layer();
  125. root_layer->Add(layer);
  126. std::unique_ptr<Layer> child(new Layer);
  127. child->SetBounds(gfx::Rect(0, 0, 100, 100));
  128. layer->Add(child.get());
  129. // This observer checks that the compositor of |child| is not null upon
  130. // animation completion.
  131. std::unique_ptr<TestLayerAnimationObserver> observer(
  132. new TestLayerAnimationObserver(child.get()));
  133. std::unique_ptr<ui::ScopedAnimationDurationScaleMode> long_duration_animation(
  134. new ui::ScopedAnimationDurationScaleMode(
  135. ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
  136. {
  137. ui::ScopedLayerAnimationSettings animation(child->GetAnimator());
  138. animation.SetTransitionDuration(base::Milliseconds(1000));
  139. animation.AddObserver(observer.get());
  140. gfx::Transform transform;
  141. transform.Scale(0.5f, 0.5f);
  142. child->SetTransform(transform);
  143. }
  144. std::unique_ptr<Layer> layer_copy = owner.RecreateLayer();
  145. }
  146. // Tests that if LayerOwner-derived class destroys layer, then
  147. // LayerAnimator's animation becomes detached from compositor timeline.
  148. TEST_F(LayerOwnerTestWithCompositor, DetachTimelineOnAnimatorDeletion) {
  149. std::unique_ptr<Layer> root_layer(new Layer);
  150. compositor()->SetRootLayer(root_layer.get());
  151. LayerOwnerForTesting owner(std::make_unique<Layer>());
  152. Layer* layer = owner.layer();
  153. layer->SetOpacity(0.5f);
  154. root_layer->Add(layer);
  155. scoped_refptr<cc::Animation> animation =
  156. layer->GetAnimator()->GetAnimationForTesting();
  157. EXPECT_TRUE(animation);
  158. EXPECT_TRUE(animation->animation_timeline());
  159. // Destroying layer/animator must detach animator's animation from timeline.
  160. owner.DestroyLayerForTesting();
  161. EXPECT_FALSE(animation->animation_timeline());
  162. }
  163. // Tests that if we run threaded opacity animation on already added layer
  164. // then LayerAnimator's animation becomes attached to timeline.
  165. TEST_F(LayerOwnerTestWithCompositor,
  166. AttachTimelineIfAnimatorCreatedAfterSetCompositor) {
  167. std::unique_ptr<Layer> root_layer(new Layer);
  168. compositor()->SetRootLayer(root_layer.get());
  169. LayerOwnerForTesting owner(std::make_unique<Layer>());
  170. Layer* layer = owner.layer();
  171. root_layer->Add(layer);
  172. layer->SetOpacity(0.5f);
  173. scoped_refptr<cc::Animation> animation =
  174. layer->GetAnimator()->GetAnimationForTesting();
  175. EXPECT_TRUE(animation);
  176. EXPECT_TRUE(animation->animation_timeline());
  177. }
  178. namespace {
  179. class TestLayerDelegate : public LayerDelegate {
  180. public:
  181. explicit TestLayerDelegate(ui::LayerOwner* owner) : owner_(owner) {}
  182. TestLayerDelegate(TestLayerDelegate&) = delete;
  183. TestLayerDelegate& operator=(TestLayerDelegate&) = delete;
  184. ~TestLayerDelegate() override = default;
  185. // LayerDelegate:
  186. void OnPaintLayer(const PaintContext& context) override {}
  187. void OnDeviceScaleFactorChanged(float old_device_scale_factor,
  188. float new_device_scale_factor) override {}
  189. void OnLayerBoundsChanged(const gfx::Rect& old_bounds,
  190. PropertyChangeReason reason) override {
  191. owner_->RecreateLayer();
  192. }
  193. private:
  194. raw_ptr<ui::LayerOwner> owner_;
  195. };
  196. } // namespace
  197. // Test if recreating a layer in OnLayerBoundsChanged will not
  198. // cause a use-after-free.
  199. TEST_F(LayerOwnerTestWithCompositor, DeleteOnLayerBoundsChanged) {
  200. LayerOwnerForTesting owner(std::make_unique<Layer>());
  201. TestLayerDelegate delegate(&owner);
  202. owner.layer()->set_delegate(&delegate);
  203. owner.layer()->SetBounds(gfx::Rect(100, 100));
  204. }
  205. } // namespace ui