diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-05 19:32:58 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-05 19:32:58 +0000 |
commit | d86de6b25c7b9020d0795ff13de2fc29aead20af (patch) | |
tree | eb3fc1b5f44dbbcc431046698fa23b8c4fe33b9a /ash/desktop_background | |
parent | 7502551150ee02157a30ee10fa8992f858accc00 (diff) | |
download | chromium_src-d86de6b25c7b9020d0795ff13de2fc29aead20af.zip chromium_src-d86de6b25c7b9020d0795ff13de2fc29aead20af.tar.gz chromium_src-d86de6b25c7b9020d0795ff13de2fc29aead20af.tar.bz2 |
ash: Add tests for desktop background, fix names
* Add basic unit tests for DesktopBackgroundController
* Add test for race condition between Chrome OS resume from
sleep/wallpaper refresh and screen unlock. See bug.
* Rename ComponentWrapper class to AnimatingDesktopController
* Rename kComponentWrapper key to kAnimatingDesktopController
* Rename kWindowDesktopComponent key to kDesktopController
* Fix lots of component vs. controller names
BUG=149043
TEST=added DesktopBackgroundControllerTest.*
Review URL: https://chromiumcodereview.appspot.com/11026047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@160449 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/desktop_background')
6 files changed, 263 insertions, 65 deletions
diff --git a/ash/desktop_background/desktop_background_controller.cc b/ash/desktop_background/desktop_background_controller.cc index ae22b55..ca697d6 100644 --- a/ash/desktop_background/desktop_background_controller.cc +++ b/ash/desktop_background/desktop_background_controller.cc @@ -24,8 +24,8 @@ #include "ui/views/widget/widget.h" using ash::internal::DesktopBackgroundWidgetController; -using ash::internal::kComponentWrapper; -using ash::internal::kWindowDesktopComponent; +using ash::internal::kAnimatingDesktopController; +using ash::internal::kDesktopController; namespace ash { namespace { @@ -154,7 +154,7 @@ void DesktopBackgroundController::OnRootWindowAdded( } } - InstallComponent(root_window); + InstallDesktopController(root_window); } void DesktopBackgroundController::CacheDefaultWallpaper(int index) { @@ -221,7 +221,7 @@ void DesktopBackgroundController::SetDesktopBackgroundSolidColorMode( background_color_ = color; desktop_background_mode_ = BACKGROUND_SOLID_COLOR; - InstallComponentForAllWindows(); + InstallDesktopControllerForAllWindows(); } void DesktopBackgroundController::CreateEmptyWallpaper() { @@ -259,15 +259,15 @@ bool DesktopBackgroundController::MoveDesktopToUnlockedContainer() { } void DesktopBackgroundController::OnWindowDestroying(aura::Window* window) { - window->SetProperty(internal::kWindowDesktopComponent, + window->SetProperty(kDesktopController, static_cast<internal::DesktopBackgroundWidgetController*>(NULL)); - window->SetProperty(internal::kComponentWrapper, - static_cast<internal::ComponentWrapper*>(NULL)); + window->SetProperty(kAnimatingDesktopController, + static_cast<internal::AnimatingDesktopController*>(NULL)); } void DesktopBackgroundController::SetDesktopBackgroundImageMode() { desktop_background_mode_ = BACKGROUND_IMAGE; - InstallComponentForAllWindows(); + InstallDesktopControllerForAllWindows(); } void DesktopBackgroundController::OnWallpaperLoadCompleted( @@ -303,7 +303,7 @@ ui::Layer* DesktopBackgroundController::SetColorLayerForContainer( return background_layer; } -void DesktopBackgroundController::InstallComponent( +void DesktopBackgroundController::InstallDesktopController( aura::RootWindow* root_window) { internal::DesktopBackgroundWidgetController* component = NULL; int container_id = GetBackgroundContainerId(locked_); @@ -326,19 +326,20 @@ void DesktopBackgroundController::InstallComponent( NOTREACHED(); } } - if (NULL == root_window->GetProperty(internal::kComponentWrapper)) { - // First time for this root window + // Ensure we're only observing the root window once. Don't rely on a window + // property check as those can be cleared by tests resetting the background. + if (!root_window->HasObserver(this)) root_window->AddObserver(this); - } - root_window->SetProperty(internal::kComponentWrapper, - new internal::ComponentWrapper(component)); + + root_window->SetProperty(kAnimatingDesktopController, + new internal::AnimatingDesktopController(component)); } -void DesktopBackgroundController::InstallComponentForAllWindows() { +void DesktopBackgroundController::InstallDesktopControllerForAllWindows() { Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); for (Shell::RootWindowList::iterator iter = root_windows.begin(); iter != root_windows.end(); ++iter) { - InstallComponent(*iter); + InstallDesktopController(*iter); } } @@ -350,26 +351,28 @@ bool DesktopBackgroundController::ReparentBackgroundWidgets(int src_container, iter != root_windows.end(); ++iter) { aura::RootWindow* root_window = *iter; // In the steady state (no animation playing) the background widget - // controller exists in the kWindowDesktopComponent property. - DesktopBackgroundWidgetController* desktop_component = root_window-> - GetProperty(kWindowDesktopComponent); - if (desktop_component) { - moved |= desktop_component->Reparent(root_window, - src_container, - dst_container); + // controller exists in the kDesktopController property. + DesktopBackgroundWidgetController* desktop_controller = root_window-> + GetProperty(kDesktopController); + if (desktop_controller) { + moved |= desktop_controller->Reparent(root_window, + src_container, + dst_container); } - // During desktop show animations the controller lives in kComponentWrapper. + // During desktop show animations the controller lives in + // kAnimatingDesktopController. // NOTE: If a wallpaper load happens during a desktop show animation there // can temporarily be two desktop background widgets. We must reparent // both of them - one above and one here. - DesktopBackgroundWidgetController* wrapped_component = - root_window->GetProperty(kComponentWrapper) ? - root_window->GetProperty(kComponentWrapper)->GetComponent(false) : + DesktopBackgroundWidgetController* animating_controller = + root_window->GetProperty(kAnimatingDesktopController) ? + root_window->GetProperty(kAnimatingDesktopController)-> + GetController(false) : NULL; - if (wrapped_component) { - moved |= wrapped_component->Reparent(root_window, - src_container, - dst_container); + if (animating_controller) { + moved |= animating_controller->Reparent(root_window, + src_container, + dst_container); } } return moved; diff --git a/ash/desktop_background/desktop_background_controller.h b/ash/desktop_background/desktop_background_controller.h index 8976a31..47a69f4 100644 --- a/ash/desktop_background/desktop_background_controller.h +++ b/ash/desktop_background/desktop_background_controller.h @@ -151,11 +151,11 @@ class ASH_EXPORT DesktopBackgroundController : public aura::WindowObserver { // Creates and adds component for current mode (either Widget or Layer) to // |root_window|. - void InstallComponent(aura::RootWindow* root_window); + void InstallDesktopController(aura::RootWindow* root_window); // Creates and adds component for current mode (either Widget or Layer) to // all root windows. - void InstallComponentForAllWindows(); + void InstallDesktopControllerForAllWindows(); // Moves all desktop components from one container to other across all root // windows. Returns true if a desktop moved. diff --git a/ash/desktop_background/desktop_background_controller_unittest.cc b/ash/desktop_background/desktop_background_controller_unittest.cc new file mode 100644 index 0000000..3b04bc4 --- /dev/null +++ b/ash/desktop_background/desktop_background_controller_unittest.cc @@ -0,0 +1,182 @@ +// Copyright (c) 2012 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/desktop_background/desktop_background_controller.h" + +#include "ash/desktop_background/desktop_background_widget_controller.h" +#include "ash/shell.h" +#include "ash/shell_window_ids.h" +#include "ash/test/ash_test_base.h" +#include "ui/aura/root_window.h" + +using aura::RootWindow; +using aura::Window; + +namespace { + +// Containers IDs used for tests. +const int kDesktopBackgroundId = + ash::internal::kShellWindowId_DesktopBackgroundContainer; +const int kLockScreenBackgroundId = + ash::internal::kShellWindowId_LockScreenBackgroundContainer; + +// Returns number of child windows in a shell window container. +int ChildCountForContainer(int container_id) { + RootWindow* root = ash::Shell::GetPrimaryRootWindow(); + Window* container = root->GetChildById(container_id); + return static_cast<int>(container->children().size()); +} + +// Steps a widget's layer animation until it is completed. Animations must be +// enabled. +void RunAnimationForWidget(views::Widget* widget) { + // Animations must be enabled for stepping to work. + DCHECK(!ui::LayerAnimator::disable_animations_for_test()); + + ui::Layer* layer = widget->GetNativeView()->layer(); + ui::LayerAnimator* animator = layer->GetAnimator(); + ui::AnimationContainerElement* element = layer->GetAnimator(); + // Multiple steps are required to complete complex animations. + // TODO(vollick): This should not be necessary. crbug.com/154017 + while (animator->is_animating()) { + base::TimeTicks step_time = animator->last_step_time(); + element->Step(step_time + base::TimeDelta::FromMilliseconds(1000)); + } +} + +} // namespace + +namespace ash { +namespace internal { + +class DesktopBackgroundControllerTest : public test::AshTestBase { + public: + DesktopBackgroundControllerTest() {} + virtual ~DesktopBackgroundControllerTest() {} + + virtual void SetUp() OVERRIDE { + test::AshTestBase::SetUp(); + // Ash shell initialization creates wallpaper. Reset it so we can manually + // control wallpaper creation and animation in our tests. + RootWindow* root = Shell::GetPrimaryRootWindow(); + root->SetProperty(kDesktopController, + static_cast<DesktopBackgroundWidgetController*>(NULL)); + root->SetProperty(kAnimatingDesktopController, + static_cast<AnimatingDesktopController*>(NULL)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(DesktopBackgroundControllerTest); +}; + +TEST_F(DesktopBackgroundControllerTest, BasicReparenting) { + DesktopBackgroundController* controller = + Shell::GetInstance()->desktop_background_controller(); + controller->CreateEmptyWallpaper(); + + // Wallpaper view/window exists in the desktop background container and + // nothing is in the lock screen background container. + EXPECT_EQ(1, ChildCountForContainer(kDesktopBackgroundId)); + EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId)); + + // Moving background to lock container should succeed the first time but + // subsequent calls should do nothing. + EXPECT_TRUE(controller->MoveDesktopToLockedContainer()); + EXPECT_FALSE(controller->MoveDesktopToLockedContainer()); + + // One window is moved from desktop to lock container. + EXPECT_EQ(0, ChildCountForContainer(kDesktopBackgroundId)); + EXPECT_EQ(1, ChildCountForContainer(kLockScreenBackgroundId)); + + // Moving background to desktop container should succeed the first time. + EXPECT_TRUE(controller->MoveDesktopToUnlockedContainer()); + EXPECT_FALSE(controller->MoveDesktopToUnlockedContainer()); + + // One window is moved from lock to desktop container. + EXPECT_EQ(1, ChildCountForContainer(kDesktopBackgroundId)); + EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId)); +} + +TEST_F(DesktopBackgroundControllerTest, ControllerOwnership) { + // We cannot short-circuit animations for this test. + ui::LayerAnimator::set_disable_animations_for_test(false); + + // Create wallpaper and background view. + DesktopBackgroundController* controller = + Shell::GetInstance()->desktop_background_controller(); + controller->CreateEmptyWallpaper(); + + // The new wallpaper is ready to start animating. kAnimatingDesktopController + // holds the widget controller instance. kDesktopController will get it later. + RootWindow* root = Shell::GetPrimaryRootWindow(); + EXPECT_TRUE( + root->GetProperty(kAnimatingDesktopController)->GetController(false)); + + // kDesktopController will receive the widget controller when the animation + // is done. + EXPECT_FALSE(root->GetProperty(kDesktopController)); + + // Force the widget's layer animation to play to completion. + RunAnimationForWidget( + root->GetProperty(kAnimatingDesktopController)->GetController(false)-> + widget()); + + // Ownership has moved from kAnimatingDesktopController to kDesktopController. + EXPECT_FALSE( + root->GetProperty(kAnimatingDesktopController)->GetController(false)); + EXPECT_TRUE(root->GetProperty(kDesktopController)); +} + +// Test for crbug.com/149043 "Unlock screen, no launcher appears". Ensure we +// move all desktop views if there are more than one. +TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { + // We cannot short-circuit animations for this test. + ui::LayerAnimator::set_disable_animations_for_test(false); + + // Reset wallpaper state, see ControllerOwnership above. + DesktopBackgroundController* controller = + Shell::GetInstance()->desktop_background_controller(); + controller->CreateEmptyWallpaper(); + + // Run wallpaper show animation to completion. + RootWindow* root = Shell::GetPrimaryRootWindow(); + RunAnimationForWidget( + root->GetProperty(kAnimatingDesktopController)->GetController(false)-> + widget()); + + // User locks the screen, which moves the background forward. + controller->MoveDesktopToLockedContainer(); + + // Suspend/resume cycle causes wallpaper to refresh, loading a new desktop + // background that will animate in on top of the old one. + controller->CreateEmptyWallpaper(); + + // In this state we have two desktop background views stored in different + // properties. Both are in the lock screen background container. + EXPECT_TRUE( + root->GetProperty(kAnimatingDesktopController)->GetController(false)); + EXPECT_TRUE(root->GetProperty(kDesktopController)); + EXPECT_EQ(0, ChildCountForContainer(kDesktopBackgroundId)); + EXPECT_EQ(2, ChildCountForContainer(kLockScreenBackgroundId)); + + // Before the wallpaper's animation completes, user unlocks the screen, which + // moves the desktop to the back. + controller->MoveDesktopToUnlockedContainer(); + + // Ensure both desktop backgrounds have moved. + EXPECT_EQ(2, ChildCountForContainer(kDesktopBackgroundId)); + EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId)); + + // Finish the new desktop background animation. + RunAnimationForWidget( + root->GetProperty(kAnimatingDesktopController)->GetController(false)-> + widget()); + + // Now there is one desktop background, in the back. + EXPECT_EQ(1, ChildCountForContainer(kDesktopBackgroundId)); + EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId)); +} + +} // namespace internal +} // namespace ash diff --git a/ash/desktop_background/desktop_background_view.cc b/ash/desktop_background/desktop_background_view.cc index 38324b8..9ebb8ea 100644 --- a/ash/desktop_background/desktop_background_view.cc +++ b/ash/desktop_background/desktop_background_view.cc @@ -52,12 +52,14 @@ class ShowWallpaperAnimationObserver : public ui::ImplicitAnimationObserver, shell->GetPrimaryRootWindowController()->HandleDesktopBackgroundVisible(); shell->user_wallpaper_delegate()->OnWallpaperAnimationFinished(); // Only removes old component when wallpaper animation finished. If we - // remove the old one too early, there will be a white flash during - // animation. - if (root_window_->GetProperty(kComponentWrapper)) { - internal::DesktopBackgroundWidgetController* component = - root_window_->GetProperty(kComponentWrapper)->GetComponent(true); - root_window_->SetProperty(kWindowDesktopComponent, component); + // remove the old one before the new wallpaper is done fading in there will + // be a white flash during the animation. + if (root_window_->GetProperty(kAnimatingDesktopController)) { + DesktopBackgroundWidgetController* controller = + root_window_->GetProperty(kAnimatingDesktopController)-> + GetController(true); + // Release the old controller and close its background widget. + root_window_->SetProperty(kDesktopController, controller); } delete this; } @@ -173,7 +175,7 @@ views::Widget* CreateDesktopBackground(aura::RootWindow* root_window, // will animate from a white screen. Note that boot animation is different. // It animates from a white background. if (animation_type == ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE && - NULL == root_window->GetProperty(internal::kComponentWrapper)) { + NULL == root_window->GetProperty(kAnimatingDesktopController)) { ash::SetWindowVisibilityAnimationTransition(desktop_widget->GetNativeView(), ash::ANIMATE_NONE); } else { diff --git a/ash/desktop_background/desktop_background_widget_controller.cc b/ash/desktop_background/desktop_background_widget_controller.cc index 6b796d0..dd247ee 100644 --- a/ash/desktop_background/desktop_background_widget_controller.cc +++ b/ash/desktop_background/desktop_background_widget_controller.cc @@ -4,18 +4,23 @@ #include "ash/desktop_background/desktop_background_widget_controller.h" +#include "ash/ash_export.h" #include "ui/aura/root_window.h" #include "ui/views/widget/widget.h" -DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::DesktopBackgroundWidgetController*); -DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::ComponentWrapper*); +// Exported for tests. +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE( + ASH_EXPORT, ash::internal::DesktopBackgroundWidgetController*); +DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE( + ASH_EXPORT, ash::internal::AnimatingDesktopController*); namespace ash { namespace internal { DEFINE_OWNED_WINDOW_PROPERTY_KEY(DesktopBackgroundWidgetController, - kWindowDesktopComponent, NULL); -DEFINE_OWNED_WINDOW_PROPERTY_KEY(ComponentWrapper, kComponentWrapper, NULL); + kDesktopController, NULL); +DEFINE_OWNED_WINDOW_PROPERTY_KEY(AnimatingDesktopController, + kAnimatingDesktopController, NULL); DesktopBackgroundWidgetController::DesktopBackgroundWidgetController( views::Widget* widget) : widget_(widget) { @@ -67,19 +72,19 @@ bool DesktopBackgroundWidgetController::Reparent(aura::RootWindow* root_window, return false; } -ComponentWrapper::ComponentWrapper( +AnimatingDesktopController::AnimatingDesktopController( DesktopBackgroundWidgetController* component) { - component_.reset(component); + controller_.reset(component); } -ComponentWrapper::~ComponentWrapper() { +AnimatingDesktopController::~AnimatingDesktopController() { } -DesktopBackgroundWidgetController* ComponentWrapper::GetComponent( +DesktopBackgroundWidgetController* AnimatingDesktopController::GetController( bool pass_ownership) { if (pass_ownership) - return component_.release(); - return component_.get(); + return controller_.release(); + return controller_.get(); } } // namespace internal diff --git a/ash/desktop_background/desktop_background_widget_controller.h b/ash/desktop_background/desktop_background_widget_controller.h index 7017eb0..31a48bd 100644 --- a/ash/desktop_background/desktop_background_widget_controller.h +++ b/ash/desktop_background/desktop_background_widget_controller.h @@ -5,6 +5,7 @@ #ifndef ASH_DESKTOP_BACKGROUND_DESKTOP_BACKGROUND_WIDGET_CONTROLLER_H_ #define ASH_DESKTOP_BACKGROUND_DESKTOP_BACKGROUND_WIDGET_CONTROLLER_H_ +#include "ash/ash_export.h" #include "base/memory/scoped_ptr.h" #include "ui/aura/window_property.h" #include "ui/compositor/layer.h" @@ -20,8 +21,9 @@ namespace internal { // RootWindow. To avoid a white flash during wallpaper changes the old // DesktopBackgroundWidgetController is moved to a secondary property // (kComponentWrapper). When the animation completes the old -// DesktopBackgroundWidgetController is destroyed. -class DesktopBackgroundWidgetController : public views::WidgetObserver { +// DesktopBackgroundWidgetController is destroyed. Exported for tests. +class ASH_EXPORT DesktopBackgroundWidgetController + : public views::WidgetObserver { public: // Create explicit DesktopBackgroundWidgetController(views::Widget* widget); @@ -55,30 +57,34 @@ class DesktopBackgroundWidgetController : public views::WidgetObserver { // This class wraps a DesktopBackgroundWidgetController pointer. It is installed // as an owned property on the RootWindow. DesktopBackgroundWidgetController is // moved to this property before animation completes. After animation completes, -// the kWindowDesktopComponent property on RootWindow is set to the -// DesktopBackgroundWidgetController in this class. -class ComponentWrapper { +// the kDesktopController property on RootWindow is set to the +// DesktopBackgroundWidgetController in this class. Exported for tests. +class ASH_EXPORT AnimatingDesktopController { public: - explicit ComponentWrapper( + explicit AnimatingDesktopController( DesktopBackgroundWidgetController* component); - ~ComponentWrapper(); + ~AnimatingDesktopController(); // Gets the wrapped DesktopBackgroundWidgetController pointer. Caller should // take ownership of the pointer if |pass_ownership| is true. - DesktopBackgroundWidgetController* GetComponent(bool pass_ownership); + DesktopBackgroundWidgetController* GetController(bool pass_ownership); private: - scoped_ptr<DesktopBackgroundWidgetController> component_; + scoped_ptr<DesktopBackgroundWidgetController> controller_; - DISALLOW_COPY_AND_ASSIGN(ComponentWrapper); + DISALLOW_COPY_AND_ASSIGN(AnimatingDesktopController); }; // Window property key, that binds instance of DesktopBackgroundWidgetController -// to root windows. -extern const aura::WindowProperty<DesktopBackgroundWidgetController*>* const - kWindowDesktopComponent; - -extern const aura::WindowProperty<ComponentWrapper*>* const kComponentWrapper; +// to root windows. Owned property. +ASH_EXPORT extern + const aura::WindowProperty<DesktopBackgroundWidgetController*>* const + kDesktopController; + +// Wrapper for the DesktopBackgroundWidgetController for a desktop background +// that is animating in. Owned property. +ASH_EXPORT extern const aura::WindowProperty<AnimatingDesktopController*>* const + kAnimatingDesktopController; } // namespace internal } // namespace ash |