Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / cc / animation / layer_animation_controller_unittest.cc
index fd54572..49ac0a5 100644 (file)
 #include "cc/test/animation_test_common.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/box_f.h"
+#include "ui/gfx/geometry/box_f.h"
 #include "ui/gfx/transform.h"
 
 namespace cc {
 namespace {
 
+using base::TimeDelta;
+using base::TimeTicks;
+
+static base::TimeTicks TicksFromSecondsF(double seconds) {
+  return base::TimeTicks::FromInternalValue(seconds *
+                                            base::Time::kMicrosecondsPerSecond);
+}
+
 // A LayerAnimationController cannot be ticked at 0.0, since an animation
 // with start time 0.0 is treated as an animation whose start time has
 // not yet been set.
-const double kInitialTickTime = 1.0;
+const TimeTicks kInitialTickTime = TicksFromSecondsF(1.0);
 
 scoped_ptr<Animation> CreateAnimation(scoped_ptr<AnimationCurve> curve,
                                       int id,
@@ -43,10 +51,16 @@ TEST(LayerAnimationControllerTest, SyncNewAnimation) {
 
   EXPECT_FALSE(controller_impl->GetAnimation(Animation::Opacity));
 
+  EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+  EXPECT_FALSE(controller_impl->needs_to_start_animations_for_testing());
+
   AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
+  EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
   int group_id = controller->GetAnimation(Animation::Opacity)->group();
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  EXPECT_TRUE(controller_impl->needs_to_start_animations_for_testing());
+  controller_impl->ActivateAnimations();
 
   EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
   EXPECT_EQ(Animation::WaitingForTargetAvailability,
@@ -72,6 +86,7 @@ TEST(LayerAnimationControllerTest, DoNotClobberStartTimes) {
   int group_id = controller->GetAnimation(Animation::Opacity)->group();
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
 
   EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
   EXPECT_EQ(Animation::WaitingForTargetAvailability,
@@ -84,15 +99,67 @@ TEST(LayerAnimationControllerTest, DoNotClobberStartTimes) {
 
   // Synchronize the start times.
   EXPECT_EQ(1u, events.size());
-  controller->NotifyAnimationStarted(events[0], 0.0);
+  controller->NotifyAnimationStarted(events[0]);
   EXPECT_EQ(controller->GetAnimation(group_id,
                                      Animation::Opacity)->start_time(),
             controller_impl->GetAnimation(group_id,
                                           Animation::Opacity)->start_time());
 
   // Start the animation on the main thread. Should not affect the start time.
-  controller->Animate(kInitialTickTime + 0.5);
-  controller->UpdateState(true, NULL);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+  controller->UpdateState(true, nullptr);
+  EXPECT_EQ(controller->GetAnimation(group_id,
+                                     Animation::Opacity)->start_time(),
+            controller_impl->GetAnimation(group_id,
+                                          Animation::Opacity)->start_time());
+}
+
+TEST(LayerAnimationControllerTest, UseSpecifiedStartTimes) {
+  FakeLayerAnimationValueObserver dummy_impl;
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+  controller_impl->AddValueObserver(&dummy_impl);
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  AddOpacityTransitionToController(controller.get(), 1, 0, 1, false);
+  int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+  const TimeTicks start_time = TicksFromSecondsF(123);
+  controller->GetAnimation(Animation::Opacity)->set_start_time(start_time);
+
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
+
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+  EXPECT_EQ(Animation::WaitingForTargetAvailability,
+            controller_impl->GetAnimation(group_id,
+                                          Animation::Opacity)->run_state());
+
+  AnimationEventsVector events;
+  controller_impl->Animate(kInitialTickTime);
+  controller_impl->UpdateState(true, &events);
+
+  // Synchronize the start times.
+  EXPECT_EQ(1u, events.size());
+  controller->NotifyAnimationStarted(events[0]);
+
+  EXPECT_EQ(start_time,
+            controller->GetAnimation(group_id,
+                                     Animation::Opacity)->start_time());
+  EXPECT_EQ(controller->GetAnimation(group_id,
+                                     Animation::Opacity)->start_time(),
+            controller_impl->GetAnimation(group_id,
+                                          Animation::Opacity)->start_time());
+
+  // Start the animation on the main thread. Should not affect the start time.
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+  controller->UpdateState(true, nullptr);
+  EXPECT_EQ(start_time,
+            controller->GetAnimation(group_id,
+                                     Animation::Opacity)->start_time());
   EXPECT_EQ(controller->GetAnimation(group_id,
                                      Animation::Opacity)->start_time(),
             controller_impl->GetAnimation(group_id,
@@ -129,6 +196,7 @@ TEST(LayerAnimationControllerTest, Activation) {
   EXPECT_EQ(1u, registrar->active_animation_controllers().size());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   // Both controllers should now be active.
   EXPECT_EQ(1u, registrar->active_animation_controllers().size());
   EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
@@ -136,23 +204,24 @@ TEST(LayerAnimationControllerTest, Activation) {
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->size());
-  controller->NotifyAnimationStarted((*events)[0], 0.0);
+  controller->NotifyAnimationStarted((*events)[0]);
 
   EXPECT_EQ(1u, registrar->active_animation_controllers().size());
   EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size());
 
-  controller->Animate(kInitialTickTime + 0.5);
-  controller->UpdateState(true, NULL);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+  controller->UpdateState(true, nullptr);
   EXPECT_EQ(1u, registrar->active_animation_controllers().size());
 
-  controller->Animate(kInitialTickTime + 1.0);
-  controller->UpdateState(true, NULL);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  controller->UpdateState(true, nullptr);
   EXPECT_EQ(Animation::Finished,
             controller->GetAnimation(Animation::Opacity)->run_state());
   EXPECT_EQ(1u, registrar->active_animation_controllers().size());
 
   events.reset(new AnimationEventsVector);
-  controller_impl->Animate(kInitialTickTime + 1.5);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1500));
   controller_impl->UpdateState(true, events.get());
 
   EXPECT_EQ(Animation::WaitingForDeletion,
@@ -161,9 +230,9 @@ TEST(LayerAnimationControllerTest, Activation) {
   EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
 
   EXPECT_EQ(1u, events->size());
-  controller->NotifyAnimationFinished((*events)[0], 0.0);
-  controller->Animate(kInitialTickTime + 1.5);
-  controller->UpdateState(true, NULL);
+  controller->NotifyAnimationFinished((*events)[0]);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1500));
+  controller->UpdateState(true, nullptr);
 
   EXPECT_EQ(Animation::WaitingForDeletion,
             controller->GetAnimation(Animation::Opacity)->run_state());
@@ -171,13 +240,14 @@ TEST(LayerAnimationControllerTest, Activation) {
   EXPECT_EQ(0u, registrar->active_animation_controllers().size());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_FALSE(controller->has_any_animation());
   EXPECT_FALSE(controller_impl->has_any_animation());
   EXPECT_EQ(0u, registrar->active_animation_controllers().size());
   EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size());
 
-  controller->SetAnimationRegistrar(NULL);
-  controller_impl->SetAnimationRegistrar(NULL);
+  controller->SetAnimationRegistrar(nullptr);
+  controller_impl->SetAnimationRegistrar(nullptr);
 }
 
 TEST(LayerAnimationControllerTest, SyncPause) {
@@ -197,6 +267,7 @@ TEST(LayerAnimationControllerTest, SyncPause) {
   int animation_id = controller->GetAnimation(Animation::Opacity)->id();
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
 
   EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
   EXPECT_EQ(Animation::WaitingForTargetAvailability,
@@ -208,7 +279,7 @@ TEST(LayerAnimationControllerTest, SyncPause) {
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, &events);
   controller->Animate(kInitialTickTime);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   EXPECT_EQ(Animation::Running,
             controller_impl->GetAnimation(group_id,
                                           Animation::Opacity)->run_state());
@@ -217,13 +288,16 @@ TEST(LayerAnimationControllerTest, SyncPause) {
                                      Animation::Opacity)->run_state());
 
   // Pause the main-thread animation.
-  controller->PauseAnimation(animation_id, kInitialTickTime + 1.0);
+  controller->PauseAnimation(
+      animation_id,
+      TimeDelta::FromMilliseconds(1000) + TimeDelta::FromMilliseconds(1000));
   EXPECT_EQ(Animation::Paused,
             controller->GetAnimation(group_id,
                                      Animation::Opacity)->run_state());
 
   // The pause run state change should make it to the impl thread controller.
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_EQ(Animation::Paused,
             controller_impl->GetAnimation(group_id,
                                           Animation::Opacity)->run_state());
@@ -246,6 +320,7 @@ TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
   int group_id = controller->GetAnimation(Animation::Opacity)->group();
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
 
   EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
   EXPECT_EQ(Animation::WaitingForTargetAvailability,
@@ -258,7 +333,7 @@ TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
                                          group_id,
                                          Animation::Opacity,
                                          kInitialTickTime);
-  controller->NotifyAnimationStarted(animation_started_event, 0.0);
+  controller->NotifyAnimationStarted(animation_started_event);
 
   // Force animation to complete on impl thread.
   controller_impl->RemoveAnimation(animation_id);
@@ -266,6 +341,7 @@ TEST(LayerAnimationControllerTest, DoNotSyncFinishedAnimation) {
   EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
 
   // Even though the main thread has a 'new' animation, it should not be pushed
   // because the animation has already completed on the impl thread.
@@ -288,25 +364,27 @@ TEST(LayerAnimationControllerTest, AnimationsAreDeleted) {
 
   AddOpacityTransitionToController(controller.get(), 1.0, 0.0f, 1.0f, false);
   controller->Animate(kInitialTickTime);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
 
-  controller_impl->Animate(kInitialTickTime + 0.5);
+  controller_impl->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller_impl->UpdateState(true, events.get());
 
   // There should be a Started event for the animation.
   EXPECT_EQ(1u, events->size());
   EXPECT_EQ(AnimationEvent::Started, (*events)[0].type);
-  controller->NotifyAnimationStarted((*events)[0], 0.0);
+  controller->NotifyAnimationStarted((*events)[0]);
 
-  controller->Animate(kInitialTickTime + 1.0);
-  controller->UpdateState(true, NULL);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  controller->UpdateState(true, nullptr);
 
   EXPECT_FALSE(dummy.animation_waiting_for_deletion());
   EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
 
   events.reset(new AnimationEventsVector);
-  controller_impl->Animate(kInitialTickTime + 2.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(2000));
   controller_impl->UpdateState(true, events.get());
 
   EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion());
@@ -319,15 +397,18 @@ TEST(LayerAnimationControllerTest, AnimationsAreDeleted) {
   EXPECT_TRUE(controller->GetAnimation(Animation::Opacity));
   EXPECT_TRUE(controller_impl->GetAnimation(Animation::Opacity));
 
-  controller->NotifyAnimationFinished((*events)[0], 0.0);
+  controller->NotifyAnimationFinished((*events)[0]);
 
-  controller->Animate(kInitialTickTime + 3.0);
-  controller->UpdateState(true, NULL);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(dummy.animation_waiting_for_deletion());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
 
-  // Both controllers should now have deleted the animation.
+  // Both controllers should now have deleted the animation. The impl controller
+  // should have deleted the animation even though activation has not occurred,
+  // since the animation was already waiting for deletion when
+  // PushAnimationUpdatesTo was called.
   EXPECT_FALSE(controller->has_any_animation());
   EXPECT_FALSE(controller_impl->has_any_animation());
 }
@@ -357,15 +438,18 @@ TEST(LayerAnimationControllerTest, TrivialTransition) {
       1,
       Animation::Opacity));
 
+  EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
   controller->AddAnimation(to_add.Pass());
+  EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
   controller->Animate(kInitialTickTime);
+  EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
   // A non-impl-only animation should not generate property updates.
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(1.f, dummy.opacity());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -392,16 +476,17 @@ TEST(LayerAnimationControllerTest, TrivialTransitionOnImpl) {
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy_impl.opacity());
-  EXPECT_EQ(2u, events->size());
+  EXPECT_EQ(1u, events->size());
   const AnimationEvent* start_opacity_event =
       GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_EQ(0.f, start_opacity_event->opacity);
 
-  controller_impl->Animate(kInitialTickTime + 1.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
   EXPECT_EQ(1.f, dummy_impl.opacity());
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(4u, events->size());
+  EXPECT_EQ(2u, events->size());
   const AnimationEvent* end_opacity_event =
       GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_EQ(1.f, end_opacity_event->opacity);
@@ -425,14 +510,12 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
 
   // Create simple Transform animation.
   TransformOperations operations;
-  curve->AddKeyframe(
-      TransformKeyframe::Create(0, operations, scoped_ptr<TimingFunction>()));
+  curve->AddKeyframe(TransformKeyframe::Create(0, operations, nullptr));
   operations.AppendTranslate(delta_x, delta_y, 0);
-  curve->AddKeyframe(
-      TransformKeyframe::Create(1, operations, scoped_ptr<TimingFunction>()));
+  curve->AddKeyframe(TransformKeyframe::Create(1, operations, nullptr));
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve.PassAs<AnimationCurve>(), 1, 0, Animation::Transform));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve.Pass(), 1, 0, Animation::Transform));
   animation->set_is_impl_only(true);
   controller_impl->AddAnimation(animation.Pass());
 
@@ -441,7 +524,7 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
   EXPECT_EQ(gfx::Transform(), dummy_impl.transform());
-  EXPECT_EQ(2u, events->size());
+  EXPECT_EQ(1u, events->size());
   const AnimationEvent* start_transform_event =
       GetMostRecentPropertyUpdateEvent(events.get());
   ASSERT_TRUE(start_transform_event);
@@ -451,11 +534,12 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) {
   gfx::Transform expected_transform;
   expected_transform.Translate(delta_x, delta_y);
 
-  controller_impl->Animate(kInitialTickTime + 1.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
   EXPECT_EQ(expected_transform, dummy_impl.transform());
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(4u, events->size());
+  EXPECT_EQ(2u, events->size());
   const AnimationEvent* end_transform_event =
       GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_EQ(expected_transform, end_transform_event->transform);
@@ -475,15 +559,13 @@ TEST(LayerAnimationControllerTest, FilterTransition) {
 
   FilterOperations start_filters;
   start_filters.Append(FilterOperation::CreateBrightnessFilter(1.f));
-  curve->AddKeyframe(
-      FilterKeyframe::Create(0, start_filters, scoped_ptr<TimingFunction>()));
+  curve->AddKeyframe(FilterKeyframe::Create(0, start_filters, nullptr));
   FilterOperations end_filters;
   end_filters.Append(FilterOperation::CreateBrightnessFilter(2.f));
-  curve->AddKeyframe(
-      FilterKeyframe::Create(1, end_filters, scoped_ptr<TimingFunction>()));
+  curve->AddKeyframe(FilterKeyframe::Create(1, end_filters, nullptr));
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve.PassAs<AnimationCurve>(), 1, 0, Animation::Filter));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve.Pass(), 1, 0, Animation::Filter));
   controller->AddAnimation(animation.Pass());
 
   controller->Animate(kInitialTickTime);
@@ -494,7 +576,7 @@ TEST(LayerAnimationControllerTest, FilterTransition) {
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
-  controller->Animate(kInitialTickTime + 0.5);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(1u, dummy.filters().size());
   EXPECT_EQ(FilterOperation::CreateBrightnessFilter(1.5f),
@@ -502,7 +584,7 @@ TEST(LayerAnimationControllerTest, FilterTransition) {
   event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(end_filters, dummy.filters());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -524,15 +606,13 @@ TEST(LayerAnimationControllerTest, FilterTransitionOnImplOnly) {
   // Create simple Filter animation.
   FilterOperations start_filters;
   start_filters.Append(FilterOperation::CreateBrightnessFilter(1.f));
-  curve->AddKeyframe(
-      FilterKeyframe::Create(0, start_filters, scoped_ptr<TimingFunction>()));
+  curve->AddKeyframe(FilterKeyframe::Create(0, start_filters, nullptr));
   FilterOperations end_filters;
   end_filters.Append(FilterOperation::CreateBrightnessFilter(2.f));
-  curve->AddKeyframe(
-      FilterKeyframe::Create(1, end_filters, scoped_ptr<TimingFunction>()));
+  curve->AddKeyframe(FilterKeyframe::Create(1, end_filters, nullptr));
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve.PassAs<AnimationCurve>(), 1, 0, Animation::Filter));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve.Pass(), 1, 0, Animation::Filter));
   animation->set_is_impl_only(true);
   controller_impl->AddAnimation(animation.Pass());
 
@@ -541,18 +621,19 @@ TEST(LayerAnimationControllerTest, FilterTransitionOnImplOnly) {
   controller_impl->UpdateState(true, events.get());
   EXPECT_TRUE(controller_impl->HasActiveAnimation());
   EXPECT_EQ(start_filters, dummy_impl.filters());
-  EXPECT_EQ(2u, events->size());
+  EXPECT_EQ(1u, events->size());
   const AnimationEvent* start_filter_event =
       GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_TRUE(start_filter_event);
   EXPECT_EQ(start_filters, start_filter_event->filters);
   EXPECT_TRUE(start_filter_event->is_impl_only);
 
-  controller_impl->Animate(kInitialTickTime + 1.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
   EXPECT_EQ(end_filters, dummy_impl.filters());
   EXPECT_FALSE(controller_impl->HasActiveAnimation());
-  EXPECT_EQ(4u, events->size());
+  EXPECT_EQ(2u, events->size());
   const AnimationEvent* end_filter_event =
       GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_TRUE(end_filter_event);
@@ -576,30 +657,34 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransition) {
   controller->AddValueObserver(&dummy);
   controller->set_value_provider(&dummy_provider);
 
-  gfx::Vector2dF initial_value(100.f, 300.f);
-  gfx::Vector2dF target_value(300.f, 200.f);
+  gfx::ScrollOffset initial_value(100.f, 300.f);
+  gfx::ScrollOffset target_value(300.f, 200.f);
   scoped_ptr<ScrollOffsetAnimationCurve> curve(
       ScrollOffsetAnimationCurve::Create(
           target_value,
           EaseInOutTimingFunction::Create().Pass()));
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve.Pass(), 1, 0, Animation::ScrollOffset));
   animation->set_needs_synchronized_start_time(true);
   controller->AddAnimation(animation.Pass());
 
   dummy_provider_impl.set_scroll_offset(initial_value);
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_TRUE(controller_impl->GetAnimation(Animation::ScrollOffset));
-  double duration = controller_impl->GetAnimation(
-      Animation::ScrollOffset)->curve()->Duration();
-
+  double duration_in_seconds =
+      controller_impl->GetAnimation(Animation::ScrollOffset)
+          ->curve()
+          ->Duration();
+  TimeDelta duration = TimeDelta::FromMicroseconds(
+      duration_in_seconds * base::Time::kMicrosecondsPerSecond);
   EXPECT_EQ(
-      duration,
+      duration_in_seconds,
       controller->GetAnimation(Animation::ScrollOffset)->curve()->Duration());
 
   controller->Animate(kInitialTickTime);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(initial_value, dummy.scroll_offset());
 
@@ -611,13 +696,13 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransition) {
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
-  controller->NotifyAnimationStarted((*events)[0], 0.0);
-  controller->Animate(kInitialTickTime + duration/2.0);
-  controller->UpdateState(true, NULL);
+  controller->NotifyAnimationStarted((*events)[0]);
+  controller->Animate(kInitialTickTime + duration / 2);
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f), dummy.scroll_offset());
 
-  controller_impl->Animate(kInitialTickTime + duration/2.0);
+  controller_impl->Animate(kInitialTickTime + duration / 2);
   controller_impl->UpdateState(true, events.get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
                       dummy_impl.scroll_offset());
@@ -632,7 +717,7 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransition) {
   EXPECT_FALSE(event);
 
   controller->Animate(kInitialTickTime + duration);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset());
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
@@ -654,30 +739,32 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransitionNoImplProvider) {
   controller->AddValueObserver(&dummy);
   controller->set_value_provider(&dummy_provider);
 
-  gfx::Vector2dF initial_value(500.f, 100.f);
-  gfx::Vector2dF target_value(300.f, 200.f);
+  gfx::ScrollOffset initial_value(500.f, 100.f);
+  gfx::ScrollOffset target_value(300.f, 200.f);
   scoped_ptr<ScrollOffsetAnimationCurve> curve(
       ScrollOffsetAnimationCurve::Create(
           target_value,
           EaseInOutTimingFunction::Create().Pass()));
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve.Pass(), 1, 0, Animation::ScrollOffset));
   animation->set_needs_synchronized_start_time(true);
   controller->AddAnimation(animation.Pass());
 
   dummy_provider.set_scroll_offset(initial_value);
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_TRUE(controller_impl->GetAnimation(Animation::ScrollOffset));
-  double duration = controller_impl->GetAnimation(
-      Animation::ScrollOffset)->curve()->Duration();
-
+  double duration_in_seconds =
+      controller_impl->GetAnimation(Animation::ScrollOffset)
+          ->curve()
+          ->Duration();
   EXPECT_EQ(
-      duration,
+      duration_in_seconds,
       controller->GetAnimation(Animation::ScrollOffset)->curve()->Duration());
 
   controller->Animate(kInitialTickTime);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(initial_value, dummy.scroll_offset());
 
@@ -689,13 +776,16 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransitionNoImplProvider) {
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
-  controller->NotifyAnimationStarted((*events)[0], 0.0);
-  controller->Animate(kInitialTickTime + duration/2.0);
-  controller->UpdateState(true, NULL);
+  TimeDelta duration = TimeDelta::FromMicroseconds(
+      duration_in_seconds * base::Time::kMicrosecondsPerSecond);
+
+  controller->NotifyAnimationStarted((*events)[0]);
+  controller->Animate(kInitialTickTime + duration / 2);
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f), dummy.scroll_offset());
 
-  controller_impl->Animate(kInitialTickTime + duration/2.0);
+  controller_impl->Animate(kInitialTickTime + duration / 2);
   controller_impl->UpdateState(true, events.get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(400.f, 150.f),
                       dummy_impl.scroll_offset());
@@ -710,7 +800,7 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransitionNoImplProvider) {
   EXPECT_FALSE(event);
 
   controller->Animate(kInitialTickTime + duration);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   EXPECT_VECTOR2DF_EQ(target_value, dummy.scroll_offset());
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
@@ -723,17 +813,17 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransitionOnImplOnly) {
   scoped_ptr<AnimationEventsVector> events(
       make_scoped_ptr(new AnimationEventsVector));
 
-  gfx::Vector2dF initial_value(100.f, 300.f);
-  gfx::Vector2dF target_value(300.f, 200.f);
+  gfx::ScrollOffset initial_value(100.f, 300.f);
+  gfx::ScrollOffset target_value(300.f, 200.f);
   scoped_ptr<ScrollOffsetAnimationCurve> curve(
       ScrollOffsetAnimationCurve::Create(
           target_value,
           EaseInOutTimingFunction::Create().Pass()));
   curve->SetInitialValue(initial_value);
-  double duration = curve->Duration();
+  double duration_in_seconds = curve->Duration();
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve.PassAs<AnimationCurve>(), 1, 0, Animation::ScrollOffset));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve.Pass(), 1, 0, Animation::ScrollOffset));
   animation->set_is_impl_only(true);
   controller_impl->AddAnimation(animation.Pass());
 
@@ -745,7 +835,10 @@ TEST(LayerAnimationControllerTest, ScrollOffsetTransitionOnImplOnly) {
   const AnimationEvent* event = GetMostRecentPropertyUpdateEvent(events.get());
   EXPECT_FALSE(event);
 
-  controller_impl->Animate(kInitialTickTime + duration/2.0);
+  TimeDelta duration = TimeDelta::FromMicroseconds(
+      duration_in_seconds * base::Time::kMicrosecondsPerSecond);
+
+  controller_impl->Animate(kInitialTickTime + duration / 2);
   controller_impl->UpdateState(true, events.get());
   EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(200.f, 250.f),
                       dummy_impl.scroll_offset());
@@ -766,17 +859,15 @@ class FakeAnimationDelegate : public AnimationDelegate {
       : started_(false),
         finished_(false) {}
 
-  virtual void NotifyAnimationStarted(
-      double wall_clock_time,
-      base::TimeTicks monotonic_time,
-      Animation::TargetProperty target_property) OVERRIDE {
+  void NotifyAnimationStarted(TimeTicks monotonic_time,
+                              Animation::TargetProperty target_property,
+                              int group) override {
     started_ = true;
   }
 
-  virtual void NotifyAnimationFinished(
-      double wall_clock_time,
-      base::TimeTicks monotonic_time,
-      Animation::TargetProperty target_property) OVERRIDE {
+  void NotifyAnimationFinished(TimeTicks monotonic_time,
+                               Animation::TargetProperty target_property,
+                               int group) override {
     finished_ = true;
   }
 
@@ -790,21 +881,17 @@ class FakeAnimationDelegate : public AnimationDelegate {
 };
 
 // Tests that impl-only animations lead to start and finished notifications
-// being sent to the main thread controller's animation delegate.
+// on the impl thread controller's animation delegate.
 TEST(LayerAnimationControllerTest,
-     NotificationsForImplOnlyAnimationsAreSentToMainThreadDelegate) {
+     NotificationsForImplOnlyAnimationsAreSentToImplThreadDelegate) {
   FakeLayerAnimationValueObserver dummy_impl;
   scoped_refptr<LayerAnimationController> controller_impl(
       LayerAnimationController::Create(0));
   controller_impl->AddValueObserver(&dummy_impl);
   scoped_ptr<AnimationEventsVector> events(
       make_scoped_ptr(new AnimationEventsVector));
-  FakeLayerAnimationValueObserver dummy;
-  scoped_refptr<LayerAnimationController> controller(
-      LayerAnimationController::Create(0));
-  controller->AddValueObserver(&dummy);
   FakeAnimationDelegate delegate;
-  controller->set_layer_animation_delegate(&delegate);
+  controller_impl->set_layer_animation_delegate(&delegate);
 
   scoped_ptr<Animation> to_add(CreateAnimation(
       scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
@@ -813,37 +900,21 @@ TEST(LayerAnimationControllerTest,
   to_add->set_is_impl_only(true);
   controller_impl->AddAnimation(to_add.Pass());
 
+  EXPECT_FALSE(delegate.started());
+  EXPECT_FALSE(delegate.finished());
+
   controller_impl->Animate(kInitialTickTime);
   controller_impl->UpdateState(true, events.get());
 
-  // We should receive 2 events (a started notification and a property update).
-  EXPECT_EQ(2u, events->size());
-  EXPECT_EQ(AnimationEvent::Started, (*events)[0].type);
-  EXPECT_TRUE((*events)[0].is_impl_only);
-  EXPECT_EQ(AnimationEvent::PropertyUpdate, (*events)[1].type);
-  EXPECT_TRUE((*events)[1].is_impl_only);
-
-  // Passing on the start event to the main thread controller should cause the
-  // delegate to get notified.
-  EXPECT_FALSE(delegate.started());
-  controller->NotifyAnimationStarted((*events)[0], 0.0);
   EXPECT_TRUE(delegate.started());
+  EXPECT_FALSE(delegate.finished());
 
   events.reset(new AnimationEventsVector);
-  controller_impl->Animate(kInitialTickTime + 1.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
 
-  // We should receive 2 events (a finished notification and a property update).
-  EXPECT_EQ(2u, events->size());
-  EXPECT_EQ(AnimationEvent::Finished, (*events)[0].type);
-  EXPECT_TRUE((*events)[0].is_impl_only);
-  EXPECT_EQ(AnimationEvent::PropertyUpdate, (*events)[1].type);
-  EXPECT_TRUE((*events)[1].is_impl_only);
-
-  // Passing on the finished event to the main thread controller should cause
-  // the delegate to get notified.
-  EXPECT_FALSE(delegate.finished());
-  controller->NotifyAnimationFinished((*events)[0], 0.0);
+  EXPECT_TRUE(delegate.started());
   EXPECT_TRUE(delegate.finished());
 }
 
@@ -871,23 +942,23 @@ TEST(LayerAnimationControllerTest,
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
 
   // Send the synchronized start time.
-  controller->NotifyAnimationStarted(AnimationEvent(AnimationEvent::Started,
-                                                    0,
-                                                    1,
-                                                    Animation::Opacity,
-                                                    kInitialTickTime + 2),
-                                     0.0);
-  controller->Animate(kInitialTickTime + 5.0);
+  controller->NotifyAnimationStarted(
+      AnimationEvent(AnimationEvent::Started,
+                     0,
+                     1,
+                     Animation::Opacity,
+                     kInitialTickTime + TimeDelta::FromMilliseconds(2000)));
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(5000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(1.f, dummy.opacity());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -902,6 +973,8 @@ TEST(LayerAnimationControllerTest, TrivialQueuing) {
       LayerAnimationController::Create(0));
   controller->AddValueObserver(&dummy);
 
+  EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+
   controller->AddAnimation(CreateAnimation(
       scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
       1,
@@ -912,15 +985,25 @@ TEST(LayerAnimationControllerTest, TrivialQueuing) {
       2,
       Animation::Opacity));
 
+  EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
+
   controller->Animate(kInitialTickTime);
+
+  // The second animation still needs to be started.
+  EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
+
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.0);
+
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
   controller->UpdateState(true, events.get());
+  EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(1.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(0.5f, dummy.opacity());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -953,11 +1036,11 @@ TEST(LayerAnimationControllerTest, Interrupt) {
 
   // Since the previous animation was aborted, the new animation should start
   // right in this call to animate.
-  controller->Animate(kInitialTickTime + 0.5);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(1.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.5);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1500));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(0.5f, dummy.opacity());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -990,13 +1073,13 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked) {
   controller->UpdateState(true, events.get());
   EXPECT_EQ(0.f, dummy.opacity());
   EXPECT_TRUE(controller->HasActiveAnimation());
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   // Should not have started the float transition yet.
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
   // The float animation should have started at time 1 and should be done.
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(1.f, dummy.opacity());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -1035,7 +1118,7 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting) {
   // The opacity animation should have finished at time 1, but the group
   // of animations with id 1 don't finish until time 2 because of the length
   // of the transform animation.
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   // Should not have started the float transition yet.
   EXPECT_TRUE(controller->HasActiveAnimation());
@@ -1043,7 +1126,7 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting) {
 
   // The second opacity animation should start at time 2 and should be done by
   // time 3.
-  controller->Animate(kInitialTickTime + 3.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(0.5f, dummy.opacity());
   EXPECT_FALSE(controller->HasActiveAnimation());
@@ -1069,29 +1152,29 @@ TEST(LayerAnimationControllerTest, TrivialLooping) {
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.25);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.25f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.75);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 2.25);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.25f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 2.75);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 3.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
   EXPECT_FALSE(controller->HasActiveAnimation());
   EXPECT_EQ(1.f, dummy.opacity());
 
   // Just be extra sure.
-  controller->Animate(kInitialTickTime + 4.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(4000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(1.f, dummy.opacity());
 }
@@ -1117,27 +1200,29 @@ TEST(LayerAnimationControllerTest, InfiniteLooping) {
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.25);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.25f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.75);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
 
-  controller->Animate(kInitialTickTime + 1073741824.25);
+  controller->Animate(kInitialTickTime +
+                      TimeDelta::FromMilliseconds(1073741824250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.25f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1073741824.75);
+  controller->Animate(kInitialTickTime +
+                      TimeDelta::FromMilliseconds(1073741824750));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
 
   EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
   controller->GetAnimation(id, Animation::Opacity)->SetRunState(
-      Animation::Aborted, kInitialTickTime + 0.75);
+      Animation::Aborted, kInitialTickTime + TimeDelta::FromMilliseconds(750));
   EXPECT_FALSE(controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
 }
@@ -1161,29 +1246,30 @@ TEST(LayerAnimationControllerTest, PauseResume) {
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 0.5);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.5f, dummy.opacity());
 
   EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
   controller->GetAnimation(id, Animation::Opacity)->SetRunState(
-      Animation::Paused, kInitialTickTime + 0.5);
+      Animation::Paused, kInitialTickTime + TimeDelta::FromMilliseconds(500));
 
-  controller->Animate(kInitialTickTime + 1024.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1024000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.5f, dummy.opacity());
 
   EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
-  controller->GetAnimation(id, Animation::Opacity)->SetRunState(
-      Animation::Running, kInitialTickTime + 1024);
-
-  controller->Animate(kInitialTickTime + 1024.25);
+  controller->GetAnimation(id, Animation::Opacity)
+      ->SetRunState(Animation::Running,
+                    kInitialTickTime + TimeDelta::FromMilliseconds(1024000));
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1024250));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1024.5);
+
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1024500));
   controller->UpdateState(true, events.get());
   EXPECT_FALSE(controller->HasActiveAnimation());
   EXPECT_EQ(1.f, dummy.opacity());
@@ -1216,19 +1302,19 @@ TEST(LayerAnimationControllerTest, AbortAGroupedAnimation) {
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.5f, dummy.opacity());
 
   EXPECT_TRUE(controller->GetAnimation(id, Animation::Opacity));
   controller->GetAnimation(id, Animation::Opacity)->SetRunState(
-      Animation::Aborted, kInitialTickTime + 1.0);
-  controller->Animate(kInitialTickTime + 1.0);
+      Animation::Aborted, kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(1.f, dummy.opacity());
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_TRUE(!controller->HasActiveAnimation());
   EXPECT_EQ(0.75f, dummy.opacity());
@@ -1261,6 +1347,7 @@ TEST(LayerAnimationControllerTest, PushUpdatesWhenSynchronizedStartTimeNeeded) {
   EXPECT_TRUE(active_animation->needs_synchronized_start_time());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
 
   active_animation = controller_impl->GetAnimation(0, Animation::Opacity);
   EXPECT_TRUE(active_animation);
@@ -1291,9 +1378,9 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
       Animation::Opacity));
 
   // Animate but don't UpdateState.
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
 
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   events.reset(new AnimationEventsVector);
   controller->UpdateState(true, events.get());
 
@@ -1305,7 +1392,7 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
   EXPECT_TRUE(controller->HasActiveAnimation());
   EXPECT_EQ(0.f, dummy.opacity());
 
-  controller->Animate(kInitialTickTime + 3.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
 
   // The float tranisition should now be done.
@@ -1313,13 +1400,13 @@ TEST(LayerAnimationControllerTest, SkipUpdateState) {
   EXPECT_FALSE(controller->HasActiveAnimation());
 }
 
-// Tests that an animation controller with only an inactive observer gets ticked
+// Tests that an animation controller with only a pending observer gets ticked
 // but doesn't progress animations past the Starting state.
 TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
   scoped_ptr<AnimationEventsVector> events(
       make_scoped_ptr(new AnimationEventsVector));
   FakeLayerAnimationValueObserver dummy;
-  FakeInactiveLayerAnimationValueObserver inactive_dummy;
+  FakeInactiveLayerAnimationValueObserver pending_dummy;
   scoped_refptr<LayerAnimationController> controller(
       LayerAnimationController::Create(0));
 
@@ -1337,42 +1424,42 @@ TEST(LayerAnimationControllerTest, InactiveObserverGetsTicked) {
   EXPECT_EQ(Animation::WaitingForTargetAvailability,
             controller->GetAnimation(id, Animation::Opacity)->run_state());
 
-  controller->AddValueObserver(&inactive_dummy);
+  controller->AddValueObserver(&pending_dummy);
 
-  // With only an inactive observer, the animation should progress to the
+  // With only a pending observer, the animation should progress to the
   // Starting state and get ticked at its starting point, but should not
   // progress to Running.
-  controller->Animate(kInitialTickTime + 1.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(0u, events->size());
   EXPECT_EQ(Animation::Starting,
             controller->GetAnimation(id, Animation::Opacity)->run_state());
-  EXPECT_EQ(0.5f, inactive_dummy.opacity());
+  EXPECT_EQ(0.5f, pending_dummy.opacity());
 
   // Even when already in the Starting state, the animation should stay
   // there, and shouldn't be ticked past its starting point.
-  controller->Animate(kInitialTickTime + 2.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(0u, events->size());
   EXPECT_EQ(Animation::Starting,
             controller->GetAnimation(id, Animation::Opacity)->run_state());
-  EXPECT_EQ(0.5f, inactive_dummy.opacity());
+  EXPECT_EQ(0.5f, pending_dummy.opacity());
 
   controller->AddValueObserver(&dummy);
 
   // Now that an active observer has been added, the animation should still
   // initially tick at its starting point, but should now progress to Running.
-  controller->Animate(kInitialTickTime + 3.0);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   controller->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->size());
   EXPECT_EQ(Animation::Running,
             controller->GetAnimation(id, Animation::Opacity)->run_state());
-  EXPECT_EQ(0.5f, inactive_dummy.opacity());
+  EXPECT_EQ(0.5f, pending_dummy.opacity());
   EXPECT_EQ(0.5f, dummy.opacity());
 
   // The animation should now tick past its starting point.
-  controller->Animate(kInitialTickTime + 3.5);
-  EXPECT_NE(0.5f, inactive_dummy.opacity());
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(3500));
+  EXPECT_NE(0.5f, pending_dummy.opacity());
   EXPECT_NE(0.5f, dummy.opacity());
 }
 
@@ -1384,28 +1471,23 @@ TEST(LayerAnimationControllerTest, TransformAnimationBounds) {
       KeyframedTransformAnimationCurve::Create());
 
   TransformOperations operations1;
-  curve1->AddKeyframe(TransformKeyframe::Create(
-      0.0, operations1, scoped_ptr<TimingFunction>()));
+  curve1->AddKeyframe(TransformKeyframe::Create(0.0, operations1, nullptr));
   operations1.AppendTranslate(10.0, 15.0, 0.0);
-  curve1->AddKeyframe(TransformKeyframe::Create(
-      1.0, operations1, scoped_ptr<TimingFunction>()));
+  curve1->AddKeyframe(TransformKeyframe::Create(1.0, operations1, nullptr));
 
-  scoped_ptr<Animation> animation(Animation::Create(
-      curve1.PassAs<AnimationCurve>(), 1, 1, Animation::Transform));
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve1.Pass(), 1, 1, Animation::Transform));
   controller_impl->AddAnimation(animation.Pass());
 
   scoped_ptr<KeyframedTransformAnimationCurve> curve2(
       KeyframedTransformAnimationCurve::Create());
 
   TransformOperations operations2;
-  curve2->AddKeyframe(TransformKeyframe::Create(
-      0.0, operations2, scoped_ptr<TimingFunction>()));
+  curve2->AddKeyframe(TransformKeyframe::Create(0.0, operations2, nullptr));
   operations2.AppendScale(2.0, 3.0, 4.0);
-  curve2->AddKeyframe(TransformKeyframe::Create(
-      1.0, operations2, scoped_ptr<TimingFunction>()));
+  curve2->AddKeyframe(TransformKeyframe::Create(1.0, operations2, nullptr));
 
-  animation = Animation::Create(
-      curve2.PassAs<AnimationCurve>(), 2, 2, Animation::Transform);
+  animation = Animation::Create(curve2.Pass(), 2, 2, Animation::Transform);
   controller_impl->AddAnimation(animation.Pass());
 
   gfx::BoxF box(1.f, 2.f, -1.f, 3.f, 4.f, 5.f);
@@ -1416,7 +1498,7 @@ TEST(LayerAnimationControllerTest, TransformAnimationBounds) {
             bounds.ToString());
 
   controller_impl->GetAnimation(1, Animation::Transform)
-      ->SetRunState(Animation::Finished, 0.0);
+      ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0));
 
   // Only the unfinished animation should affect the animated bounds.
   EXPECT_TRUE(controller_impl->TransformAnimationBoundsForBox(box, &bounds));
@@ -1424,7 +1506,7 @@ TEST(LayerAnimationControllerTest, TransformAnimationBounds) {
             bounds.ToString());
 
   controller_impl->GetAnimation(2, Animation::Transform)
-      ->SetRunState(Animation::Finished, 0.0);
+      ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0));
 
   // There are no longer any running animations.
   EXPECT_FALSE(controller_impl->HasTransformAnimationThatInflatesBounds());
@@ -1435,13 +1517,10 @@ TEST(LayerAnimationControllerTest, TransformAnimationBounds) {
   TransformOperations operations3;
   gfx::Transform transform3;
   transform3.Scale3d(1.0, 2.0, 3.0);
-  curve3->AddKeyframe(TransformKeyframe::Create(
-      0.0, operations3, scoped_ptr<TimingFunction>()));
+  curve3->AddKeyframe(TransformKeyframe::Create(0.0, operations3, nullptr));
   operations3.AppendMatrix(transform3);
-  curve3->AddKeyframe(TransformKeyframe::Create(
-      1.0, operations3, scoped_ptr<TimingFunction>()));
-  animation = Animation::Create(
-      curve3.PassAs<AnimationCurve>(), 3, 3, Animation::Transform);
+  curve3->AddKeyframe(TransformKeyframe::Create(1.0, operations3, nullptr));
+  animation = Animation::Create(curve3.Pass(), 3, 3, Animation::Transform);
   controller_impl->AddAnimation(animation.Pass());
   EXPECT_FALSE(controller_impl->TransformAnimationBoundsForBox(box, &bounds));
 }
@@ -1478,9 +1557,9 @@ TEST(LayerAnimationControllerTest, AbortAnimations) {
       Animation::Opacity));
 
   controller->Animate(kInitialTickTime);
-  controller->UpdateState(true, NULL);
-  controller->Animate(kInitialTickTime + 1.0);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  controller->UpdateState(true, nullptr);
 
   EXPECT_EQ(Animation::Finished,
             controller->GetAnimation(1, Animation::Transform)->run_state());
@@ -1523,6 +1602,7 @@ TEST(LayerAnimationControllerTest, MainThreadAbortedAnimationGetsDeleted) {
   int group_id = controller->GetAnimation(Animation::Opacity)->group();
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
 
   controller->AbortAnimations(Animation::Opacity);
@@ -1532,12 +1612,13 @@ TEST(LayerAnimationControllerTest, MainThreadAbortedAnimationGetsDeleted) {
   EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion());
 
   controller->Animate(kInitialTickTime);
-  controller->UpdateState(true, NULL);
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(dummy.animation_waiting_for_deletion());
   EXPECT_EQ(Animation::WaitingForDeletion,
             controller->GetAnimation(Animation::Opacity)->run_state());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_FALSE(controller->GetAnimation(group_id, Animation::Opacity));
   EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
 }
@@ -1557,6 +1638,7 @@ TEST(LayerAnimationControllerTest, ImplThreadAbortedAnimationGetsDeleted) {
   int group_id = controller->GetAnimation(Animation::Opacity)->group();
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
 
   controller_impl->AbortAnimations(Animation::Opacity);
@@ -1578,13 +1660,14 @@ TEST(LayerAnimationControllerTest, ImplThreadAbortedAnimationGetsDeleted) {
   EXPECT_EQ(Animation::Aborted,
             controller->GetAnimation(Animation::Opacity)->run_state());
 
-  controller->Animate(kInitialTickTime + 0.5);
-  controller->UpdateState(true, NULL);
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+  controller->UpdateState(true, nullptr);
   EXPECT_TRUE(dummy.animation_waiting_for_deletion());
   EXPECT_EQ(Animation::WaitingForDeletion,
             controller->GetAnimation(Animation::Opacity)->run_state());
 
   controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
   EXPECT_FALSE(controller->GetAnimation(group_id, Animation::Opacity));
   EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity));
 }
@@ -1618,7 +1701,8 @@ TEST(LayerAnimationControllerTest, FinishedEventsForGroup) {
   EXPECT_EQ(AnimationEvent::Started, (*events)[1].type);
 
   events.reset(new AnimationEventsVector);
-  controller_impl->Animate(kInitialTickTime + 1.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
 
   // The opacity animation should be finished, but should not have generated
@@ -1630,7 +1714,8 @@ TEST(LayerAnimationControllerTest, FinishedEventsForGroup) {
             controller_impl->GetAnimation(1,
                                           Animation::Transform)->run_state());
 
-  controller_impl->Animate(kInitialTickTime + 2.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(2000));
   controller_impl->UpdateState(true, events.get());
 
   // Both animations should have generated Finished events.
@@ -1671,7 +1756,8 @@ TEST(LayerAnimationControllerTest, FinishedAndAbortedEventsForGroup) {
   controller_impl->AbortAnimations(Animation::Opacity);
 
   events.reset(new AnimationEventsVector);
-  controller_impl->Animate(kInitialTickTime + 1.0);
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
   controller_impl->UpdateState(true, events.get());
 
   // We should have exactly 2 events: a Finished event for the tranform
@@ -1683,5 +1769,580 @@ TEST(LayerAnimationControllerTest, FinishedAndAbortedEventsForGroup) {
   EXPECT_EQ(Animation::Opacity, (*events)[1].target_property);
 }
 
+TEST(LayerAnimationControllerTest, HasAnimationThatAffectsScale) {
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+
+  EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+
+  controller_impl->AddAnimation(CreateAnimation(
+      scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+      1,
+      Animation::Opacity));
+
+  // Opacity animations don't affect scale.
+  EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations1;
+  curve1->AddKeyframe(TransformKeyframe::Create(0.0, operations1, nullptr));
+  operations1.AppendTranslate(10.0, 15.0, 0.0);
+  curve1->AddKeyframe(TransformKeyframe::Create(1.0, operations1, nullptr));
+
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve1.Pass(), 2, 2, Animation::Transform));
+  controller_impl->AddAnimation(animation.Pass());
+
+  // Translations don't affect scale.
+  EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve2(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations2;
+  curve2->AddKeyframe(TransformKeyframe::Create(0.0, operations2, nullptr));
+  operations2.AppendScale(2.0, 3.0, 4.0);
+  curve2->AddKeyframe(TransformKeyframe::Create(1.0, operations2, nullptr));
+
+  animation = Animation::Create(curve2.Pass(), 3, 3, Animation::Transform);
+  controller_impl->AddAnimation(animation.Pass());
+
+  EXPECT_TRUE(controller_impl->HasAnimationThatAffectsScale());
+
+  controller_impl->GetAnimation(3, Animation::Transform)
+      ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0));
+
+  // Only unfinished animations should be considered by
+  // HasAnimationThatAffectsScale.
+  EXPECT_FALSE(controller_impl->HasAnimationThatAffectsScale());
+}
+
+TEST(LayerAnimationControllerTest, HasOnlyTranslationTransforms) {
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+
+  EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+
+  controller_impl->AddAnimation(CreateAnimation(
+      scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+      1,
+      Animation::Opacity));
+
+  // Opacity animations aren't non-translation transforms.
+  EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations1;
+  curve1->AddKeyframe(TransformKeyframe::Create(0.0, operations1, nullptr));
+  operations1.AppendTranslate(10.0, 15.0, 0.0);
+  curve1->AddKeyframe(TransformKeyframe::Create(1.0, operations1, nullptr));
+
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve1.Pass(), 2, 2, Animation::Transform));
+  controller_impl->AddAnimation(animation.Pass());
+
+  // The only transform animation we've added is a translation.
+  EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve2(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations2;
+  curve2->AddKeyframe(TransformKeyframe::Create(0.0, operations2, nullptr));
+  operations2.AppendScale(2.0, 3.0, 4.0);
+  curve2->AddKeyframe(TransformKeyframe::Create(1.0, operations2, nullptr));
+
+  animation = Animation::Create(curve2.Pass(), 3, 3, Animation::Transform);
+  controller_impl->AddAnimation(animation.Pass());
+
+  // A scale animation is not a translation.
+  EXPECT_FALSE(controller_impl->HasOnlyTranslationTransforms());
+
+  controller_impl->GetAnimation(3, Animation::Transform)
+      ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0));
+
+  // Only unfinished animations should be considered by
+  // HasOnlyTranslationTransforms.
+  EXPECT_TRUE(controller_impl->HasOnlyTranslationTransforms());
+}
+
+TEST(LayerAnimationControllerTest, MaximumTargetScale) {
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+
+  float max_scale = 0.f;
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(0.f, max_scale);
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations1;
+  curve1->AddKeyframe(TransformKeyframe::Create(0.0, operations1, nullptr));
+  operations1.AppendScale(2.0, 3.0, 4.0);
+  curve1->AddKeyframe(TransformKeyframe::Create(1.0, operations1, nullptr));
+
+  scoped_ptr<Animation> animation(
+      Animation::Create(curve1.Pass(), 1, 1, Animation::Transform));
+  controller_impl->AddAnimation(animation.Pass());
+
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(4.f, max_scale);
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve2(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations2;
+  curve2->AddKeyframe(TransformKeyframe::Create(0.0, operations2, nullptr));
+  operations2.AppendScale(6.0, 5.0, 4.0);
+  curve2->AddKeyframe(TransformKeyframe::Create(1.0, operations2, nullptr));
+
+  animation = Animation::Create(curve2.Pass(), 2, 2, Animation::Transform);
+  controller_impl->AddAnimation(animation.Pass());
+
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(6.f, max_scale);
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve3(
+      KeyframedTransformAnimationCurve::Create());
+
+  TransformOperations operations3;
+  curve3->AddKeyframe(TransformKeyframe::Create(0.0, operations3, nullptr));
+  operations3.AppendPerspective(6.0);
+  curve3->AddKeyframe(TransformKeyframe::Create(1.0, operations3, nullptr));
+
+  animation = Animation::Create(curve3.Pass(), 3, 3, Animation::Transform);
+  controller_impl->AddAnimation(animation.Pass());
+
+  EXPECT_FALSE(controller_impl->MaximumTargetScale(&max_scale));
+
+  controller_impl->GetAnimation(3, Animation::Transform)
+      ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0));
+  controller_impl->GetAnimation(2, Animation::Transform)
+      ->SetRunState(Animation::Finished, TicksFromSecondsF(0.0));
+
+  // Only unfinished animations should be considered by
+  // MaximumTargetScale.
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(4.f, max_scale);
+}
+
+TEST(LayerAnimationControllerTest, MaximumTargetScaleWithDirection) {
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+
+  scoped_ptr<KeyframedTransformAnimationCurve> curve1(
+      KeyframedTransformAnimationCurve::Create());
+  TransformOperations operations1;
+  operations1.AppendScale(1.0, 2.0, 3.0);
+  curve1->AddKeyframe(TransformKeyframe::Create(0.0, operations1, nullptr));
+  TransformOperations operations2;
+  operations2.AppendScale(4.0, 5.0, 6.0);
+  curve1->AddKeyframe(TransformKeyframe::Create(1.0, operations2, nullptr));
+
+  scoped_ptr<Animation> animation_owned(
+      Animation::Create(curve1.Pass(), 1, 1, Animation::Transform));
+  Animation* animation = animation_owned.get();
+  controller_impl->AddAnimation(animation_owned.Pass());
+
+  float max_scale = 0.f;
+
+  EXPECT_GT(animation->playback_rate(), 0.0);
+
+  // Normal direction with positive playback rate.
+  animation->set_direction(Animation::Normal);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(6.f, max_scale);
+
+  // Alternate direction with positive playback rate.
+  animation->set_direction(Animation::Alternate);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(6.f, max_scale);
+
+  // Reverse direction with positive playback rate.
+  animation->set_direction(Animation::Reverse);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(3.f, max_scale);
+
+  // Alternate reverse direction.
+  animation->set_direction(Animation::Reverse);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(3.f, max_scale);
+
+  animation->set_playback_rate(-1.0);
+
+  // Normal direction with negative playback rate.
+  animation->set_direction(Animation::Normal);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(3.f, max_scale);
+
+  // Alternate direction with negative playback rate.
+  animation->set_direction(Animation::Alternate);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(3.f, max_scale);
+
+  // Reverse direction with negative playback rate.
+  animation->set_direction(Animation::Reverse);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(6.f, max_scale);
+
+  // Alternate reverse direction with negative playback rate.
+  animation->set_direction(Animation::Reverse);
+  EXPECT_TRUE(controller_impl->MaximumTargetScale(&max_scale));
+  EXPECT_EQ(6.f, max_scale);
+}
+
+TEST(LayerAnimationControllerTest, NewlyPushedAnimationWaitsForActivation) {
+  scoped_ptr<AnimationEventsVector> events(
+      make_scoped_ptr(new AnimationEventsVector));
+  FakeLayerAnimationValueObserver dummy_impl;
+  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->AddValueObserver(&pending_dummy_impl);
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  EXPECT_FALSE(controller->needs_to_start_animations_for_testing());
+  AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, false);
+  int group_id = controller->GetAnimation(Animation::Opacity)->group();
+  EXPECT_TRUE(controller->needs_to_start_animations_for_testing());
+
+  EXPECT_FALSE(controller_impl->needs_to_start_animations_for_testing());
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+  EXPECT_TRUE(controller_impl->needs_to_start_animations_for_testing());
+
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+  EXPECT_EQ(
+      Animation::WaitingForTargetAvailability,
+      controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                   ->affects_active_observers());
+
+  controller_impl->Animate(kInitialTickTime);
+  EXPECT_FALSE(controller_impl->needs_to_start_animations_for_testing());
+  controller_impl->UpdateState(true, events.get());
+
+  // Since the animation hasn't been activated, it should still be Starting
+  // rather than Running.
+  EXPECT_EQ(
+      Animation::Starting,
+      controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+
+  // Since the animation hasn't been activated, only the pending observer
+  // should have been ticked.
+  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.f, dummy_impl.opacity());
+
+  controller_impl->ActivateAnimations();
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_active_observers());
+
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
+  controller_impl->UpdateState(true, events.get());
+
+  // Since the animation has been activated, it should have reached the
+  // Running state and the active observer should start to get ticked.
+  EXPECT_EQ(
+      Animation::Running,
+      controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity());
+}
+
+TEST(LayerAnimationControllerTest, ActivationBetweenAnimateAndUpdateState) {
+  scoped_ptr<AnimationEventsVector> events(
+      make_scoped_ptr(new AnimationEventsVector));
+  FakeLayerAnimationValueObserver dummy_impl;
+  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->AddValueObserver(&pending_dummy_impl);
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, true);
+  int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity));
+  EXPECT_EQ(
+      Animation::WaitingForTargetAvailability,
+      controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                   ->affects_active_observers());
+
+  controller_impl->Animate(kInitialTickTime);
+
+  // Since the animation hasn't been activated, only the pending observer
+  // should have been ticked.
+  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.f, dummy_impl.opacity());
+
+  controller_impl->ActivateAnimations();
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_active_observers());
+
+  controller_impl->UpdateState(true, events.get());
+
+  // Since the animation has been activated, it should have reached the
+  // Running state.
+  EXPECT_EQ(
+      Animation::Running,
+      controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+
+  controller_impl->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+
+  // Both observers should have been ticked.
+  EXPECT_EQ(0.75f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.75f, dummy_impl.opacity());
+}
+
+TEST(LayerAnimationControllerTest, ClippedOpacityValues) {
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  AddOpacityTransitionToController(controller.get(), 1, 1.f, 2.f, true);
+
+  controller->Animate(kInitialTickTime);
+  EXPECT_EQ(1.f, dummy.opacity());
+
+  // Opacity values are clipped [0,1]
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  EXPECT_EQ(1.f, dummy.opacity());
+}
+
+TEST(LayerAnimationControllerTest, ClippedNegativeOpacityValues) {
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  AddOpacityTransitionToController(controller.get(), 1, 0.f, -2.f, true);
+
+  controller->Animate(kInitialTickTime);
+  EXPECT_EQ(0.f, dummy.opacity());
+
+  // Opacity values are clipped [0,1]
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  EXPECT_EQ(0.f, dummy.opacity());
+}
+
+TEST(LayerAnimationControllerTest, PushedDeletedAnimationWaitsForActivation) {
+  scoped_ptr<AnimationEventsVector> events(
+      make_scoped_ptr(new AnimationEventsVector));
+  FakeLayerAnimationValueObserver dummy_impl;
+  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->AddValueObserver(&pending_dummy_impl);
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  AddOpacityTransitionToController(controller.get(), 1, 0.5f, 1.f, true);
+  int group_id = controller->GetAnimation(Animation::Opacity)->group();
+
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
+  controller_impl->Animate(kInitialTickTime);
+  controller_impl->UpdateState(true, events.get());
+  EXPECT_EQ(
+      Animation::Running,
+      controller_impl->GetAnimation(group_id, Animation::Opacity)->run_state());
+  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity());
+
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_active_observers());
+
+  // Delete the animation on the main-thread controller.
+  controller->RemoveAnimation(
+      controller->GetAnimation(Animation::Opacity)->id());
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+
+  // The animation should no longer affect pending observers.
+  EXPECT_FALSE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                   ->affects_pending_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(group_id, Animation::Opacity)
+                  ->affects_active_observers());
+
+  controller_impl->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+  controller_impl->UpdateState(true, events.get());
+
+  // Only the active observer should have been ticked.
+  EXPECT_EQ(0.5f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.75f, dummy_impl.opacity());
+
+  controller_impl->ActivateAnimations();
+
+  // Activation should cause the animation to be deleted.
+  EXPECT_FALSE(controller_impl->has_any_animation());
+}
+
+// Tests that an animation that affects only active observers won't block
+// an animation that affects only pending observers from starting.
+TEST(LayerAnimationControllerTest, StartAnimationsAffectingDifferentObservers) {
+  scoped_ptr<AnimationEventsVector> events(
+      make_scoped_ptr(new AnimationEventsVector));
+  FakeLayerAnimationValueObserver dummy_impl;
+  FakeInactiveLayerAnimationValueObserver pending_dummy_impl;
+  scoped_refptr<LayerAnimationController> controller_impl(
+      LayerAnimationController::Create(0));
+  controller_impl->AddValueObserver(&dummy_impl);
+  controller_impl->AddValueObserver(&pending_dummy_impl);
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  AddOpacityTransitionToController(controller.get(), 1, 0.f, 1.f, true);
+  int first_animation_group_id =
+      controller->GetAnimation(Animation::Opacity)->group();
+
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+  controller_impl->ActivateAnimations();
+  controller_impl->Animate(kInitialTickTime);
+  controller_impl->UpdateState(true, events.get());
+
+  // Remove the first animation from the main-thread controller, and add a
+  // new animation affecting the same property.
+  controller->RemoveAnimation(
+      controller->GetAnimation(Animation::Opacity)->id());
+  AddOpacityTransitionToController(controller.get(), 1, 1.f, 0.5f, true);
+  int second_animation_group_id =
+      controller->GetAnimation(Animation::Opacity)->group();
+  controller->PushAnimationUpdatesTo(controller_impl.get());
+
+  // The original animation should only affect active observers, and the new
+  // animation should only affect pending observers.
+  EXPECT_FALSE(controller_impl->GetAnimation(first_animation_group_id,
+                                             Animation::Opacity)
+                   ->affects_pending_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(first_animation_group_id,
+                                            Animation::Opacity)
+                  ->affects_active_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(second_animation_group_id,
+                                            Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_FALSE(controller_impl->GetAnimation(second_animation_group_id,
+                                             Animation::Opacity)
+                   ->affects_active_observers());
+
+  controller_impl->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500));
+  controller_impl->UpdateState(true, events.get());
+
+  // The original animation should still be running, and the new animation
+  // should be starting.
+  EXPECT_EQ(Animation::Running,
+            controller_impl->GetAnimation(first_animation_group_id,
+                                          Animation::Opacity)->run_state());
+  EXPECT_EQ(Animation::Starting,
+            controller_impl->GetAnimation(second_animation_group_id,
+                                          Animation::Opacity)->run_state());
+
+  // The active observer should have been ticked by the original animation,
+  // and the pending observer should have been ticked by the new animation.
+  EXPECT_EQ(1.f, pending_dummy_impl.opacity());
+  EXPECT_EQ(0.5f, dummy_impl.opacity());
+
+  controller_impl->ActivateAnimations();
+
+  // The original animation should have been deleted, and the new animation
+  // should now affect both observers.
+  EXPECT_FALSE(controller_impl->GetAnimation(first_animation_group_id,
+                                             Animation::Opacity));
+  EXPECT_TRUE(controller_impl->GetAnimation(second_animation_group_id,
+                                            Animation::Opacity)
+                  ->affects_pending_observers());
+  EXPECT_TRUE(controller_impl->GetAnimation(second_animation_group_id,
+                                            Animation::Opacity)
+                  ->affects_active_observers());
+
+  controller_impl->Animate(kInitialTickTime +
+                           TimeDelta::FromMilliseconds(1000));
+  controller_impl->UpdateState(true, events.get());
+
+  // The new animation should be running, and the active observer should have
+  // been ticked at the new animation's starting point.
+  EXPECT_EQ(Animation::Running,
+            controller_impl->GetAnimation(second_animation_group_id,
+                                          Animation::Opacity)->run_state());
+  EXPECT_EQ(1.f, pending_dummy_impl.opacity());
+  EXPECT_EQ(1.f, dummy_impl.opacity());
+}
+
+TEST(LayerAnimationControllerTest, TestIsAnimatingProperty) {
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  scoped_ptr<Animation> animation(CreateAnimation(
+      scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+      1,
+      Animation::Opacity));
+  controller->AddAnimation(animation.Pass());
+  controller->Animate(kInitialTickTime);
+  EXPECT_TRUE(controller->IsAnimatingProperty(Animation::Opacity));
+  controller->UpdateState(true, nullptr);
+  EXPECT_TRUE(controller->HasActiveAnimation());
+  EXPECT_TRUE(controller->IsAnimatingProperty(Animation::Opacity));
+  EXPECT_FALSE(controller->IsAnimatingProperty(Animation::Filter));
+  EXPECT_EQ(0.f, dummy.opacity());
+}
+
+TEST(LayerAnimationControllerTest, TestIsAnimatingPropertyTimeOffsetFillMode) {
+  FakeLayerAnimationValueObserver dummy;
+  scoped_refptr<LayerAnimationController> controller(
+      LayerAnimationController::Create(0));
+  controller->AddValueObserver(&dummy);
+
+  scoped_ptr<Animation> animation(CreateAnimation(
+      scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(),
+      1,
+      Animation::Opacity));
+  animation->set_fill_mode(Animation::FillModeNone);
+  animation->set_time_offset(TimeDelta::FromMilliseconds(-2000));
+  controller->AddAnimation(animation.Pass());
+
+  controller->Animate(kInitialTickTime);
+  controller->UpdateState(true, nullptr);
+  EXPECT_FALSE(controller->IsAnimatingProperty(Animation::Opacity));
+  EXPECT_TRUE(controller->HasActiveAnimation());
+  EXPECT_FALSE(controller->IsAnimatingProperty(Animation::Opacity));
+  EXPECT_FALSE(controller->IsAnimatingProperty(Animation::Filter));
+
+  controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  controller->UpdateState(true, nullptr);
+  EXPECT_TRUE(controller->IsAnimatingProperty(Animation::Opacity));
+}
+
 }  // namespace
 }  // namespace cc