| Index: mojo/services/view_manager/server_view.cc | 
| diff --git a/mojo/services/view_manager/server_view.cc b/mojo/services/view_manager/server_view.cc | 
| index 6459f9adcd84c72cf5fe4ad3d323a60e9b215f96..78edf388bb7e9d60657f2690f740917e5c63f6d4 100644 | 
| --- a/mojo/services/view_manager/server_view.cc | 
| +++ b/mojo/services/view_manager/server_view.cc | 
| @@ -8,6 +8,7 @@ | 
|  | 
| #include "base/strings/stringprintf.h" | 
| #include "mojo/services/view_manager/server_view_delegate.h" | 
| +#include "mojo/services/view_manager/server_view_observer.h" | 
|  | 
| namespace view_manager { | 
|  | 
| @@ -16,12 +17,17 @@ ServerView::ServerView(ServerViewDelegate* delegate, const ViewId& id) | 
| id_(id), | 
| parent_(nullptr), | 
| visible_(false), | 
| -      opacity_(1) { | 
| +      opacity_(1), | 
| +      // Don't notify newly added observers during notification. This causes | 
| +      // problems for code that adds an observer as part of an observer | 
| +      // notification (such as ServerViewDrawTracker). | 
| +      observers_(ObserverList<ServerViewObserver>::NOTIFY_EXISTING_ONLY) { | 
| DCHECK(delegate);  // Must provide a delegate. | 
| } | 
|  | 
| ServerView::~ServerView() { | 
| -  delegate_->OnWillDestroyView(this); | 
| +  delegate_->PrepareToDestroyView(this); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, OnWillDestroyView(this)); | 
|  | 
| while (!children_.empty()) | 
| children_.front()->parent()->Remove(children_.front()); | 
| @@ -29,7 +35,15 @@ ServerView::~ServerView() { | 
| if (parent_) | 
| parent_->Remove(this); | 
|  | 
| -  delegate_->OnViewDestroyed(this); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, OnViewDestroyed(this)); | 
| +} | 
| + | 
| +void ServerView::AddObserver(ServerViewObserver* observer) { | 
| +  observers_.AddObserver(observer); | 
| +} | 
| + | 
| +void ServerView::RemoveObserver(ServerViewObserver* observer) { | 
| +  observers_.RemoveObserver(observer); | 
| } | 
|  | 
| void ServerView::Add(ServerView* child) { | 
| @@ -45,13 +59,17 @@ void ServerView::Add(ServerView* child) { | 
| } | 
|  | 
| ServerView* old_parent = child->parent(); | 
| -  child->delegate_->OnWillChangeViewHierarchy(child, this, old_parent); | 
| +  child->delegate_->PrepareToChangeViewHierarchy(child, this, old_parent); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, child->observers_, | 
| +                    OnWillChangeViewHierarchy(child, this, old_parent)); | 
| + | 
| if (child->parent()) | 
| child->parent()->RemoveImpl(child); | 
|  | 
| child->parent_ = this; | 
| children_.push_back(child); | 
| -  child->delegate_->OnViewHierarchyChanged(child, this, old_parent); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, child->observers_, | 
| +                    OnViewHierarchyChanged(child, this, old_parent)); | 
| } | 
|  | 
| void ServerView::Remove(ServerView* child) { | 
| @@ -60,9 +78,12 @@ void ServerView::Remove(ServerView* child) { | 
| DCHECK(child != this); | 
| DCHECK(child->parent() == this); | 
|  | 
| -  child->delegate_->OnWillChangeViewHierarchy(child, NULL, this); | 
| +  child->delegate_->PrepareToChangeViewHierarchy(child, NULL, this); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, child->observers_, | 
| +                    OnWillChangeViewHierarchy(child, nullptr, this)); | 
| RemoveImpl(child); | 
| -  child->delegate_->OnViewHierarchyChanged(child, NULL, this); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, child->observers_, | 
| +                    OnViewHierarchyChanged(child, nullptr, this)); | 
| } | 
|  | 
| void ServerView::Reorder(ServerView* child, | 
| @@ -81,7 +102,8 @@ void ServerView::Reorder(ServerView* child, | 
| DCHECK(i != children_.end()); | 
| children_.insert(i, child); | 
| } | 
| -  delegate_->OnViewReordered(this, relative, direction); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, | 
| +                    OnViewReordered(this, relative, direction)); | 
| } | 
|  | 
| void ServerView::SetBounds(const gfx::Rect& bounds) { | 
| @@ -90,7 +112,8 @@ void ServerView::SetBounds(const gfx::Rect& bounds) { | 
|  | 
| const gfx::Rect old_bounds = bounds_; | 
| bounds_ = bounds; | 
| -  delegate_->OnViewBoundsChanged(this, old_bounds, bounds); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, | 
| +                    OnViewBoundsChanged(this, old_bounds, bounds)); | 
| } | 
|  | 
| const ServerView* ServerView::GetRoot() const { | 
| @@ -125,8 +148,12 @@ void ServerView::SetVisible(bool value) { | 
| if (visible_ == value) | 
| return; | 
|  | 
| -  delegate_->OnWillChangeViewVisibility(this); | 
| +  delegate_->PrepareToChangeViewVisibility(this); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, | 
| +                    OnWillChangeViewVisibility(this)); | 
| visible_ = value; | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, | 
| +                    OnViewVisibilityChanged(this)); | 
| } | 
|  | 
| void ServerView::SetOpacity(float value) { | 
| @@ -162,7 +189,8 @@ void ServerView::SetProperty(const std::string& name, | 
| properties_.erase(it); | 
| } | 
|  | 
| -  delegate_->OnViewSharedPropertyChanged(this, name, value); | 
| +  FOR_EACH_OBSERVER(ServerViewObserver, observers_, | 
| +                    OnViewSharedPropertyChanged(this, name, value)); | 
| } | 
|  | 
| bool ServerView::IsDrawn(const ServerView* root) const { | 
| @@ -176,7 +204,7 @@ bool ServerView::IsDrawn(const ServerView* root) const { | 
|  | 
| void ServerView::SetSurfaceId(cc::SurfaceId surface_id) { | 
| surface_id_ = surface_id; | 
| -  delegate_->OnViewSurfaceIdChanged(this); | 
| +  delegate_->OnScheduleViewPaint(this); | 
| } | 
|  | 
| #if !defined(NDEBUG) | 
|  |