| // 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 "ash/shelf/shelf_background_animator.h" |
| |
| #include <memory> |
| |
| #include "ash/animation/animation_change_type.h" |
| #include "ash/public/cpp/ash_switches.h" |
| #include "ash/public/cpp/shelf_config.h" |
| #include "ash/session/test_session_controller_client.h" |
| #include "ash/shelf/shelf.h" |
| #include "ash/shelf/shelf_background_animator_observer.h" |
| #include "ash/shelf/shelf_widget.h" |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/command_line.h" |
| #include "base/macros.h" |
| #include "base/run_loop.h" |
| #include "base/test/test_mock_time_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "ui/gfx/animation/slide_animation.h" |
| #include "ui/gfx/color_palette.h" |
| |
| namespace ash { |
| namespace { |
| |
| // A valid color value that is distinct from any final animation state values. |
| // Used to check if color values are changed during animations. |
| const SkColor kDummyColor = SK_ColorBLUE; |
| |
| // Observer that caches color values for the last observation. This observer |
| // will also call a set callback when ShelfBackgroundAnimator completes an |
| // animation. |
| class TestShelfBackgroundObserver : public ShelfBackgroundAnimatorObserver { |
| public: |
| TestShelfBackgroundObserver() = default; |
| ~TestShelfBackgroundObserver() override = default; |
| |
| SkColor background_color() const { return background_color_; } |
| |
| // Convenience function to get the alpha value from |background_color_|. |
| int GetBackgroundAlpha() const; |
| |
| // Sets |animation_complete_callback_| to be called when animation ends. |
| void SetAnimationCompleteCallback(base::OnceClosure callback); |
| |
| // ShelfBackgroundObserver: |
| void UpdateShelfBackground(SkColor color) override; |
| void OnShelfBackgroundAnimationEnded() override; |
| |
| private: |
| int background_color_ = SK_ColorTRANSPARENT; |
| |
| base::OnceClosure animation_complete_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestShelfBackgroundObserver); |
| }; |
| |
| int TestShelfBackgroundObserver::GetBackgroundAlpha() const { |
| return SkColorGetA(background_color_); |
| } |
| |
| void TestShelfBackgroundObserver::UpdateShelfBackground(SkColor color) { |
| background_color_ = color; |
| } |
| |
| void TestShelfBackgroundObserver::OnShelfBackgroundAnimationEnded() { |
| if (!animation_complete_callback_.is_null()) |
| std::move(animation_complete_callback_).Run(); |
| } |
| |
| void TestShelfBackgroundObserver::SetAnimationCompleteCallback( |
| base::OnceClosure callback) { |
| animation_complete_callback_ = std::move(callback); |
| } |
| |
| } // namespace |
| |
| // Provides internal access to a ShelfBackgroundAnimator instance. |
| class ShelfBackgroundAnimatorTestApi { |
| public: |
| explicit ShelfBackgroundAnimatorTestApi(ShelfBackgroundAnimator* animator) |
| : animator_(animator) {} |
| |
| ~ShelfBackgroundAnimatorTestApi() = default; |
| |
| ShelfBackgroundType previous_background_type() const { |
| return animator_->previous_background_type_; |
| } |
| |
| gfx::SlideAnimation* animator() const { return animator_->animator_.get(); } |
| |
| SkColor shelf_background_target_color() const { |
| return animator_->shelf_background_values_.target_color(); |
| } |
| |
| private: |
| // The instance to provide internal access to. |
| ShelfBackgroundAnimator* animator_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTestApi); |
| }; |
| |
| class ShelfBackgroundAnimatorTest : public AshTestBase { |
| public: |
| ShelfBackgroundAnimatorTest() = default; |
| ~ShelfBackgroundAnimatorTest() override = default; |
| |
| // testing::Test: |
| void SetUp() override; |
| |
| protected: |
| // Convenience wrapper for |animator_|'s PaintBackground(). |
| void PaintBackground( |
| ShelfBackgroundType background_type, |
| AnimationChangeType change_type = AnimationChangeType::IMMEDIATE); |
| |
| // Set all of the color values for the |observer_|. |
| void SetColorValuesOnObserver(SkColor color); |
| |
| // Waits for animation to complete. |
| void WaitForAnimationCompletion(); |
| |
| TestShelfBackgroundObserver observer_; |
| |
| // Test target. |
| ShelfBackgroundAnimator* animator_; |
| |
| // Provides internal access to |animator_|. |
| std::unique_ptr<ShelfBackgroundAnimatorTestApi> test_api_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundAnimatorTest); |
| }; |
| |
| void ShelfBackgroundAnimatorTest::SetUp() { |
| AshTestBase::SetUp(); |
| |
| animator_ = |
| GetPrimaryShelf()->shelf_widget()->background_animator_for_testing(); |
| animator_->AddObserver(&observer_); |
| |
| test_api_.reset(new ShelfBackgroundAnimatorTestApi(animator_)); |
| } |
| |
| void ShelfBackgroundAnimatorTest::PaintBackground( |
| ShelfBackgroundType background_type, |
| AnimationChangeType change_type) { |
| animator_->PaintBackground(background_type, change_type); |
| } |
| |
| void ShelfBackgroundAnimatorTest::SetColorValuesOnObserver(SkColor color) { |
| observer_.UpdateShelfBackground(color); |
| } |
| |
| void ShelfBackgroundAnimatorTest::WaitForAnimationCompletion() { |
| base::RunLoop run_loop; |
| |
| observer_.SetAnimationCompleteCallback(run_loop.QuitWhenIdleClosure()); |
| |
| run_loop.Run(); |
| } |
| |
| // Verify the |previous_background_type_| and |target_background_type_| values |
| // when animating to the same target type multiple times. |
| TEST_F(ShelfBackgroundAnimatorTest, BackgroundTypesWhenAnimatingToSameTarget) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED); |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type()); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type()); |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, test_api_->previous_background_type()); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type()); |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, test_api_->previous_background_type()); |
| } |
| |
| // Verify subsequent calls to PaintBackground() using the |
| // AnimationChangeType::ANIMATE change type are ignored. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| MultipleAnimateCallsToSameTargetAreIgnored) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED); |
| SetColorValuesOnObserver(kDummyColor); |
| animator_->PaintBackground(SHELF_BACKGROUND_DEFAULT, |
| AnimationChangeType::ANIMATE); |
| WaitForAnimationCompletion(); |
| |
| EXPECT_NE(observer_.background_color(), kDummyColor); |
| |
| SetColorValuesOnObserver(kDummyColor); |
| animator_->PaintBackground(SHELF_BACKGROUND_DEFAULT, |
| AnimationChangeType::ANIMATE); |
| |
| EXPECT_EQ(observer_.background_color(), kDummyColor); |
| } |
| |
| // Verify observers are updated with the current values when they are added. |
| TEST_F(ShelfBackgroundAnimatorTest, ObserversUpdatedWhenAdded) { |
| animator_->RemoveObserver(&observer_); |
| SetColorValuesOnObserver(kDummyColor); |
| |
| animator_->AddObserver(&observer_); |
| |
| EXPECT_NE(observer_.background_color(), kDummyColor); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_DEFAULT state. |
| TEST_F(ShelfBackgroundAnimatorTest, DefaultBackground) { |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, animator_->target_background_type()); |
| EXPECT_EQ((int)SkColorGetA(ShelfConfig::Get()->GetDefaultShelfColor()), |
| observer_.GetBackgroundAlpha()); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_MAXIMIZED state. |
| TEST_F(ShelfBackgroundAnimatorTest, MaximizedBackground) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, animator_->target_background_type()); |
| EXPECT_EQ((int)SkColorGetA(ShelfConfig::Get()->GetMaximizedShelfColor()), |
| observer_.GetBackgroundAlpha()); |
| } |
| |
| // Verify the alpha values for the SHELF_BACKGROUND_APP_LIST state. |
| TEST_F(ShelfBackgroundAnimatorTest, FullscreenAppListBackground) { |
| PaintBackground(SHELF_BACKGROUND_APP_LIST); |
| |
| EXPECT_EQ(SHELF_BACKGROUND_APP_LIST, animator_->target_background_type()); |
| EXPECT_EQ((int)SkColorGetA(ShelfConfig::Get()->GetShelfWithAppListColor()), |
| observer_.GetBackgroundAlpha()); |
| } |
| |
| TEST_F(ShelfBackgroundAnimatorTest, |
| AnimatorIsDetroyedWhenCompletingSuccessfully) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED, AnimationChangeType::ANIMATE); |
| EXPECT_TRUE(test_api_->animator()); |
| WaitForAnimationCompletion(); |
| |
| EXPECT_FALSE(test_api_->animator()); |
| } |
| |
| TEST_F(ShelfBackgroundAnimatorTest, |
| AnimatorDestroyedWhenChangingBackgroundImmediately) { |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED, AnimationChangeType::ANIMATE); |
| EXPECT_TRUE(test_api_->animator()); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT, AnimationChangeType::IMMEDIATE); |
| EXPECT_FALSE(test_api_->animator()); |
| } |
| |
| // Verify that existing animator is used when animating to the previous state. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| ExistingAnimatorIsReusedWhenAnimatingToPreviousState) { |
| // First PaintBackground() must be immediate so that the |
| // ShelfBackgroundAnimator has its color set correctly. |
| PaintBackground(SHELF_BACKGROUND_DEFAULT, AnimationChangeType::IMMEDIATE); |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED, AnimationChangeType::ANIMATE); |
| |
| const gfx::SlideAnimation* animator = test_api_->animator(); |
| EXPECT_TRUE(animator); |
| |
| PaintBackground(SHELF_BACKGROUND_DEFAULT, AnimationChangeType::ANIMATE); |
| |
| EXPECT_EQ(animator, test_api_->animator()); |
| } |
| |
| // Verify that existing animator is not re-used when the target background isn't |
| // the same as the previous background. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| ExistingAnimatorNotReusedWhenTargetBackgroundNotPreviousBackground) { |
| PaintBackground(SHELF_BACKGROUND_APP_LIST, AnimationChangeType::ANIMATE); |
| |
| const gfx::SlideAnimation* animator = test_api_->animator(); |
| EXPECT_TRUE(animator); |
| |
| EXPECT_NE(SHELF_BACKGROUND_MAXIMIZED, test_api_->previous_background_type()); |
| PaintBackground(SHELF_BACKGROUND_MAXIMIZED, AnimationChangeType::ANIMATE); |
| |
| EXPECT_NE(animator, test_api_->animator()); |
| } |
| |
| // Verify observers are always notified, even when alpha values don't change. |
| TEST_F(ShelfBackgroundAnimatorTest, |
| ObserversAreNotifiedWhenSnappingToSameTargetBackground) { |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| SetColorValuesOnObserver(kDummyColor); |
| PaintBackground(SHELF_BACKGROUND_DEFAULT); |
| |
| EXPECT_NE(observer_.background_color(), kDummyColor); |
| } |
| |
| class ShelfBackgroundTargetColorTest : public NoSessionAshTestBase { |
| public: |
| ShelfBackgroundTargetColorTest() = default; |
| ~ShelfBackgroundTargetColorTest() override = default; |
| |
| protected: |
| // Helper function to notify session state changes. |
| void NotifySessionStateChanged(session_manager::SessionState state) { |
| GetSessionControllerClient()->SetSessionState(state); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ShelfBackgroundTargetColorTest); |
| }; |
| |
| // Verify the target color of the shelf background is updated based on session |
| // state, starting from LOGIN_PRIMARY. |
| TEST_F(ShelfBackgroundTargetColorTest, ShelfBackgroundColorUpdatedFromLogin) { |
| ShelfBackgroundAnimatorTestApi test_api( |
| Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow()) |
| ->shelf_widget() |
| ->background_animator_for_testing()); |
| |
| NotifySessionStateChanged(session_manager::SessionState::LOGIN_PRIMARY); |
| EXPECT_EQ(test_api.shelf_background_target_color(), SK_ColorTRANSPARENT); |
| |
| SimulateUserLogin("user1@test.com"); |
| |
| NotifySessionStateChanged(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(test_api.shelf_background_target_color(), |
| ShelfConfig::Get()->GetDefaultShelfColor()); |
| } |
| |
| // Verify the target color of the shelf background is updated based on session |
| // state, starting from OOBE. |
| TEST_F(ShelfBackgroundTargetColorTest, ShelfBackgroundColorUpdatedFromOOBE) { |
| ShelfBackgroundAnimatorTestApi test_api( |
| Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow()) |
| ->shelf_widget() |
| ->background_animator_for_testing()); |
| |
| NotifySessionStateChanged(session_manager::SessionState::OOBE); |
| EXPECT_EQ(test_api.shelf_background_target_color(), SK_ColorTRANSPARENT); |
| |
| SimulateUserLogin("user1@test.com"); |
| |
| NotifySessionStateChanged( |
| session_manager::SessionState::LOGGED_IN_NOT_ACTIVE); |
| EXPECT_EQ(test_api.shelf_background_target_color(), SK_ColorTRANSPARENT); |
| |
| NotifySessionStateChanged(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(test_api.shelf_background_target_color(), |
| ShelfConfig::Get()->GetDefaultShelfColor()); |
| } |
| |
| } // namespace ash |