| Index: ui/compositor/compositor.cc | 
| diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc | 
| index 6d1bdace3345cb8ae0d8bd054652013f694ae9cb..ed80f6210642d5b63e0094e37eafad6e395a0ff1 100644 | 
| --- a/ui/compositor/compositor.cc | 
| +++ b/ui/compositor/compositor.cc | 
| @@ -194,8 +194,6 @@ Compositor::~Compositor() { | 
| FOR_EACH_OBSERVER(CompositorAnimationObserver, animation_observer_list_, | 
| OnCompositingShuttingDown(this)); | 
|  | 
| -  DCHECK(begin_frame_observer_list_.empty()); | 
| - | 
| if (root_layer_) | 
| root_layer_->ResetCompositor(); | 
|  | 
| @@ -359,30 +357,21 @@ bool Compositor::HasAnimationObserver( | 
| } | 
|  | 
| void Compositor::AddBeginFrameObserver(CompositorBeginFrameObserver* observer) { | 
| -  DCHECK(std::find(begin_frame_observer_list_.begin(), | 
| -                   begin_frame_observer_list_.end(), observer) == | 
| -         begin_frame_observer_list_.end()); | 
| - | 
| -  if (begin_frame_observer_list_.empty()) | 
| +  if (!begin_frame_observer_list_.might_have_observers()) | 
| host_->SetChildrenNeedBeginFrames(true); | 
|  | 
| +  begin_frame_observer_list_.AddObserver(observer); | 
| + | 
| if (missed_begin_frame_args_.IsValid()) | 
| observer->OnSendBeginFrame(missed_begin_frame_args_); | 
| - | 
| -  begin_frame_observer_list_.push_back(observer); | 
| } | 
|  | 
| void Compositor::RemoveBeginFrameObserver( | 
| CompositorBeginFrameObserver* observer) { | 
| -  auto it = std::find(begin_frame_observer_list_.begin(), | 
| -                      begin_frame_observer_list_.end(), observer); | 
| -  DCHECK(it != begin_frame_observer_list_.end()); | 
| -  begin_frame_observer_list_.erase(it); | 
| +  begin_frame_observer_list_.RemoveObserver(observer); | 
|  | 
| -  if (begin_frame_observer_list_.empty()) { | 
| -    host_->SetChildrenNeedBeginFrames(false); | 
| -    missed_begin_frame_args_ = cc::BeginFrameArgs(); | 
| -  } | 
| +  // As this call may take place while iterating over observers, unsubscription | 
| +  // from |host_| is performed after iteration in |SendBeginFramesToChildren()|. | 
| } | 
|  | 
| void Compositor::BeginMainFrame(const cc::BeginFrameArgs& args) { | 
| @@ -452,8 +441,18 @@ void Compositor::DidAbortSwapBuffers() { | 
| } | 
|  | 
| void Compositor::SendBeginFramesToChildren(const cc::BeginFrameArgs& args) { | 
| -  for (auto observer : begin_frame_observer_list_) | 
| -    observer->OnSendBeginFrame(args); | 
| +  FOR_EACH_OBSERVER(CompositorBeginFrameObserver, begin_frame_observer_list_, | 
| +                    OnSendBeginFrame(args)); | 
| + | 
| +  // Unsubscription is performed here, after iteration, to handle the case where | 
| +  // the last BeginFrame observer is removed while iterating over the observers. | 
| +  if (!begin_frame_observer_list_.might_have_observers()) { | 
| +    host_->SetChildrenNeedBeginFrames(false); | 
| +    // Unsubscription should reset |missed_begin_frame_args_|, avoiding stale | 
| +    // BeginFrame dispatch when the next BeginFrame observer is added. | 
| +    missed_begin_frame_args_ = cc::BeginFrameArgs(); | 
| +    return; | 
| +  } | 
|  | 
| missed_begin_frame_args_ = args; | 
| missed_begin_frame_args_.type = cc::BeginFrameArgs::MISSED; | 
|  |