Chromium Code Reviews| Index: ui/views/corewm/window_animations.cc |
| diff --git a/ui/views/corewm/window_animations.cc b/ui/views/corewm/window_animations.cc |
| index 4eb2caeceaf1ad2054890b00bd36f4a765c35840..723b498d0ad81b321de77b34ded6cb3bbe3e7026 100644 |
| --- a/ui/views/corewm/window_animations.cc |
| +++ b/ui/views/corewm/window_animations.cc |
| @@ -7,6 +7,7 @@ |
| #include <math.h> |
| #include <algorithm> |
| +#include <set> |
| #include <vector> |
| #include "base/command_line.h" |
| @@ -125,41 +126,78 @@ class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, |
| public aura::WindowObserver { |
| public: |
| explicit HidingWindowAnimationObserver(aura::Window* window) |
| - : window_(window) { |
| - window_->AddObserver(this); |
| + : topmost_window_(window) { |
| + topmost_window_->AddObserver(this); |
| + observed_.insert(topmost_window_); |
| } |
| virtual ~HidingWindowAnimationObserver() { |
| STLDeleteElements(&layers_); |
| + |
| + // |topmost_window_| should either be not destroyed or |topmost_window_| |
| + // and all of its children should be destroyed. |
| + // TODO(pkotwicz): Remove CHECK once it has been determined whether a child |
| + // window outliving the end of |topmost_window_|'s animation is the source |
| + // of the crash in crbug.com/338788 |
| + CHECK(topmost_window_ || observed_.empty()); |
|
sky
2014/02/05 21:38:15
If observed_ is not empty, is it possible to embed
|
| + |
| + for (std::set<aura::Window*>::const_iterator it = observed_.begin(); |
| + it != observed_.end(); |
| + ++it) { |
| + (*it)->RemoveObserver(this); |
| + } |
| } |
| private: |
| // Overridden from ui::ImplicitAnimationObserver: |
| virtual void OnImplicitAnimationsCompleted() OVERRIDE { |
| // Window may have been destroyed by this point. |
| - if (window_) { |
| + if (topmost_window_) { |
| aura::client::AnimationHost* animation_host = |
| - aura::client::GetAnimationHost(window_); |
| + aura::client::GetAnimationHost(topmost_window_); |
| if (animation_host) |
| animation_host->OnWindowHidingAnimationCompleted(); |
| - window_->RemoveObserver(this); |
| } |
| delete this; |
| } |
| // Overridden from aura::WindowObserver: |
| virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { |
| - DCHECK_EQ(window, window_); |
| + window->RemoveObserver(this); |
| + observed_.erase(window); |
| + |
| + if (window != topmost_window_) |
| + return; |
| + |
| + // We acquire the layers of all of |topmost_window_|'s children with the |
| + // assumption that they will be destroyed by the time that the animation |
| + // terminates. Observe |topmost_window_|'s children to verify the |
| + // assumption. |
| + ObserveAllChildren(topmost_window_); |
| + |
| DCHECK(layers_.empty()); |
| - AcquireAllLayers(window_); |
| + AcquireAllLayers(topmost_window_); |
| // If the Widget has views with layers, then it is necessary to take |
| // ownership of those layers too. |
| - views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_); |
| + views::Widget* widget = views::Widget::GetWidgetForNativeWindow( |
| + topmost_window_); |
| const views::Widget* const_widget = widget; |
| if (widget && const_widget->GetRootView() && widget->GetContentsView()) |
| AcquireAllViewLayers(widget->GetContentsView()); |
| - window_->RemoveObserver(this); |
| - window_ = NULL; |
| + topmost_window_ = NULL; |
| + } |
| + |
| + // Starts observing all of the windows in a subtree rooted at |window| |
| + // excluding |window|. |
| + void ObserveAllChildren(aura::Window* window) { |
| + for (aura::Window::Windows::const_iterator it = window->children().begin(); |
| + it != window->children().end(); |
| + ++it) { |
| + aura::Window* child = *it; |
| + child->AddObserver(this); |
| + observed_.insert(child); |
| + ObserveAllChildren(child); |
| + } |
| } |
| void AcquireAllLayers(aura::Window* window) { |
| @@ -184,7 +222,11 @@ class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, |
| } |
| } |
| - aura::Window* window_; |
| + aura::Window* topmost_window_; |
| + |
| + // The set of windows observed by this class. |
| + std::set<aura::Window*> observed_; |
| + |
| std::vector<ui::Layer*> layers_; |
| DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); |