| Index: cc/input/top_controls_manager.cc
 | 
| diff --git a/cc/input/top_controls_manager.cc b/cc/input/top_controls_manager.cc
 | 
| index 1615d7f2d3875e4766bb55f884e166caa7d380b9..615afb07056800b92d55ad38807fec7ce2212c65 100644
 | 
| --- a/cc/input/top_controls_manager.cc
 | 
| +++ b/cc/input/top_controls_manager.cc
 | 
| @@ -39,7 +39,6 @@ TopControlsManager::TopControlsManager(TopControlsManagerClient* client,
 | 
|      : client_(client),
 | 
|        animation_direction_(NO_ANIMATION),
 | 
|        permitted_state_(BOTH),
 | 
| -      top_controls_height_(0.f),
 | 
|        current_scroll_delta_(0.f),
 | 
|        controls_scroll_begin_offset_(0.f),
 | 
|        top_controls_show_threshold_(top_controls_hide_threshold),
 | 
| @@ -51,12 +50,20 @@ TopControlsManager::TopControlsManager(TopControlsManagerClient* client,
 | 
|  TopControlsManager::~TopControlsManager() {
 | 
|  }
 | 
|  
 | 
| -float TopControlsManager::ControlsTopOffset() {
 | 
| -  return client_->ControlsTopOffset();
 | 
| +float TopControlsManager::ControlsTopOffset() const {
 | 
| +  return ContentTopOffset() - TopControlsHeight();
 | 
|  }
 | 
|  
 | 
| -float TopControlsManager::ContentTopOffset() {
 | 
| -  return client_->ControlsTopOffset() + top_controls_height_;
 | 
| +float TopControlsManager::ContentTopOffset() const {
 | 
| +  return TopControlsShownRatio() * TopControlsHeight();
 | 
| +}
 | 
| +
 | 
| +float TopControlsManager::TopControlsShownRatio() const {
 | 
| +  return client_->CurrentTopControlsShownRatio();
 | 
| +}
 | 
| +
 | 
| +float TopControlsManager::TopControlsHeight() const {
 | 
| +  return client_->TopControlsHeight();
 | 
|  }
 | 
|  
 | 
|  void TopControlsManager::UpdateTopControlsState(TopControlsState constraints,
 | 
| @@ -72,31 +79,25 @@ void TopControlsManager::UpdateTopControlsState(TopControlsState constraints,
 | 
|      return;
 | 
|  
 | 
|    // Don't do anything if there is no change in offset.
 | 
| -  float final_controls_position = 0.f;
 | 
| -  if (constraints == HIDDEN || current == HIDDEN) {
 | 
| -    final_controls_position = -top_controls_height_;
 | 
| -  }
 | 
| -  if (final_controls_position == client_->ControlsTopOffset()) {
 | 
| +  float final_shown_ratio = 1.f;
 | 
| +  if (constraints == HIDDEN || current == HIDDEN)
 | 
| +    final_shown_ratio = 0.f;
 | 
| +  if (final_shown_ratio == TopControlsShownRatio())
 | 
|      return;
 | 
| -  }
 | 
|  
 | 
| -  AnimationDirection animation_direction = SHOWING_CONTROLS;
 | 
| -  if (constraints == HIDDEN || current == HIDDEN)
 | 
| -    animation_direction = HIDING_CONTROLS;
 | 
| -  ResetAnimations();
 | 
|    if (animate) {
 | 
| -    SetupAnimation(animation_direction);
 | 
| +    SetupAnimation(final_shown_ratio ? SHOWING_CONTROLS : HIDING_CONTROLS);
 | 
|    } else {
 | 
| -    client_->SetControlsTopOffset(final_controls_position);
 | 
| +    ResetAnimations();
 | 
| +    client_->SetCurrentTopControlsShownRatio(final_shown_ratio);
 | 
|    }
 | 
| -  client_->DidChangeTopControlsPosition();
 | 
|  }
 | 
|  
 | 
|  void TopControlsManager::ScrollBegin() {
 | 
|    DCHECK(!pinch_gesture_active_);
 | 
|    ResetAnimations();
 | 
|    current_scroll_delta_ = 0.f;
 | 
| -  controls_scroll_begin_offset_ = client_->ControlsTopOffset();
 | 
| +  controls_scroll_begin_offset_ = ContentTopOffset();
 | 
|  }
 | 
|  
 | 
|  gfx::Vector2dF TopControlsManager::ScrollBy(
 | 
| @@ -111,19 +112,21 @@ gfx::Vector2dF TopControlsManager::ScrollBy(
 | 
|  
 | 
|    current_scroll_delta_ += pending_delta.y();
 | 
|  
 | 
| -  float old_offset = client_->ControlsTopOffset();
 | 
| -  SetControlsTopOffset(controls_scroll_begin_offset_ - current_scroll_delta_);
 | 
| +  float old_offset = ContentTopOffset();
 | 
| +  client_->SetCurrentTopControlsShownRatio(
 | 
| +      (controls_scroll_begin_offset_ - current_scroll_delta_) /
 | 
| +      TopControlsHeight());
 | 
|  
 | 
|    // If the controls are fully visible, treat the current position as the
 | 
|    // new baseline even if the gesture didn't end.
 | 
| -  if (client_->ControlsTopOffset() == 0.f) {
 | 
| +  if (TopControlsShownRatio() == 1.f) {
 | 
|      current_scroll_delta_ = 0.f;
 | 
| -    controls_scroll_begin_offset_ = 0.f;
 | 
| +    controls_scroll_begin_offset_ = ContentTopOffset();
 | 
|    }
 | 
|  
 | 
|    ResetAnimations();
 | 
|  
 | 
| -  gfx::Vector2dF applied_delta(0.f, old_offset - client_->ControlsTopOffset());
 | 
| +  gfx::Vector2dF applied_delta(0.f, old_offset - ContentTopOffset());
 | 
|    return pending_delta - applied_delta;
 | 
|  }
 | 
|  
 | 
| @@ -146,44 +149,20 @@ void TopControlsManager::PinchEnd() {
 | 
|    ScrollBegin();
 | 
|  }
 | 
|  
 | 
| -void TopControlsManager::SetControlsTopOffset(float controls_top_offset) {
 | 
| -  controls_top_offset = std::max(controls_top_offset, -top_controls_height_);
 | 
| -  controls_top_offset = std::min(controls_top_offset, 0.f);
 | 
| -
 | 
| -  if (client_->ControlsTopOffset() == controls_top_offset)
 | 
| -    return;
 | 
| -
 | 
| -  client_->SetControlsTopOffset(controls_top_offset);
 | 
| -
 | 
| -  client_->DidChangeTopControlsPosition();
 | 
| -}
 | 
| -
 | 
| -void TopControlsManager::SetTopControlsHeight(float top_controls_height) {
 | 
| -  DCHECK_GE(top_controls_height, 0);
 | 
| -
 | 
| -  if (top_controls_height == top_controls_height_)
 | 
| -    return;
 | 
| -
 | 
| -  ResetAnimations();
 | 
| -  float top_controls_offset = client_->ControlsTopOffset();
 | 
| -  top_controls_height_ = top_controls_height;
 | 
| -  SetControlsTopOffset(top_controls_offset);
 | 
| -  StartAnimationIfNecessary();
 | 
| -}
 | 
| -
 | 
|  gfx::Vector2dF TopControlsManager::Animate(base::TimeTicks monotonic_time) {
 | 
|    if (!top_controls_animation_ || !client_->HaveRootScrollLayer())
 | 
|      return gfx::Vector2dF();
 | 
|  
 | 
|    base::TimeDelta time = monotonic_time - base::TimeTicks();
 | 
|  
 | 
| -  float old_offset = client_->ControlsTopOffset();
 | 
| -  SetControlsTopOffset(top_controls_animation_->GetValue(time));
 | 
| +  float old_offset = ContentTopOffset();
 | 
| +  client_->SetCurrentTopControlsShownRatio(
 | 
| +      top_controls_animation_->GetValue(time));
 | 
|  
 | 
|    if (IsAnimationCompleteAtTime(monotonic_time))
 | 
|      ResetAnimations();
 | 
|  
 | 
| -  gfx::Vector2dF scroll_delta(0.f, client_->ControlsTopOffset() - old_offset);
 | 
| +  gfx::Vector2dF scroll_delta(0.f, ContentTopOffset() - old_offset);
 | 
|    return scroll_delta;
 | 
|  }
 | 
|  
 | 
| @@ -193,15 +172,9 @@ void TopControlsManager::ResetAnimations() {
 | 
|  }
 | 
|  
 | 
|  void TopControlsManager::SetupAnimation(AnimationDirection direction) {
 | 
| -  DCHECK(direction != NO_ANIMATION);
 | 
| -
 | 
| -  if (direction == SHOWING_CONTROLS && client_->ControlsTopOffset() == 0)
 | 
| -    return;
 | 
| -
 | 
| -  if (direction == HIDING_CONTROLS &&
 | 
| -      client_->ControlsTopOffset() == -top_controls_height_) {
 | 
| -    return;
 | 
| -  }
 | 
| +  DCHECK_NE(NO_ANIMATION, direction);
 | 
| +  DCHECK_IMPLIES(direction == HIDING_CONTROLS, TopControlsShownRatio() > 0.f);
 | 
| +  DCHECK_IMPLIES(direction == SHOWING_CONTROLS, TopControlsShownRatio() < 1.f);
 | 
|  
 | 
|    if (top_controls_animation_ && animation_direction_ == direction)
 | 
|      return;
 | 
| @@ -209,42 +182,32 @@ void TopControlsManager::SetupAnimation(AnimationDirection direction) {
 | 
|    top_controls_animation_ = KeyframedFloatAnimationCurve::Create();
 | 
|    base::TimeDelta start_time = gfx::FrameTime::Now() - base::TimeTicks();
 | 
|    top_controls_animation_->AddKeyframe(
 | 
| -      FloatKeyframe::Create(start_time, client_->ControlsTopOffset(), nullptr));
 | 
| -  float max_ending_offset =
 | 
| -      (direction == SHOWING_CONTROLS ? 1 : -1) * top_controls_height_;
 | 
| +      FloatKeyframe::Create(start_time, TopControlsShownRatio(), nullptr));
 | 
| +  float max_ending_ratio = (direction == SHOWING_CONTROLS ? 1 : -1);
 | 
|    top_controls_animation_->AddKeyframe(FloatKeyframe::Create(
 | 
|        start_time + base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs),
 | 
| -      client_->ControlsTopOffset() + max_ending_offset,
 | 
| +      TopControlsShownRatio() + max_ending_ratio,
 | 
|        EaseTimingFunction::Create()));
 | 
|    animation_direction_ = direction;
 | 
|    client_->DidChangeTopControlsPosition();
 | 
|  }
 | 
|  
 | 
|  void TopControlsManager::StartAnimationIfNecessary() {
 | 
| -  if (client_->ControlsTopOffset() != 0
 | 
| -      && client_->ControlsTopOffset() != -top_controls_height_) {
 | 
| -    AnimationDirection show_controls = NO_ANIMATION;
 | 
| -
 | 
| -    float top_controls_show_height =
 | 
| -        top_controls_height_ * top_controls_hide_threshold_;
 | 
| -    float top_controls_hide_height =
 | 
| -        top_controls_height_ * (1.f - top_controls_show_threshold_);
 | 
| -    if (client_->ControlsTopOffset() >= -top_controls_show_height) {
 | 
| -      // If we're showing so much that the hide threshold won't trigger, show.
 | 
| -      show_controls = SHOWING_CONTROLS;
 | 
| -    } else if (client_->ControlsTopOffset() <= -top_controls_hide_height) {
 | 
| -      // If we're showing so little that the show threshold won't trigger, hide.
 | 
| -      show_controls = HIDING_CONTROLS;
 | 
| -    } else {
 | 
| -      // If we could be either showing or hiding, we determine which one to
 | 
| -      // do based on whether or not the total scroll delta was moving up or
 | 
| -      // down.
 | 
| -      show_controls = current_scroll_delta_ <= 0.f ?
 | 
| -          SHOWING_CONTROLS : HIDING_CONTROLS;
 | 
| -    }
 | 
| -
 | 
| -    if (show_controls != NO_ANIMATION)
 | 
| -      SetupAnimation(show_controls);
 | 
| +  if (TopControlsShownRatio() == 0.f || TopControlsShownRatio() == 1.f)
 | 
| +    return;
 | 
| +
 | 
| +  if (TopControlsShownRatio() >= 1.f - top_controls_hide_threshold_) {
 | 
| +    // If we're showing so much that the hide threshold won't trigger, show.
 | 
| +    SetupAnimation(SHOWING_CONTROLS);
 | 
| +  } else if (TopControlsShownRatio() <= top_controls_show_threshold_) {
 | 
| +    // If we're showing so little that the show threshold won't trigger, hide.
 | 
| +    SetupAnimation(HIDING_CONTROLS);
 | 
| +  } else {
 | 
| +    // If we could be either showing or hiding, we determine which one to
 | 
| +    // do based on whether or not the total scroll delta was moving up or
 | 
| +    // down.
 | 
| +    SetupAnimation(current_scroll_delta_ <= 0.f ? SHOWING_CONTROLS
 | 
| +                                                : HIDING_CONTROLS);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -253,11 +216,10 @@ bool TopControlsManager::IsAnimationCompleteAtTime(base::TimeTicks time) {
 | 
|      return true;
 | 
|  
 | 
|    base::TimeDelta animation_time = time - base::TimeTicks();
 | 
| -  float new_offset = top_controls_animation_->GetValue(animation_time);
 | 
| +  float new_ratio = top_controls_animation_->GetValue(animation_time);
 | 
|  
 | 
| -  if ((animation_direction_ == SHOWING_CONTROLS && new_offset >= 0) ||
 | 
| -      (animation_direction_ == HIDING_CONTROLS
 | 
| -          && new_offset <= -top_controls_height_)) {
 | 
| +  if ((animation_direction_ == SHOWING_CONTROLS && new_ratio >= 1.f) ||
 | 
| +      (animation_direction_ == HIDING_CONTROLS && new_ratio <= 0.f)) {
 | 
|      return true;
 | 
|    }
 | 
|    return false;
 | 
| 
 |