Commit 81e77929 authored by varkha's avatar varkha Committed by Commit bot

[ash-md] Corrects a crash when a window is closed after leaving overview

Exiting overview mode may leave overview header widget still animating.
It is important not to attempt any window manipulation such as
re-stacking when the animation completes because the affected windows
may be gone by then.

BUG=646350
TEST=WindowSelectorTest.SafeToDestroyWindowDuringAnimation

Review-Url: https://codereview.chromium.org/2337383003
Cr-Commit-Position: refs/heads/master@{#418780}
parent 0109afc3
......@@ -33,6 +33,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
......@@ -197,7 +198,10 @@ class WindowSelectorItem::RoundedContainerView
~RoundedContainerView() override { StopObservingLayerAnimations(); }
void OnItemRestored() { item_ = nullptr; }
void OnItemRestored() {
item_ = nullptr;
item_window_ = nullptr;
}
// Starts observing layer animations so that actions can be taken when
// particular animations (opacity) complete. It should only be called once
......@@ -216,6 +220,9 @@ class WindowSelectorItem::RoundedContainerView
layer_ = nullptr;
}
// Used by tests to set animation state.
gfx::SlideAnimation* animation() { return animation_.get(); }
void set_color(SkColor target_color) { target_color_ = target_color; }
// Starts a color animation using |tween_type|. The animation will change the
......@@ -896,4 +903,8 @@ void WindowSelectorItem::FadeOut(std::unique_ptr<views::Widget> widget) {
widget_ptr->SetOpacity(0.f);
}
gfx::SlideAnimation* WindowSelectorItem::GetBackgroundViewAnimation() {
return background_view_ ? background_view_->animation() : nullptr;
}
} // namespace ash
......@@ -18,6 +18,10 @@
#include "ui/views/controls/button/label_button.h"
#include "ui/views/widget/widget.h"
namespace gfx {
class SlideAnimation;
}
namespace views {
class ImageButton;
}
......@@ -201,6 +205,9 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener,
// Fades out a window caption when exiting overview mode.
void FadeOut(std::unique_ptr<views::Widget> widget);
// Allows a test to directly set animation state.
gfx::SlideAnimation* GetBackgroundViewAnimation();
static bool hide_header() { return use_mask_ || use_shape_; }
// True if the item is being shown in the overview, false if it's being
......
......@@ -60,6 +60,7 @@
#include "ui/display/manager/display_layout.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
......@@ -273,6 +274,13 @@ class WindowSelectorTest
return *iter;
}
gfx::SlideAnimation* GetBackgroundViewAnimationForWindow(
int grid_index,
aura::Window* window) {
return GetWindowItemForWindow(grid_index, window)
->GetBackgroundViewAnimation();
}
// Selects |window| in the active overview session by cycling through all
// windows in overview until it is found. Returns true if |window| was found,
// false otherwise.
......@@ -1286,6 +1294,38 @@ TEST_P(WindowSelectorTest, DISABLED_MinimizedWindowVisibility) {
}
}
// Tests that it is safe to destroy a window while the overview header animation
// is still active. See http://crbug.com/646350.
TEST_P(WindowSelectorTest, SafeToDestroyWindowDuringAnimation) {
gfx::Rect bounds(0, 0, 400, 400);
{
// Quickly enter and exit overview mode to activate header animations.
std::unique_ptr<aura::Window> window(CreateWindow(bounds));
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
ToggleOverview();
EXPECT_TRUE(IsSelecting());
gfx::SlideAnimation* animation =
GetBackgroundViewAnimationForWindow(0, window.get());
if (ash::MaterialDesignController::IsOverviewMaterial())
ASSERT_NE(nullptr, animation);
ToggleOverview();
EXPECT_FALSE(IsSelecting());
if (animation)
EXPECT_TRUE(animation->is_animating());
// Close the window while the overview header animation is active.
window.reset();
// Progress animation to the end - should not crash.
if (animation) {
animation->SetCurrentValue(1.0);
animation->Reset(1.0);
}
}
}
// Tests that a bounds change during overview is corrected for.
TEST_P(WindowSelectorTest, BoundsChangeDuringOverview) {
std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400)));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment