| Index: ui/compositor/layer_animation_sequence.cc
 | 
| diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc
 | 
| index a997c385a3f49ce1cc696aff829679af5056d60b..10ba702c005cc26f036de2ff3fab6d67a03050f3 100644
 | 
| --- a/ui/compositor/layer_animation_sequence.cc
 | 
| +++ b/ui/compositor/layer_animation_sequence.cc
 | 
| @@ -16,12 +16,18 @@ namespace ui {
 | 
|  
 | 
|  LayerAnimationSequence::LayerAnimationSequence()
 | 
|      : is_cyclic_(false),
 | 
| -      last_element_(0) {
 | 
| +      last_element_(0),
 | 
| +      waiting_for_group_start_(false),
 | 
| +      animation_group_id_(0),
 | 
| +      last_progressed_fraction_(0.0) {
 | 
|  }
 | 
|  
 | 
|  LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement* element)
 | 
|      : is_cyclic_(false),
 | 
| -      last_element_(0) {
 | 
| +      last_element_(0),
 | 
| +      waiting_for_group_start_(false),
 | 
| +      animation_group_id_(0),
 | 
| +      last_progressed_fraction_(0.0) {
 | 
|    AddElement(element);
 | 
|  }
 | 
|  
 | 
| @@ -31,8 +37,19 @@ LayerAnimationSequence::~LayerAnimationSequence() {
 | 
|                      DetachedFromSequence(this, true));
 | 
|  }
 | 
|  
 | 
| +void LayerAnimationSequence::Start(LayerAnimationDelegate* delegate) {
 | 
| +  DCHECK(start_time_ != base::TimeTicks());
 | 
| +  last_progressed_fraction_ = 0.0;
 | 
| +  if (elements_.empty())
 | 
| +    return;
 | 
| +
 | 
| +  elements_[0]->set_requested_start_time(start_time_);
 | 
| +  elements_[0]->Start(delegate, animation_group_id_);
 | 
| +}
 | 
| +
 | 
|  void LayerAnimationSequence::Progress(base::TimeTicks now,
 | 
|                                        LayerAnimationDelegate* delegate) {
 | 
| +  DCHECK(start_time_ != base::TimeTicks());
 | 
|    bool redraw_required = false;
 | 
|  
 | 
|    if (elements_.empty())
 | 
| @@ -44,21 +61,27 @@ void LayerAnimationSequence::Progress(base::TimeTicks now,
 | 
|    size_t current_index = last_element_ % elements_.size();
 | 
|    base::TimeDelta element_duration;
 | 
|    while (is_cyclic_ || last_element_ < elements_.size()) {
 | 
| -    elements_[current_index]->set_start_time(last_start_);
 | 
| +    elements_[current_index]->set_requested_start_time(last_start_);
 | 
|      if (!elements_[current_index]->IsFinished(now, &element_duration))
 | 
|        break;
 | 
|  
 | 
|      // Let the element we're passing finish.
 | 
| -    if (elements_[current_index]->Progress(now, delegate))
 | 
| +    if (elements_[current_index]->ProgressToEnd(delegate))
 | 
|        redraw_required = true;
 | 
|      last_start_ += element_duration;
 | 
|      ++last_element_;
 | 
| +    last_progressed_fraction_ =
 | 
| +        elements_[current_index]->last_progressed_fraction();
 | 
|      current_index = last_element_ % elements_.size();
 | 
|    }
 | 
|  
 | 
|    if (is_cyclic_ || last_element_ < elements_.size()) {
 | 
| +    if (!elements_[current_index]->Started())
 | 
| +      elements_[current_index]->Start(delegate, animation_group_id_);
 | 
|      if (elements_[current_index]->Progress(now, delegate))
 | 
|        redraw_required = true;
 | 
| +    last_progressed_fraction_ =
 | 
| +        elements_[current_index]->last_progressed_fraction();
 | 
|    }
 | 
|  
 | 
|    // Since the delegate may be deleted due to the notifications below, it is
 | 
| @@ -68,12 +91,14 @@ void LayerAnimationSequence::Progress(base::TimeTicks now,
 | 
|  
 | 
|    if (!is_cyclic_ && last_element_ == elements_.size()) {
 | 
|      last_element_ = 0;
 | 
| +    waiting_for_group_start_ = false;
 | 
| +    animation_group_id_ = 0;
 | 
|      NotifyEnded();
 | 
|    }
 | 
|  }
 | 
|  
 | 
|  bool LayerAnimationSequence::IsFinished(base::TimeTicks time) {
 | 
| -  if (is_cyclic_)
 | 
| +  if (is_cyclic_ || waiting_for_group_start_)
 | 
|      return false;
 | 
|  
 | 
|    if (elements_.empty())
 | 
| @@ -86,7 +111,7 @@ bool LayerAnimationSequence::IsFinished(base::TimeTicks time) {
 | 
|    size_t current_index = last_element_;
 | 
|    base::TimeDelta element_duration;
 | 
|    while (current_index < elements_.size()) {
 | 
| -    elements_[current_index]->set_start_time(current_start);
 | 
| +    elements_[current_index]->set_requested_start_time(current_start);
 | 
|      if (!elements_[current_index]->IsFinished(time, &element_duration))
 | 
|        break;
 | 
|  
 | 
| @@ -107,6 +132,8 @@ void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) {
 | 
|    while (current_index < elements_.size()) {
 | 
|      if (elements_[current_index]->ProgressToEnd(delegate))
 | 
|        redraw_required = true;
 | 
| +    last_progressed_fraction_ =
 | 
| +        elements_[current_index]->last_progressed_fraction();
 | 
|      ++current_index;
 | 
|      ++last_element_;
 | 
|    }
 | 
| @@ -116,6 +143,8 @@ void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) {
 | 
|  
 | 
|    if (!is_cyclic_) {
 | 
|      last_element_ = 0;
 | 
| +    waiting_for_group_start_ = false;
 | 
| +    animation_group_id_ = 0;
 | 
|      NotifyEnded();
 | 
|    }
 | 
|  }
 | 
| @@ -129,13 +158,14 @@ void LayerAnimationSequence::GetTargetValue(
 | 
|      elements_[i]->GetTargetValue(target);
 | 
|  }
 | 
|  
 | 
| -void LayerAnimationSequence::Abort() {
 | 
| +void LayerAnimationSequence::Abort(LayerAnimationDelegate* delegate) {
 | 
|    size_t current_index = last_element_ % elements_.size();
 | 
|    while (current_index < elements_.size()) {
 | 
| -    elements_[current_index]->Abort();
 | 
| +    elements_[current_index]->Abort(delegate);
 | 
|      ++current_index;
 | 
|    }
 | 
|    last_element_ = 0;
 | 
| +  waiting_for_group_start_ = false;
 | 
|    NotifyAborted();
 | 
|  }
 | 
|  
 | 
| @@ -156,6 +186,13 @@ bool LayerAnimationSequence::HasCommonProperty(
 | 
|    return intersection.size() > 0;
 | 
|  }
 | 
|  
 | 
| +bool LayerAnimationSequence::IsFirstElementThreaded() const {
 | 
| +  if (!elements_.empty())
 | 
| +    return elements_[0]->IsThreaded();
 | 
| +
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
|  void LayerAnimationSequence::AddObserver(LayerAnimationObserver* observer) {
 | 
|    if (!observers_.HasObserver(observer)) {
 | 
|      observers_.AddObserver(observer);
 | 
| @@ -168,6 +205,22 @@ void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver* observer) {
 | 
|    observer->DetachedFromSequence(this, true);
 | 
|  }
 | 
|  
 | 
| +void LayerAnimationSequence::OnThreadedAnimationStarted(
 | 
| +    const cc::AnimationEvent& event) {
 | 
| +  if (elements_.empty() || event.groupId != animation_group_id_)
 | 
| +    return;
 | 
| +
 | 
| +  size_t current_index = last_element_ % elements_.size();
 | 
| +  const LayerAnimationElement::AnimatableProperties& element_properties =
 | 
| +    elements_[current_index]->properties();
 | 
| +  LayerAnimationElement::AnimatableProperty event_property =
 | 
| +      LayerAnimationElement::ToAnimatableProperty(event.targetProperty);
 | 
| +  DCHECK(element_properties.find(event_property) != element_properties.end());
 | 
| +  elements_[current_index]->set_effective_start_time(
 | 
| +      base::TimeTicks::FromInternalValue(
 | 
| +          event.monotonicTime * base::Time::kMicrosecondsPerSecond));
 | 
| +}
 | 
| +
 | 
|  void LayerAnimationSequence::OnScheduled() {
 | 
|    NotifyScheduled();
 | 
|  }
 | 
| @@ -204,4 +257,12 @@ void LayerAnimationSequence::NotifyAborted() {
 | 
|                      OnLayerAnimationAborted(this));
 | 
|  }
 | 
|  
 | 
| +LayerAnimationElement* LayerAnimationSequence::CurrentElement() {
 | 
| +  if (elements_.empty())
 | 
| +    return NULL;
 | 
| +
 | 
| +  size_t current_index = last_element_ % elements_.size();
 | 
| +  return elements_[current_index].get();
 | 
| +}
 | 
| +
 | 
|  }  // namespace ui
 | 
| 
 |