[cc] Adds source_id and sequence_number to BeginFrameArgs.

Also uses the sequence number in external BeginFrameSources to
decide whether a missed BeginFrame should be sent.

BUG=646774, 401331
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel

Review-Url: https://codereview.chromium.org/2583483002
Cr-Commit-Position: refs/heads/master@{#440382}
diff --git a/cc/blimp/layer_tree_host_remote.cc b/cc/blimp/layer_tree_host_remote.cc
index 466a4209..442be97 100644
--- a/cc/blimp/layer_tree_host_remote.cc
+++ b/cc/blimp/layer_tree_host_remote.cc
@@ -11,7 +11,6 @@
 #include "cc/blimp/engine_picture_cache.h"
 #include "cc/blimp/picture_data_conversions.h"
 #include "cc/blimp/remote_compositor_bridge.h"
-#include "cc/output/begin_frame_args.h"
 #include "cc/output/compositor_frame_sink.h"
 #include "cc/proto/compositor_message.pb.h"
 #include "cc/proto/gfx_conversions.h"
@@ -371,8 +370,10 @@
   current_pipeline_stage_ = FramePipelineStage::ANIMATE;
   base::TimeTicks now = base::TimeTicks::Now();
   client_->BeginMainFrame(BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, now, now + kDefaultFrameInterval,
+      BEGINFRAME_FROM_HERE, begin_frame_source_.source_id(),
+      begin_frame_number_, now, now + kDefaultFrameInterval,
       kDefaultFrameInterval, BeginFrameArgs::NORMAL));
+  begin_frame_number_++;
   // We don't run any animations on the layer because threaded animations are
   // disabled.
   // TODO(khushalsagar): Revisit this when adding support for animations.
diff --git a/cc/blimp/layer_tree_host_remote.h b/cc/blimp/layer_tree_host_remote.h
index e7c3c8b7..b1c1748 100644
--- a/cc/blimp/layer_tree_host_remote.h
+++ b/cc/blimp/layer_tree_host_remote.h
@@ -10,6 +10,8 @@
 #include "cc/base/cc_export.h"
 #include "cc/blimp/remote_compositor_bridge_client.h"
 #include "cc/debug/layer_tree_debug_state.h"
+#include "cc/output/begin_frame_args.h"
+#include "cc/scheduler/begin_frame_source.h"
 #include "cc/surfaces/surface_sequence_generator.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
@@ -126,6 +128,10 @@
   bool visible_ = false;
   bool defer_commits_ = false;
 
+  // Provides |source_id| for BeginFrameArgs we create.
+  StubBeginFrameSource begin_frame_source_;
+  uint64_t begin_frame_number_ = BeginFrameArgs::kStartingFrameNumber;
+
   // In threaded/single-threaded mode, the LayerTree and Layers expect scroll/
   // scale updates to come from the impl thread only during the main frame.
   // Since we synchronize state outside of that, this is set so we can
diff --git a/cc/ipc/begin_frame_args.mojom b/cc/ipc/begin_frame_args.mojom
index 8b16c62a..ad53658 100644
--- a/cc/ipc/begin_frame_args.mojom
+++ b/cc/ipc/begin_frame_args.mojom
@@ -18,6 +18,8 @@
   mojo.common.mojom.TimeTicks frame_time;
   mojo.common.mojom.TimeTicks deadline;
   mojo.common.mojom.TimeDelta interval;
+  uint64 sequence_number;
+  uint32 source_id;
   BeginFrameArgsType type;
   bool on_critical_path;
 };
diff --git a/cc/ipc/begin_frame_args_struct_traits.h b/cc/ipc/begin_frame_args_struct_traits.h
index bf3c5a8..4d81339 100644
--- a/cc/ipc/begin_frame_args_struct_traits.h
+++ b/cc/ipc/begin_frame_args_struct_traits.h
@@ -24,6 +24,14 @@
     return args.interval;
   }
 
+  static uint64_t sequence_number(const cc::BeginFrameArgs& args) {
+    return args.sequence_number;
+  }
+
+  static uint32_t source_id(const cc::BeginFrameArgs& args) {
+    return args.source_id;
+  }
+
   static cc::mojom::BeginFrameArgsType type(const cc::BeginFrameArgs& args) {
     return static_cast<cc::mojom::BeginFrameArgsType>(args.type);
   }
@@ -39,6 +47,8 @@
         !data.ReadInterval(&out->interval)) {
       return false;
     }
+    out->source_id = data.source_id();
+    out->sequence_number = data.sequence_number();
     out->type =
         static_cast<cc::BeginFrameArgs::BeginFrameArgsType>(data.type());
     out->on_critical_path = data.on_critical_path();
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h
index b90e250..1410de7 100644
--- a/cc/ipc/cc_param_traits_macros.h
+++ b/cc/ipc/cc_param_traits_macros.h
@@ -159,6 +159,8 @@
   IPC_STRUCT_TRAITS_MEMBER(frame_time)
   IPC_STRUCT_TRAITS_MEMBER(deadline)
   IPC_STRUCT_TRAITS_MEMBER(interval)
+  IPC_STRUCT_TRAITS_MEMBER(sequence_number)
+  IPC_STRUCT_TRAITS_MEMBER(source_id)
   IPC_STRUCT_TRAITS_MEMBER(type)
 IPC_STRUCT_TRAITS_END()
 
diff --git a/cc/output/begin_frame_args.cc b/cc/output/begin_frame_args.cc
index 7ef2c484..f7a35ff 100644
--- a/cc/output/begin_frame_args.cc
+++ b/cc/output/begin_frame_args.cc
@@ -24,26 +24,37 @@
   return "???";
 }
 
+constexpr uint64_t BeginFrameArgs::kInvalidFrameNumber;
+constexpr uint64_t BeginFrameArgs::kStartingFrameNumber;
+
 BeginFrameArgs::BeginFrameArgs()
     : frame_time(base::TimeTicks()),
       deadline(base::TimeTicks()),
       interval(base::TimeDelta::FromMicroseconds(-1)),
+      sequence_number(kInvalidFrameNumber),
+      source_id(0),
       type(BeginFrameArgs::INVALID),
-      on_critical_path(true) {
-}
+      on_critical_path(true) {}
 
-BeginFrameArgs::BeginFrameArgs(base::TimeTicks frame_time,
+BeginFrameArgs::BeginFrameArgs(uint32_t source_id,
+                               uint64_t sequence_number,
+                               base::TimeTicks frame_time,
                                base::TimeTicks deadline,
                                base::TimeDelta interval,
                                BeginFrameArgs::BeginFrameArgsType type)
     : frame_time(frame_time),
       deadline(deadline),
       interval(interval),
+      sequence_number(sequence_number),
+      source_id(source_id),
       type(type),
       on_critical_path(true) {
+  DCHECK_LT(kInvalidFrameNumber, sequence_number);
 }
 
 BeginFrameArgs BeginFrameArgs::Create(BeginFrameArgs::CreationLocation location,
+                                      uint32_t source_id,
+                                      uint64_t sequence_number,
                                       base::TimeTicks frame_time,
                                       base::TimeTicks deadline,
                                       base::TimeDelta interval,
@@ -51,9 +62,11 @@
   DCHECK_NE(type, BeginFrameArgs::INVALID);
   DCHECK_NE(type, BeginFrameArgs::BEGIN_FRAME_ARGS_TYPE_MAX);
 #ifdef NDEBUG
-  return BeginFrameArgs(frame_time, deadline, interval, type);
+  return BeginFrameArgs(source_id, sequence_number, frame_time, deadline,
+                        interval, type);
 #else
-  BeginFrameArgs args = BeginFrameArgs(frame_time, deadline, interval, type);
+  BeginFrameArgs args = BeginFrameArgs(source_id, sequence_number, frame_time,
+                                       deadline, interval, type);
   args.created_from = location;
   return args;
 #endif
@@ -70,6 +83,8 @@
 void BeginFrameArgs::AsValueInto(base::trace_event::TracedValue* state) const {
   state->SetString("type", "BeginFrameArgs");
   state->SetString("subtype", TypeToString(type));
+  state->SetInteger("source_id", source_id);
+  state->SetInteger("sequence_number", sequence_number);
   state->SetDouble("frame_time_us", frame_time.ToInternalValue());
   state->SetDouble("deadline_us", deadline.ToInternalValue());
   state->SetDouble("interval_us", interval.InMicroseconds());
diff --git a/cc/output/begin_frame_args.h b/cc/output/begin_frame_args.h
index 78ddce99..a75f446e8 100644
--- a/cc/output/begin_frame_args.h
+++ b/cc/output/begin_frame_args.h
@@ -5,6 +5,7 @@
 #ifndef CC_OUTPUT_BEGIN_FRAME_ARGS_H_
 #define CC_OUTPUT_BEGIN_FRAME_ARGS_H_
 
+#include <stdint.h>
 #include <memory>
 
 #include "base/location.h"
@@ -49,6 +50,9 @@
   };
   static const char* TypeToString(BeginFrameArgsType type);
 
+  static constexpr uint64_t kInvalidFrameNumber = 0;
+  static constexpr uint64_t kStartingFrameNumber = 1;
+
   // Creates an invalid set of values.
   BeginFrameArgs();
 
@@ -63,6 +67,8 @@
   // created by searching for "BeginFrameArgs::Create".
   // The location argument should **always** be BEGINFRAME_FROM_HERE macro.
   static BeginFrameArgs Create(CreationLocation location,
+                               uint32_t source_id,
+                               uint64_t sequence_number,
                                base::TimeTicks frame_time,
                                base::TimeTicks deadline,
                                base::TimeDelta interval,
@@ -84,11 +90,21 @@
   base::TimeTicks frame_time;
   base::TimeTicks deadline;
   base::TimeDelta interval;
+
+  // |source_id| and |sequence_number| identify a BeginFrame within a single
+  // process and are set by the original BeginFrameSource that created the
+  // BeginFrameArgs. When |source_id| of consecutive BeginFrameArgs changes,
+  // observers should expect the continuity of |sequence_number| to break.
+  uint64_t sequence_number;
+  uint32_t source_id;  // |source_id| after |sequence_number| for packing.
+
   BeginFrameArgsType type;
   bool on_critical_path;
 
  private:
-  BeginFrameArgs(base::TimeTicks frame_time,
+  BeginFrameArgs(uint32_t source_id,
+                 uint64_t sequence_number,
+                 base::TimeTicks frame_time,
                  base::TimeTicks deadline,
                  base::TimeDelta interval,
                  BeginFrameArgsType type);
diff --git a/cc/output/begin_frame_args_unittest.cc b/cc/output/begin_frame_args_unittest.cc
index eb63cc7..65e0e9f6 100644
--- a/cc/output/begin_frame_args_unittest.cc
+++ b/cc/output/begin_frame_args_unittest.cc
@@ -14,56 +14,79 @@
 
 TEST(BeginFrameArgsTest, Helpers) {
   // Quick create methods work
-  BeginFrameArgs args0 = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+  BeginFrameArgs args0 =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
   EXPECT_TRUE(args0.IsValid()) << args0;
 
   BeginFrameArgs args1 =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 0, -1);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 0, 0, -1);
   EXPECT_FALSE(args1.IsValid()) << args1;
 
   BeginFrameArgs args2 =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 1, 2, 3);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 10, 1, 2, 3);
   EXPECT_TRUE(args2.IsValid()) << args2;
+  EXPECT_EQ(123u, args2.source_id);
+  EXPECT_EQ(10u, args2.sequence_number);
   EXPECT_EQ(1, args2.frame_time.ToInternalValue());
   EXPECT_EQ(2, args2.deadline.ToInternalValue());
   EXPECT_EQ(3, args2.interval.ToInternalValue());
   EXPECT_EQ(BeginFrameArgs::NORMAL, args2.type);
 
   BeginFrameArgs args4 = CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 1, 2, 3, BeginFrameArgs::MISSED);
+      BEGINFRAME_FROM_HERE, 234, 20, 1, 2, 3, BeginFrameArgs::MISSED);
   EXPECT_TRUE(args4.IsValid()) << args4;
+  EXPECT_EQ(234u, args4.source_id);
+  EXPECT_EQ(20u, args4.sequence_number);
   EXPECT_EQ(1, args4.frame_time.ToInternalValue());
   EXPECT_EQ(2, args4.deadline.ToInternalValue());
   EXPECT_EQ(3, args4.interval.ToInternalValue());
   EXPECT_EQ(BeginFrameArgs::MISSED, args4.type);
 
   // operator==
-  EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 4, 5, 6),
-            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 4, 5, 6));
+  EXPECT_EQ(
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 20, 4, 5, 6),
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 20, 4, 5, 6));
 
   EXPECT_NONFATAL_FAILURE(
-      EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 7, 8, 9,
-                                               BeginFrameArgs::MISSED),
-                CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 7, 8, 9)),
+      EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 30, 7,
+                                               8, 9, BeginFrameArgs::MISSED),
+                CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 30, 7,
+                                               8, 9)),
       "");
 
   EXPECT_NONFATAL_FAILURE(
-      EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 4, 5, 6),
-                CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 7, 8, 9)),
+      EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 30, 4,
+                                               5, 6),
+                CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 30, 7,
+                                               8, 9)),
+      "");
+
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 30, 7,
+                                               8, 9),
+                CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 40, 7,
+                                               8, 9)),
+      "");
+
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_EQ(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 123, 30, 7,
+                                               8, 9),
+                CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 234, 30, 7,
+                                               8, 9)),
       "");
 
   // operator<<
   std::stringstream out1;
   out1 << args1;
-  EXPECT_EQ("BeginFrameArgs(NORMAL, 0, 0, -1us)", out1.str());
+  EXPECT_EQ("BeginFrameArgs(NORMAL, 0, 1, 0, 0, -1us)", out1.str());
   std::stringstream out2;
   out2 << args2;
-  EXPECT_EQ("BeginFrameArgs(NORMAL, 1, 2, 3us)", out2.str());
+  EXPECT_EQ("BeginFrameArgs(NORMAL, 123, 10, 1, 2, 3us)", out2.str());
 
   // PrintTo
-  EXPECT_EQ(std::string("BeginFrameArgs(NORMAL, 0, 0, -1us)"),
+  EXPECT_EQ(std::string("BeginFrameArgs(NORMAL, 0, 1, 0, 0, -1us)"),
             ::testing::PrintToString(args1));
-  EXPECT_EQ(std::string("BeginFrameArgs(NORMAL, 1, 2, 3us)"),
+  EXPECT_EQ(std::string("BeginFrameArgs(NORMAL, 123, 10, 1, 2, 3us)"),
             ::testing::PrintToString(args2));
 }
 
@@ -74,10 +97,12 @@
   EXPECT_TRUE(args1.on_critical_path);
 
   BeginFrameArgs args2 = BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, base::TimeTicks::FromInternalValue(1),
+      BEGINFRAME_FROM_HERE, 123, 10, base::TimeTicks::FromInternalValue(1),
       base::TimeTicks::FromInternalValue(2),
       base::TimeDelta::FromInternalValue(3), BeginFrameArgs::NORMAL);
   EXPECT_TRUE(args2.IsValid()) << args2;
+  EXPECT_EQ(123u, args2.source_id) << args2;
+  EXPECT_EQ(10u, args2.sequence_number) << args2;
   EXPECT_EQ(1, args2.frame_time.ToInternalValue()) << args2;
   EXPECT_EQ(2, args2.deadline.ToInternalValue()) << args2;
   EXPECT_EQ(3, args2.interval.ToInternalValue()) << args2;
@@ -88,7 +113,7 @@
 TEST(BeginFrameArgsTest, Location) {
   tracked_objects::Location expected_location = BEGINFRAME_FROM_HERE;
 
-  BeginFrameArgs args = CreateBeginFrameArgsForTesting(expected_location);
+  BeginFrameArgs args = CreateBeginFrameArgsForTesting(expected_location, 0, 1);
   EXPECT_EQ(expected_location.ToString(), args.created_from.ToString());
 }
 #endif
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index 4c859a7..a7ba684d 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include "base/atomic_sequence_num.h"
 #include "base/auto_reset.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -25,7 +26,7 @@
 static const double kDoubleTickDivisor = 2.0;
 }
 
-// BeginFrameObserverBase -----------------------------------------------
+// BeginFrameObserverBase -------------------------------------------------
 BeginFrameObserverBase::BeginFrameObserverBase()
     : last_begin_frame_args_(), dropped_begin_frame_args_(0) {
 }
@@ -33,9 +34,12 @@
 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const {
   return last_begin_frame_args_;
 }
+
 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) {
   DCHECK(args.IsValid());
   DCHECK(args.frame_time >= last_begin_frame_args_.frame_time);
+  DCHECK(args.sequence_number > last_begin_frame_args_.sequence_number ||
+         args.source_id != last_begin_frame_args_.source_id);
   bool used = OnBeginFrameDerivedImpl(args);
   if (used) {
     last_begin_frame_args_ = args;
@@ -44,17 +48,31 @@
   }
 }
 
+// BeginFrameSource -------------------------------------------------------
+namespace {
+static base::StaticAtomicSequenceNumber g_next_source_id;
+}  // namespace
+
+BeginFrameSource::BeginFrameSource() : source_id_(g_next_source_id.GetNext()) {}
+
+uint32_t BeginFrameSource::source_id() const {
+  return source_id_;
+}
+
+// StubBeginFrameSource ---------------------------------------------------
 bool StubBeginFrameSource::IsThrottled() const {
   return true;
 }
 
-// SyntheticBeginFrameSource ---------------------------------------------
+// SyntheticBeginFrameSource ----------------------------------------------
 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default;
 
-// BackToBackBeginFrameSource --------------------------------------------
+// BackToBackBeginFrameSource ---------------------------------------------
 BackToBackBeginFrameSource::BackToBackBeginFrameSource(
     std::unique_ptr<DelayBasedTimeSource> time_source)
-    : time_source_(std::move(time_source)), weak_factory_(this) {
+    : time_source_(std::move(time_source)),
+      next_sequence_number_(BeginFrameArgs::kStartingFrameNumber),
+      weak_factory_(this) {
   time_source_->SetClient(this);
   // The time_source_ ticks immediately, so we SetActive(true) for a single
   // tick when we need it, and keep it as SetActive(false) otherwise.
@@ -97,8 +115,9 @@
   base::TimeTicks frame_time = time_source_->LastTickTime();
   base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval();
   BeginFrameArgs args = BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, frame_time, frame_time + default_interval,
-      default_interval, BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, frame_time,
+      frame_time + default_interval, default_interval, BeginFrameArgs::NORMAL);
+  next_sequence_number_++;
 
   // This must happen after getting the LastTickTime() from the time source.
   time_source_->SetActive(false);
@@ -113,7 +132,8 @@
 // DelayBasedBeginFrameSource ---------------------------------------------
 DelayBasedBeginFrameSource::DelayBasedBeginFrameSource(
     std::unique_ptr<DelayBasedTimeSource> time_source)
-    : time_source_(std::move(time_source)) {
+    : time_source_(std::move(time_source)),
+      next_sequence_number_(BeginFrameArgs::kStartingFrameNumber) {
   time_source_->SetClient(this);
 }
 
@@ -142,9 +162,10 @@
 BeginFrameArgs DelayBasedBeginFrameSource::CreateBeginFrameArgs(
     base::TimeTicks frame_time,
     BeginFrameArgs::BeginFrameArgsType type) {
-  return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time,
-                                time_source_->NextTickTime(),
-                                time_source_->Interval(), type);
+  uint64_t sequence_number = next_sequence_number_++;
+  return BeginFrameArgs::Create(
+      BEGINFRAME_FROM_HERE, source_id(), sequence_number, frame_time,
+      time_source_->NextTickTime(), time_source_->Interval(), type);
 }
 
 void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) {
@@ -154,14 +175,33 @@
   observers_.insert(obs);
   obs->OnBeginFrameSourcePausedChanged(false);
   time_source_->SetActive(true);
-  BeginFrameArgs args = CreateBeginFrameArgs(
-      time_source_->NextTickTime() - time_source_->Interval(),
-      BeginFrameArgs::MISSED);
+
+  // Missed args should correspond to |current_begin_frame_args_| (particularly,
+  // have the same sequence number) if |current_begin_frame_args_| still
+  // correspond to the last time the time source should have ticked. This may
+  // not be the case if OnTimerTick() has never run yet, the time source was
+  // inactive before AddObserver() was called, or the interval changed. In such
+  // a case, we create new args with a new sequence number.
+  base::TimeTicks last_or_missed_tick_time =
+      time_source_->NextTickTime() - time_source_->Interval();
+  if (current_begin_frame_args_.IsValid() &&
+      current_begin_frame_args_.frame_time == last_or_missed_tick_time &&
+      current_begin_frame_args_.interval == time_source_->Interval()) {
+    // Ensure that the args have the right type.
+    current_begin_frame_args_.type = BeginFrameArgs::MISSED;
+  } else {
+    // The args are not up to date and we need to create new ones with the
+    // missed tick's time and a new sequence number.
+    current_begin_frame_args_ =
+        CreateBeginFrameArgs(last_or_missed_tick_time, BeginFrameArgs::MISSED);
+  }
+
   BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
   if (!last_args.IsValid() ||
-      (args.frame_time >
-       last_args.frame_time + args.interval / kDoubleTickDivisor)) {
-    obs->OnBeginFrame(args);
+      (current_begin_frame_args_.frame_time >
+       last_args.frame_time +
+           current_begin_frame_args_.interval / kDoubleTickDivisor)) {
+    obs->OnBeginFrame(current_begin_frame_args_);
   }
 }
 
@@ -179,18 +219,21 @@
 }
 
 void DelayBasedBeginFrameSource::OnTimerTick() {
-  BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(),
-                                             BeginFrameArgs::NORMAL);
+  current_begin_frame_args_ = CreateBeginFrameArgs(time_source_->LastTickTime(),
+                                                   BeginFrameArgs::NORMAL);
   std::unordered_set<BeginFrameObserver*> observers(observers_);
   for (auto* obs : observers) {
     BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
     if (!last_args.IsValid() ||
-        (args.frame_time >
-         last_args.frame_time + args.interval / kDoubleTickDivisor))
-      obs->OnBeginFrame(args);
+        (current_begin_frame_args_.frame_time >
+         last_args.frame_time +
+             current_begin_frame_args_.interval / kDoubleTickDivisor)) {
+      obs->OnBeginFrame(current_begin_frame_args_);
+    }
   }
 }
 
+// ExternalBeginFrameSource -----------------------------------------------
 ExternalBeginFrameSource::ExternalBeginFrameSource(
     ExternalBeginFrameSourceClient* client)
     : client_(client) {
@@ -214,6 +257,9 @@
     BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
     if (!last_args.IsValid() ||
         (missed_begin_frame_args_.frame_time > last_args.frame_time)) {
+      DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) ||
+             (missed_begin_frame_args_.sequence_number >
+              last_args.sequence_number));
       obs->OnBeginFrame(missed_begin_frame_args_);
     }
   }
diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h
index bde01afd..c25fff6 100644
--- a/cc/scheduler/begin_frame_source.h
+++ b/cc/scheduler/begin_frame_source.h
@@ -26,8 +26,10 @@
   virtual ~BeginFrameObserver() {}
 
   // The |args| given to OnBeginFrame is guaranteed to have
-  // |args|.IsValid()==true and have |args|.frame_time
-  // field be strictly greater than the previous call.
+  // |args|.IsValid()==true. If |args|.source_id did not change between
+  // invocations, |args|.sequence_number is guaranteed to be be strictly greater
+  // than the previous call. Further, |args|.frame_time is guaranteed to be
+  // greater than or equal to the previous call even if the source_id changes.
   //
   // Side effects: This function can (and most of the time *will*) change the
   // return value of the LastUsedBeginFrameArgs method. See the documentation
@@ -99,6 +101,7 @@
 // all BeginFrameSources *must* provide.
 class CC_EXPORT BeginFrameSource {
  public:
+  BeginFrameSource();
   virtual ~BeginFrameSource() {}
 
   // DidFinishFrame provides back pressure to a frame source about frame
@@ -116,6 +119,15 @@
   // Returns false if the begin frame source will just continue to produce
   // begin frames without waiting.
   virtual bool IsThrottled() const = 0;
+
+  // Returns an identifier for this BeginFrameSource. Guaranteed unique within a
+  // process, but not across processes. This is used to create BeginFrames that
+  // originate at this source. Note that BeginFrameSources may pass on
+  // BeginFrames created by other sources, with different IDs.
+  uint32_t source_id() const;
+
+ private:
+  uint32_t source_id_;
 };
 
 // A BeginFrameSource that does nothing.
@@ -167,6 +179,7 @@
   std::unique_ptr<DelayBasedTimeSource> time_source_;
   std::unordered_set<BeginFrameObserver*> observers_;
   std::unordered_set<BeginFrameObserver*> pending_begin_frame_observers_;
+  uint64_t next_sequence_number_;
   base::WeakPtrFactory<BackToBackBeginFrameSource> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BackToBackBeginFrameSource);
@@ -204,6 +217,8 @@
   std::unordered_set<BeginFrameObserver*> observers_;
   base::TimeTicks last_timebase_;
   base::TimeDelta authoritative_interval_;
+  BeginFrameArgs current_begin_frame_args_;
+  uint64_t next_sequence_number_;
 
   DISALLOW_COPY_AND_ASSIGN(DelayBasedBeginFrameSource);
 };
diff --git a/cc/scheduler/begin_frame_source_unittest.cc b/cc/scheduler/begin_frame_source_unittest.cc
index 450e154..8250c6c 100644
--- a/cc/scheduler/begin_frame_source_unittest.cc
+++ b/cc/scheduler/begin_frame_source_unittest.cc
@@ -19,6 +19,17 @@
 namespace cc {
 namespace {
 
+// BeginFrameSource testing ----------------------------------------------------
+TEST(BeginFrameSourceTest, SourceIdsAreUnique) {
+  StubBeginFrameSource source1;
+  StubBeginFrameSource source2;
+  StubBeginFrameSource source3;
+  EXPECT_NE(source1.source_id(), source2.source_id());
+  EXPECT_NE(source1.source_id(), source3.source_id());
+  EXPECT_NE(source2.source_id(), source3.source_id());
+}
+
+// BackToBackBeginFrameSource testing ------------------------------------------
 class BackToBackBeginFrameSourceTest : public ::testing::Test {
  protected:
   static const int64_t kDeadline;
@@ -55,20 +66,23 @@
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
   EXPECT_TRUE(task_runner_->HasPendingTasks());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
+                          1100 + kDeadline, kInterval);
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   source_->DidFinishFrame(obs_.get(), 0);
   task_runner_->RunPendingTasks();
 }
 
 TEST_F(BackToBackBeginFrameSourceTest,
-       DidFinishFrameThenRemoveObserverProducesNoFrame) {
+       RemoveObserverThenDidFinishFrameProducesNoFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   source_->RemoveObserver(obs_.get());
@@ -82,10 +96,11 @@
 }
 
 TEST_F(BackToBackBeginFrameSourceTest,
-       RemoveObserverThenDidFinishFrameProducesNoFrame) {
+       DidFinishFrameThenRemoveObserverProducesNoFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
@@ -100,7 +115,8 @@
        TogglingObserverThenDidFinishFrameProducesCorrectFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
@@ -116,7 +132,8 @@
   now_src_->Advance(base::TimeDelta::FromMicroseconds(10));
   // The begin frame is posted at the time when the observer was added,
   // so it ignores changes to "now" afterward.
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1110, 1110 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1110,
+                          1110 + kDeadline, kInterval);
   EXPECT_TRUE(task_runner_->HasPendingTasks());
   task_runner_->RunPendingTasks();
 }
@@ -125,7 +142,8 @@
        DidFinishFrameThenTogglingObserverProducesCorrectFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
@@ -141,7 +159,8 @@
   now_src_->Advance(base::TimeDelta::FromMicroseconds(10));
   // Ticks at the time at which the observer was added, ignoring the
   // last change to "now".
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1120, 1120 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1120,
+                          1120 + kDeadline, kInterval);
   EXPECT_TRUE(task_runner_->HasPendingTasks());
   task_runner_->RunPendingTasks();
 }
@@ -157,7 +176,8 @@
 TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameRemainingFrames) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   // Runs the pending begin frame.
   task_runner_->RunPendingTasks();
   // While running the begin frame, the next frame was cancelled, this
@@ -174,7 +194,8 @@
   source_->DidFinishFrame(obs_.get(), 1);
   EXPECT_FALSE(task_runner_->HasPendingTasks());
 
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
+                          1100 + kDeadline, kInterval);
   source_->DidFinishFrame(obs_.get(), 0);
   EXPECT_EQ(base::TimeDelta(), task_runner_->DelayToNextTaskTime());
   task_runner_->RunPendingTasks();
@@ -183,28 +204,32 @@
 TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   source_->DidFinishFrame(obs_.get(), 0);
   source_->DidFinishFrame(obs_.get(), 0);
   source_->DidFinishFrame(obs_.get(), 0);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
+                          1100 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   source_->DidFinishFrame(obs_.get(), 0);
   source_->DidFinishFrame(obs_.get(), 0);
   source_->DidFinishFrame(obs_.get(), 0);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1200, 1200 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 1200,
+                          1200 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 }
 
 TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 1, 1000,
+                          1000 + kDeadline, kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
@@ -212,7 +237,8 @@
   now_src_->Advance(base::TimeDelta::FromMicroseconds(50));
   // Ticks at the time the last frame finished, so ignores the last change to
   // "now".
-  EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 1100,
+                          1100 + kDeadline, kInterval);
 
   EXPECT_TRUE(task_runner_->HasPendingTasks());
   task_runner_->RunPendingTasks();
@@ -226,15 +252,19 @@
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
   source_->AddObserver(&obs2);
 
-  EXPECT_BEGIN_FRAME_USED(obs1, 1000, 1000 + kDeadline, kInterval);
-  EXPECT_BEGIN_FRAME_USED(obs2, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 1, 1000, 1000 + kDeadline,
+                          kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 1, 1000, 1000 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   source_->DidFinishFrame(&obs1, 0);
   source_->DidFinishFrame(&obs2, 0);
-  EXPECT_BEGIN_FRAME_USED(obs1, 1100, 1100 + kDeadline, kInterval);
-  EXPECT_BEGIN_FRAME_USED(obs2, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 1100, 1100 + kDeadline,
+                          kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
@@ -251,18 +281,21 @@
 
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false);
   source_->AddObserver(&obs1);
-  EXPECT_BEGIN_FRAME_USED(obs1, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 1, 1000, 1000 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
   source_->AddObserver(&obs2);
-  EXPECT_BEGIN_FRAME_USED(obs2, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   source_->DidFinishFrame(&obs1, 0);
-  EXPECT_BEGIN_FRAME_USED(obs1, 1200, 1200 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 3, 1200, 1200 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   source_->DidFinishFrame(&obs1, 0);
@@ -275,7 +308,8 @@
 
   now_src_->Advance(base::TimeDelta::FromMicroseconds(100));
   source_->DidFinishFrame(&obs2, 0);
-  EXPECT_BEGIN_FRAME_USED(obs2, 1300, 1300 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 4, 1300, 1300 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   source_->DidFinishFrame(&obs2, 0);
@@ -289,8 +323,10 @@
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
   source_->AddObserver(&obs1);
   source_->AddObserver(&obs2);
-  EXPECT_BEGIN_FRAME_USED(obs1, 1000, 1000 + kDeadline, kInterval);
-  EXPECT_BEGIN_FRAME_USED(obs2, 1000, 1000 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 1, 1000, 1000 + kDeadline,
+                          kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 1, 1000, 1000 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   // |obs1| finishes first.
@@ -303,8 +339,10 @@
 
   // Because the begin frame source already ticked when |obs1| finished,
   // we see it as the frame time for both observers.
-  EXPECT_BEGIN_FRAME_USED(obs1, 1100, 1100 + kDeadline, kInterval);
-  EXPECT_BEGIN_FRAME_USED(obs2, 1100, 1100 + kDeadline, kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 1100, 1100 + kDeadline,
+                          kInterval);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 2, 1100, 1100 + kDeadline,
+                          kInterval);
   task_runner_->RunPendingTasks();
 
   source_->DidFinishFrame(&obs1, 0);
@@ -341,18 +379,20 @@
        AddObserverCallsOnBeginFrameWithMissedTick) {
   now_src_->Advance(base::TimeDelta::FromMicroseconds(9010));
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 10000, 20000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 10000, 20000,
+                                 10000);
   source_->AddObserver(obs_.get());  // Should cause the last tick to be sent
   // No tasks should need to be run for this to occur.
 }
 
 TEST_F(DelayBasedBeginFrameSourceTest, AddObserverCallsCausesOnBeginFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 10000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
+                                 10000);
   source_->AddObserver(obs_.get());
   EXPECT_EQ(10000, task_runner_->NextTaskTime().ToInternalValue());
 
-  EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
   now_src_->Advance(base::TimeDelta::FromMicroseconds(9010));
   task_runner_->RunPendingTasks();
 }
@@ -361,11 +401,12 @@
   task_runner_->SetAutoAdvanceNowToPendingTasks(true);
 
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 10000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
+                                 10000);
   source_->AddObserver(obs_.get());
-  EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 20000, 30000, 10000);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 30000, 40000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
   task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(30001));
 
   source_->RemoveObserver(obs_.get());
@@ -376,21 +417,22 @@
 TEST_F(DelayBasedBeginFrameSourceTest, VSyncChanges) {
   task_runner_->SetAutoAdvanceNowToPendingTasks(true);
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 10000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 0, 10000,
+                                 10000);
   source_->AddObserver(obs_.get());
 
-  EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 20000, 30000, 10000);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 30000, 40000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10000, 20000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20000, 30000, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30000, 40000, 10000);
   task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(30001));
 
   // Update the vsync information
   source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(27500),
                                    base::TimeDelta::FromMicroseconds(10001));
 
-  EXPECT_BEGIN_FRAME_USED(*obs_, 40000, 47502, 10001);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 47502, 57503, 10001);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 57503, 67504, 10001);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 5, 40000, 47502, 10001);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 6, 47502, 57503, 10001);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 7, 57503, 67504, 10001);
   task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(60000));
 }
 
@@ -399,25 +441,26 @@
   source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(500),
                                    base::TimeDelta::FromMicroseconds(10000));
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 500, 10500, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, source_->source_id(), 1, 500, 10500,
+                                 10000);
   source_->AddObserver(obs_.get());
 
-  EXPECT_BEGIN_FRAME_USED(*obs_, 10500, 20500, 10000);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 20500, 30500, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 2, 10500, 20500, 10000);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 3, 20500, 30500, 10000);
   task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(20501));
 
   // This will keep the same timebase, so 500, 9999
   source_->SetAuthoritativeVSyncInterval(
       base::TimeDelta::FromMicroseconds(9999));
-  EXPECT_BEGIN_FRAME_USED(*obs_, 30500, 40496, 9999);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 40496, 50495, 9999);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 4, 30500, 40496, 9999);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 5, 40496, 50495, 9999);
   task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(40497));
 
   // Change the vsync params, but the new interval will be ignored.
   source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(400),
                                    base::TimeDelta::FromMicroseconds(1));
-  EXPECT_BEGIN_FRAME_USED(*obs_, 50495, 60394, 9999);
-  EXPECT_BEGIN_FRAME_USED(*obs_, 60394, 70393, 9999);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 6, 50495, 60394, 9999);
+  EXPECT_BEGIN_FRAME_USED(*obs_, source_->source_id(), 7, 60394, 70393, 9999);
   task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(60395));
 }
 
@@ -427,25 +470,28 @@
   // now_src_ starts off at 1000.
   task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(9010));
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(obs1, 10000, 20000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(obs1, source_->source_id(), 1, 10000, 20000,
+                                 10000);
   source_->AddObserver(&obs1);  // Should cause the last tick to be sent
   // No tasks should need to be run for this to occur.
 
-  EXPECT_BEGIN_FRAME_USED(obs1, 20000, 30000, 10000);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 2, 20000, 30000, 10000);
   task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(10000));
 
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(obs2, 20000, 30000, 10000);
+  // Sequence number unchanged for missed frame with time of last normal frame.
+  EXPECT_BEGIN_FRAME_USED_MISSED(obs2, source_->source_id(), 2, 20000, 30000,
+                                 10000);
   source_->AddObserver(&obs2);  // Should cause the last tick to be sent
   // No tasks should need to be run for this to occur.
 
-  EXPECT_BEGIN_FRAME_USED(obs1, 30000, 40000, 10000);
-  EXPECT_BEGIN_FRAME_USED(obs2, 30000, 40000, 10000);
+  EXPECT_BEGIN_FRAME_USED(obs1, source_->source_id(), 3, 30000, 40000, 10000);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 3, 30000, 40000, 10000);
   task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(10000));
 
   source_->RemoveObserver(&obs1);
 
-  EXPECT_BEGIN_FRAME_USED(obs2, 40000, 50000, 10000);
+  EXPECT_BEGIN_FRAME_USED(obs2, source_->source_id(), 4, 40000, 50000, 10000);
   task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(10000));
 
   source_->RemoveObserver(&obs2);
@@ -457,7 +503,7 @@
   StrictMock<MockBeginFrameObserver> obs;
 
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(obs, 0, 10000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 1, 0, 10000, 10000);
   source_->AddObserver(&obs);
 
   source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(5000),
@@ -471,7 +517,7 @@
   source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(10000),
                                    base::TimeDelta::FromInternalValue(10000));
   now_src_->Advance(base::TimeDelta::FromInternalValue(5000));
-  EXPECT_BEGIN_FRAME_USED(obs, 10000, 20000, 10000);
+  EXPECT_BEGIN_FRAME_USED(obs, source_->source_id(), 2, 10000, 20000, 10000);
   task_runner_->RunPendingTasks();
 }
 
@@ -479,7 +525,7 @@
   StrictMock<MockBeginFrameObserver> obs;
 
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(obs, 0, 10000, 10000);
+  EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 1, 0, 10000, 10000);
   source_->AddObserver(&obs);
   source_->RemoveObserver(&obs);
 
@@ -489,6 +535,8 @@
 
   // No missed frame received.
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
+  // This does not cause a missed BeginFrame, but the sequence number is
+  // incremented, because the possible missed frame has different time/interval.
   source_->AddObserver(&obs);
   source_->RemoveObserver(&obs);
 
@@ -497,7 +545,10 @@
                                    base::TimeDelta::FromInternalValue(10000));
   now_src_->Advance(base::TimeDelta::FromInternalValue(5000));
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false);
-  EXPECT_BEGIN_FRAME_USED_MISSED(obs, 10000, 20000, 10000);
+  // Sequence number is incremented again, because the missed frame has
+  // different time/interval.
+  EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_->source_id(), 3, 10000, 20000,
+                                 10000);
   source_->AddObserver(&obs);
   source_->RemoveObserver(&obs);
 }
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index ace12c6..64f4acd3 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
+#include "cc/output/begin_frame_args.h"
 #include "cc/test/begin_frame_args_test.h"
 #include "cc/test/fake_external_begin_frame_source.h"
 #include "cc/test/ordered_simple_task_runner.h"
@@ -236,7 +237,9 @@
   SchedulerTest()
       : now_src_(new base::SimpleTestTickClock()),
         task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)),
-        fake_external_begin_frame_source_(nullptr) {
+        fake_external_begin_frame_source_(nullptr),
+        fake_compositor_timing_history_(nullptr),
+        next_begin_frame_number_(BeginFrameArgs::kStartingFrameNumber) {
     now_src_->Advance(base::TimeDelta::FromMicroseconds(10000));
     // A bunch of tests require NowTicks()
     // to be > BeginFrameArgs::DefaultInterval()
@@ -405,8 +408,10 @@
     // Creep the time forward so that any BeginFrameArgs is not equal to the
     // last one otherwise we violate the BeginFrameSource contract.
     now_src_->Advance(BeginFrameArgs::DefaultInterval());
-    BeginFrameArgs args =
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
+    BeginFrameArgs args = CreateBeginFrameArgsForTesting(
+        BEGINFRAME_FROM_HERE, fake_external_begin_frame_source_->source_id(),
+        next_begin_frame_number_, now_src());
+    next_begin_frame_number_++;
     fake_external_begin_frame_source_->TestOnBeginFrame(args);
     return args;
   }
@@ -435,6 +440,7 @@
   std::unique_ptr<FakeSchedulerClient> client_;
   std::unique_ptr<TestScheduler> scheduler_;
   FakeCompositorTimingHistory* fake_compositor_timing_history_;
+  uint64_t next_begin_frame_number_;
 };
 
 TEST_F(SchedulerTest, InitializeCompositorFrameSinkDoesNotBeginImplFrame) {
@@ -1332,8 +1338,10 @@
 
   // Advance frame and create a begin frame.
   now_src_->Advance(BeginFrameArgs::DefaultInterval());
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
+  BeginFrameArgs args = CreateBeginFrameArgsForTesting(
+      BEGINFRAME_FROM_HERE, fake_external_begin_frame_source_->source_id(),
+      next_begin_frame_number_, now_src());
+  next_begin_frame_number_++;
 
   // Deliver this begin frame super late.
   now_src_->Advance(BeginFrameArgs::DefaultInterval() * 100);
diff --git a/cc/surfaces/display_scheduler_unittest.cc b/cc/surfaces/display_scheduler_unittest.cc
index ec9c221..c7b5bd81 100644
--- a/cc/surfaces/display_scheduler_unittest.cc
+++ b/cc/surfaces/display_scheduler_unittest.cc
@@ -89,8 +89,9 @@
     base::TimeTicks frame_time = now_src_.NowTicks();
     base::TimeDelta interval = BeginFrameArgs::DefaultInterval();
     base::TimeTicks deadline = frame_time + interval;
+    // FakeBeginFrameSource deals with |source_id| and |sequence_number|.
     fake_begin_frame_source_.TestOnBeginFrame(
-        BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
+        BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0, 1, frame_time, deadline,
                                interval, BeginFrameArgs::NORMAL));
   }
 
diff --git a/cc/test/begin_frame_args_test.cc b/cc/test/begin_frame_args_test.cc
index 8b4dfd3b..7ce80b5 100644
--- a/cc/test/begin_frame_args_test.cc
+++ b/cc/test/begin_frame_args_test.cc
@@ -12,15 +12,20 @@
 namespace cc {
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(
-    BeginFrameArgs::CreationLocation location) {
-  return CreateBeginFrameArgsForTesting(location, base::TimeTicks::Now());
+    BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number) {
+  return CreateBeginFrameArgsForTesting(location, source_id, sequence_number,
+                                        base::TimeTicks::Now());
 }
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     base::TimeTicks frame_time) {
   return BeginFrameArgs::Create(
-      location, frame_time,
+      location, source_id, sequence_number, frame_time,
       frame_time + BeginFrameArgs::DefaultInterval() -
           BeginFrameArgs::DefaultEstimatedParentDrawTime(),
       BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
@@ -28,40 +33,51 @@
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     int64_t frame_time,
     int64_t deadline,
     int64_t interval) {
-  return BeginFrameArgs::Create(
-      location, base::TimeTicks::FromInternalValue(frame_time),
-      base::TimeTicks::FromInternalValue(deadline),
-      base::TimeDelta::FromInternalValue(interval), BeginFrameArgs::NORMAL);
+  return BeginFrameArgs::Create(location, source_id, sequence_number,
+                                base::TimeTicks::FromInternalValue(frame_time),
+                                base::TimeTicks::FromInternalValue(deadline),
+                                base::TimeDelta::FromInternalValue(interval),
+                                BeginFrameArgs::NORMAL);
 }
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     int64_t frame_time,
     int64_t deadline,
     int64_t interval,
     BeginFrameArgs::BeginFrameArgsType type) {
-  return BeginFrameArgs::Create(
-      location, base::TimeTicks::FromInternalValue(frame_time),
-      base::TimeTicks::FromInternalValue(deadline),
-      base::TimeDelta::FromInternalValue(interval), type);
+  return BeginFrameArgs::Create(location, source_id, sequence_number,
+                                base::TimeTicks::FromInternalValue(frame_time),
+                                base::TimeTicks::FromInternalValue(deadline),
+                                base::TimeDelta::FromInternalValue(interval),
+                                type);
 }
 
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     base::SimpleTestTickClock* now_src) {
   base::TimeTicks now = now_src->NowTicks();
   return BeginFrameArgs::Create(
-      location, now, now + BeginFrameArgs::DefaultInterval() -
-                         BeginFrameArgs::DefaultEstimatedParentDrawTime(),
+      location, source_id, sequence_number, now,
+      now + BeginFrameArgs::DefaultInterval() -
+          BeginFrameArgs::DefaultEstimatedParentDrawTime(),
       BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
 }
 
 bool operator==(const BeginFrameArgs& lhs, const BeginFrameArgs& rhs) {
-  return (lhs.type == rhs.type) && (lhs.frame_time == rhs.frame_time) &&
-         (lhs.deadline == rhs.deadline) && (lhs.interval == rhs.interval);
+  return (lhs.type == rhs.type) && (lhs.source_id == rhs.source_id) &&
+         (lhs.sequence_number == rhs.sequence_number) &&
+         (lhs.frame_time == rhs.frame_time) && (lhs.deadline == rhs.deadline) &&
+         (lhs.interval == rhs.interval);
 }
 
 ::std::ostream& operator<<(::std::ostream& os, const BeginFrameArgs& args) {
@@ -71,6 +87,7 @@
 
 void PrintTo(const BeginFrameArgs& args, ::std::ostream* os) {
   *os << "BeginFrameArgs(" << BeginFrameArgs::TypeToString(args.type) << ", "
+      << args.source_id << ", " << args.sequence_number << ", "
       << args.frame_time.ToInternalValue() << ", "
       << args.deadline.ToInternalValue() << ", "
       << args.interval.InMicroseconds() << "us)";
diff --git a/cc/test/begin_frame_args_test.h b/cc/test/begin_frame_args_test.h
index d798094..57cee81f 100644
--- a/cc/test/begin_frame_args_test.h
+++ b/cc/test/begin_frame_args_test.h
@@ -18,17 +18,25 @@
 
 // Functions for quickly creating BeginFrameArgs
 BeginFrameArgs CreateBeginFrameArgsForTesting(
-    BeginFrameArgs::CreationLocation location);
+    BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number);
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     base::TimeTicks frame_time);
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     int64_t frame_time,
     int64_t deadline,
     int64_t interval);
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     int64_t frame_time,
     int64_t deadline,
     int64_t interval,
@@ -38,6 +46,8 @@
 // OrderSimpleTaskRunner.
 BeginFrameArgs CreateBeginFrameArgsForTesting(
     BeginFrameArgs::CreationLocation location,
+    uint32_t source_id,
+    uint64_t sequence_number,
     base::SimpleTestTickClock* now_src);
 
 // gtest helpers -- these *must* be in the same namespace as the types they
diff --git a/cc/test/begin_frame_source_test.cc b/cc/test/begin_frame_source_test.cc
index ef1c033..997aa9955 100644
--- a/cc/test/begin_frame_source_test.cc
+++ b/cc/test/begin_frame_source_test.cc
@@ -35,6 +35,8 @@
         FROM_HERE_WITH_EXPLICIT_FUNCTION(
             "MockBeginFrameObserver::kDefaultBeginFrameArgs"),
 #endif
+        0,
+        BeginFrameArgs::kStartingFrameNumber,
         -1,
         -1,
         -1);
diff --git a/cc/test/begin_frame_source_test.h b/cc/test/begin_frame_source_test.h
index cde725b..8be41ae 100644
--- a/cc/test/begin_frame_source_test.h
+++ b/cc/test/begin_frame_source_test.h
@@ -12,24 +12,28 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 // Macros to help set up expected calls on the MockBeginFrameObserver.
-#define EXPECT_BEGIN_FRAME_DROP(obs, frame_time, deadline, interval)      \
-  EXPECT_CALL((obs),                                                      \
-              OnBeginFrame(CreateBeginFrameArgsForTesting(                \
-                  BEGINFRAME_FROM_HERE, frame_time, deadline, interval))) \
-      .Times(1)                                                           \
+#define EXPECT_BEGIN_FRAME_DROP(obs, source_id, sequence_number, frame_time, \
+                                deadline, interval)                          \
+  EXPECT_CALL((obs), OnBeginFrame(CreateBeginFrameArgsForTesting(            \
+                         BEGINFRAME_FROM_HERE, source_id, sequence_number,   \
+                         frame_time, deadline, interval)))                   \
+      .Times(1)                                                              \
       .InSequence((obs).sequence)
 
-#define EXPECT_BEGIN_FRAME_USED(obs, frame_time, deadline, interval)      \
-  EXPECT_CALL((obs),                                                      \
-              OnBeginFrame(CreateBeginFrameArgsForTesting(                \
-                  BEGINFRAME_FROM_HERE, frame_time, deadline, interval))) \
-      .InSequence((obs).sequence)                                         \
+#define EXPECT_BEGIN_FRAME_USED(obs, source_id, sequence_number, frame_time, \
+                                deadline, interval)                          \
+  EXPECT_CALL((obs), OnBeginFrame(CreateBeginFrameArgsForTesting(            \
+                         BEGINFRAME_FROM_HERE, source_id, sequence_number,   \
+                         frame_time, deadline, interval)))                   \
+      .InSequence((obs).sequence)                                            \
       .WillOnce(::testing::SaveArg<0>(&((obs).last_begin_frame_args)))
 
-#define EXPECT_BEGIN_FRAME_USED_MISSED(obs, frame_time, deadline, interval)    \
-  EXPECT_CALL((obs), OnBeginFrame(CreateBeginFrameArgsForTesting(              \
-                         BEGINFRAME_FROM_HERE, frame_time, deadline, interval, \
-                         BeginFrameArgs::MISSED)))                             \
+#define EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_id, sequence_number,        \
+                                       frame_time, deadline, interval)         \
+  EXPECT_CALL(                                                                 \
+      (obs), OnBeginFrame(CreateBeginFrameArgsForTesting(                      \
+                 BEGINFRAME_FROM_HERE, source_id, sequence_number, frame_time, \
+                 deadline, interval, BeginFrameArgs::MISSED)))                 \
       .InSequence((obs).sequence)                                              \
       .WillOnce(::testing::SaveArg<0>(&((obs).last_begin_frame_args)))
 
@@ -40,24 +44,29 @@
 
 // Macros to send BeginFrameArgs on a FakeBeginFrameSink (and verify resulting
 // observer behaviour).
-#define SEND_BEGIN_FRAME(args_equal_to, source, frame_time, deadline, \
-                         interval)                                    \
-  {                                                                   \
-    BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs();  \
-    BeginFrameArgs new_args = CreateBeginFrameArgsForTesting(         \
-        BEGINFRAME_FROM_HERE, frame_time, deadline, interval);        \
-    ASSERT_FALSE(old_args == new_args);                               \
-    (source).TestOnBeginFrame(new_args);                              \
-    EXPECT_EQ(args_equal_to, (source).TestLastUsedBeginFrameArgs());  \
+#define SEND_BEGIN_FRAME(args_equal_to, source, sequence_number, frame_time, \
+                         deadline, interval)                                 \
+  {                                                                          \
+    BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs();         \
+    BeginFrameArgs new_args = CreateBeginFrameArgsForTesting(                \
+        BEGINFRAME_FROM_HERE, (source).source_id(), sequence_number,         \
+        frame_time, deadline, interval);                                     \
+    ASSERT_FALSE(old_args == new_args);                                      \
+    (source).TestOnBeginFrame(new_args);                                     \
+    EXPECT_EQ(args_equal_to, (source).TestLastUsedBeginFrameArgs());         \
   }
 
 // When dropping LastUsedBeginFrameArgs **shouldn't** change.
-#define SEND_BEGIN_FRAME_DROP(source, frame_time, deadline, interval) \
-  SEND_BEGIN_FRAME(old_args, source, frame_time, deadline, interval);
+#define SEND_BEGIN_FRAME_DROP(source, sequence_number, frame_time, deadline, \
+                              interval)                                      \
+  SEND_BEGIN_FRAME(old_args, source, sequence_number, frame_time, deadline,  \
+                   interval);
 
 // When used LastUsedBeginFrameArgs **should** be updated.
-#define SEND_BEGIN_FRAME_USED(source, frame_time, deadline, interval) \
-  SEND_BEGIN_FRAME(new_args, source, frame_time, deadline, interval);
+#define SEND_BEGIN_FRAME_USED(source, sequence_number, frame_time, deadline, \
+                              interval)                                      \
+  SEND_BEGIN_FRAME(new_args, source, sequence_number, frame_time, deadline,  \
+                   interval);
 
 namespace cc {
 
diff --git a/cc/test/begin_frame_source_test_unittest.cc b/cc/test/begin_frame_source_test_unittest.cc
index 601da31..d3765cc 100644
--- a/cc/test/begin_frame_source_test_unittest.cc
+++ b/cc/test/begin_frame_source_test_unittest.cc
@@ -14,110 +14,110 @@
 TEST(MockBeginFrameObserverTest, FailOnMissingCalls) {
   EXPECT_MOCK_FAILURE({
     ::testing::NiceMock<MockBeginFrameObserver> obs;
-    EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300);
-    EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
 
-    obs.OnBeginFrame(
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 400, 600, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                    400, 600, 300));
   });
 }
 
 TEST(MockBeginFrameObserverTest, FailOnMultipleCalls) {
   EXPECT_MOCK_FAILURE({
     ::testing::NiceMock<MockBeginFrameObserver> obs;
-    EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300);
-    EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
 
-    obs.OnBeginFrame(
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
-    obs.OnBeginFrame(
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
-    obs.OnBeginFrame(
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 400, 600, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                    100, 200, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                    100, 200, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                    400, 600, 300));
   });
 }
 
 TEST(MockBeginFrameObserverTest, FailOnWrongCallOrder) {
   EXPECT_MOCK_FAILURE({
     ::testing::NiceMock<MockBeginFrameObserver> obs;
-    EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300);
-    EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
 
-    obs.OnBeginFrame(
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 400, 600, 300));
-    obs.OnBeginFrame(
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                    400, 600, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                    100, 200, 300));
   });
 }
 
 TEST(MockBeginFrameObserverTest, ExpectOnBeginFrame) {
   ::testing::NiceMock<MockBeginFrameObserver> obs;
-  EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300);
-  EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300);
-  EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 3, 700, 900, 300);
 
   EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
             MockBeginFrameObserver::kDefaultBeginFrameArgs);
 
   obs.OnBeginFrame(CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 100, 200,
+      BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
       300));  // One call to LastUsedBeginFrameArgs
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
 
   obs.OnBeginFrame(CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 400, 600,
+      BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
       300));  // Multiple calls to LastUsedBeginFrameArgs
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 400, 600, 300));
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 400, 600, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
+                                           300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
+                                           300));
 
   obs.OnBeginFrame(CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 700, 900,
+      BEGINFRAME_FROM_HERE, 0, 3, 700, 900,
       300));  // No calls to LastUsedBeginFrameArgs
 }
 
 TEST(MockBeginFrameObserverTest, ExpectOnBeginFrameStatus) {
   ::testing::NiceMock<MockBeginFrameObserver> obs;
-  EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300);
-  EXPECT_BEGIN_FRAME_DROP(obs, 400, 600, 300);
-  EXPECT_BEGIN_FRAME_DROP(obs, 450, 650, 300);
-  EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+  EXPECT_BEGIN_FRAME_DROP(obs, 0, 2, 400, 600, 300);
+  EXPECT_BEGIN_FRAME_DROP(obs, 0, 3, 450, 650, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 4, 700, 900, 300);
 
   EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
             MockBeginFrameObserver::kDefaultBeginFrameArgs);
 
   // Used
-  obs.OnBeginFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                  100, 200, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
 
   // Dropped
-  obs.OnBeginFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 400, 600, 300));
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                  400, 600, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
 
   // Dropped
-  obs.OnBeginFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 450, 650, 300));
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 100, 200, 300));
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 3,
+                                                  450, 650, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
 
   // Used
-  obs.OnBeginFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 700, 900, 300));
-  EXPECT_EQ(
-      obs.LastUsedBeginFrameArgs(),
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 700, 900, 300));
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 4,
+                                                  700, 900, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 4, 700, 900,
+                                           300));
 }
 
 }  // namespace
diff --git a/cc/test/fake_external_begin_frame_source.cc b/cc/test/fake_external_begin_frame_source.cc
index 1a15b09..23051fa 100644
--- a/cc/test/fake_external_begin_frame_source.cc
+++ b/cc/test/fake_external_begin_frame_source.cc
@@ -65,9 +65,12 @@
 void FakeExternalBeginFrameSource::TestOnBeginFrame(
     const BeginFrameArgs& args) {
   DCHECK(CalledOnValidThread());
+  BeginFrameArgs modified_args = args;
+  modified_args.source_id = source_id();
+  modified_args.sequence_number = next_begin_frame_number_++;
   std::set<BeginFrameObserver*> observers(observers_);
   for (auto* obs : observers)
-    obs->OnBeginFrame(args);
+    obs->OnBeginFrame(modified_args);
   if (tick_automatically_)
     PostTestOnBeginFrame();
 }
@@ -77,10 +80,12 @@
       base::Bind(&FakeExternalBeginFrameSource::TestOnBeginFrame,
                  weak_ptr_factory_.GetWeakPtr()));
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(begin_frame_task_.callback(),
-                 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)),
+      FROM_HERE, base::Bind(begin_frame_task_.callback(),
+                            CreateBeginFrameArgsForTesting(
+                                BEGINFRAME_FROM_HERE, source_id(),
+                                next_begin_frame_number_)),
       base::TimeDelta::FromMilliseconds(milliseconds_per_frame_));
+  next_begin_frame_number_++;
 }
 
 }  // namespace cc
diff --git a/cc/test/fake_external_begin_frame_source.h b/cc/test/fake_external_begin_frame_source.h
index 8f2d4f09..ced3b3b 100644
--- a/cc/test/fake_external_begin_frame_source.h
+++ b/cc/test/fake_external_begin_frame_source.h
@@ -10,6 +10,7 @@
 #include "base/cancelable_callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/non_thread_safe.h"
+#include "cc/output/begin_frame_args.h"
 #include "cc/scheduler/begin_frame_source.h"
 
 namespace cc {
@@ -49,6 +50,7 @@
   const double milliseconds_per_frame_;
   Client* client_ = nullptr;
   bool paused_ = false;
+  uint64_t next_begin_frame_number_ = BeginFrameArgs::kStartingFrameNumber;
   std::set<BeginFrameObserver*> observers_;
   base::CancelableCallback<void(const BeginFrameArgs&)> begin_frame_task_;
   base::WeakPtrFactory<FakeExternalBeginFrameSource> weak_ptr_factory_;
diff --git a/cc/test/fake_layer_tree_host_impl.cc b/cc/test/fake_layer_tree_host_impl.cc
index 445b63d..d6b2cd07 100644
--- a/cc/test/fake_layer_tree_host_impl.cc
+++ b/cc/test/fake_layer_tree_host_impl.cc
@@ -40,7 +40,7 @@
   // Start an impl frame so tests have a valid frame_time to work with.
   base::TimeTicks time_ticks = base::TimeTicks::FromInternalValue(1);
   WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks));
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, time_ticks));
 }
 
 FakeLayerTreeHostImpl::~FakeLayerTreeHostImpl() {
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index c540c24d..b2fd2e17 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -207,7 +207,7 @@
     host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
     // Set the BeginFrameArgs so that methods which use it are able to.
     host_impl_->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
-        BEGINFRAME_FROM_HERE,
+        BEGINFRAME_FROM_HERE, 0, 1,
         base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
     host_impl_->DidFinishImplFrame();
 
@@ -362,8 +362,8 @@
   }
 
   LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
-    LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
-        host_impl_->active_tree(), content_size);
+    LayerImpl* scroll_layer =
+        CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size);
     host_impl_->active_tree()->DidBecomeActive();
     return scroll_layer;
   }
@@ -748,10 +748,11 @@
   DrawFrame();
 
   // We should not crash if the tree is replaced while we are scrolling.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->active_tree()->DetachLayers();
 
   scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
@@ -780,9 +781,8 @@
       host_impl_->GetEventListenerProperties(EventListenerClass::kMouseWheel));
 
   // But they don't influence the actual handling of the scroll gestures.
-  InputHandler::ScrollStatus status =
-    host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                   InputHandler::WHEEL);
+  InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
+      BeginState(gfx::Point()).get(), InputHandler::WHEEL);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
   EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
             status.main_thread_scrolling_reasons);
@@ -1130,64 +1130,64 @@
 
   // Trying to scroll to the left/top will not succeed.
   EXPECT_FALSE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
           .did_scroll);
   EXPECT_FALSE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get())
           .did_scroll);
   EXPECT_FALSE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(-10, -10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10)).get())
           .did_scroll);
 
   // Scrolling to the right/bottom will succeed.
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(10, 0)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 0)).get())
           .did_scroll);
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
           .did_scroll);
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(10, 10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 10)).get())
           .did_scroll);
 
   // Scrolling to left/top will now succeed.
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
           .did_scroll);
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -10)).get())
           .did_scroll);
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(-10, -10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10)).get())
           .did_scroll);
 
   // Scrolling diagonally against an edge will succeed.
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(10, -10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, -10)).get())
           .did_scroll);
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0)).get())
           .did_scroll);
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(-10, 10)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(-10, 10)).get())
           .did_scroll);
 
   // Trying to scroll more than the available space will also succeed.
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(5000, 5000)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(5000, 5000)).get())
           .did_scroll);
 }
 
@@ -1211,10 +1211,11 @@
   DrawFrame();
   gfx::Point scroll_position(10, 10);
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(scroll_position).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
 
@@ -1229,10 +1230,11 @@
 
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(scroll_position).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
 
@@ -1245,10 +1247,11 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(scroll_position).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
+          .thread);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
 
@@ -1345,7 +1348,7 @@
 
   base::TimeTicks now = base::TimeTicks::Now();
   host_impl_->WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now));
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, now));
 
   // TODO(crbug.com/551134): We always request a new frame and a draw for
   // animations that are on the pending tree, but we don't need to do that
@@ -1457,7 +1460,7 @@
 
   base::TimeTicks now = base::TimeTicks::Now();
   host_impl_->WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now));
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, now));
   EXPECT_TRUE(did_request_next_frame_);
   did_request_next_frame_ = false;
 
@@ -1537,7 +1540,7 @@
 
   base::TimeTicks now = base::TimeTicks::Now();
   host_impl_->WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now));
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, now));
 
   host_impl_->ActivateAnimations();
   host_impl_->Animate();
@@ -1651,8 +1654,9 @@
 
     gfx::Vector2d scroll_delta(0, 10);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::WHEEL)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::WHEEL)
                   .thread);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
     host_impl_->ScrollEnd(EndState().get());
@@ -1680,9 +1684,8 @@
   inner_scroll_layer->SetDrawsContent(true);
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(500, 500),
-      outer_scroll_layer->MaxScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500),
+                   outer_scroll_layer->MaxScrollOffset());
 
   host_impl_->ScrollBegin(BeginState(gfx::Point(250, 250)).get(),
                           InputHandler::TOUCHSCREEN);
@@ -1692,12 +1695,10 @@
   host_impl_->ScrollEnd(EndState().get());
 
   // Sanity check - we're zoomed in, starting from the origin.
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(0, 0),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(0, 0),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
+                   outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
+                   inner_scroll_layer->CurrentScrollOffset());
 
   // Scroll down - only the inner viewport should scroll.
   host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
@@ -1706,12 +1707,10 @@
       UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f)).get());
   host_impl_->ScrollEnd(EndState().get());
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(50, 50),
-      inner_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(0, 0),
-      outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
+                   inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
+                   outer_scroll_layer->CurrentScrollOffset());
 
   // Scroll down - outer viewport should start scrolling after the inner is at
   // its maximum.
@@ -1721,12 +1720,10 @@
       UpdateState(gfx::Point(0, 0), gfx::Vector2dF(1000.f, 1000.f)).get());
   host_impl_->ScrollEnd(EndState().get());
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(250, 250),
-      inner_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(300, 300),
-      outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250),
+                   inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(300, 300),
+                   outer_scroll_layer->CurrentScrollOffset());
 }
 
 // Make sure scrolls smaller than a unit applied to the viewport don't get
@@ -1747,9 +1744,8 @@
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
   // Sanity checks.
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(500, 500),
-      outer_scroll_layer->MaxScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500),
+                   outer_scroll_layer->MaxScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), outer_scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll_layer->CurrentScrollOffset());
 
@@ -1758,12 +1754,10 @@
                           InputHandler::TOUCHSCREEN);
   host_impl_->ScrollBy(
       UpdateState(gfx::Point(250, 250), gfx::Vector2dF(0.125f, 0.125f)).get());
-  EXPECT_VECTOR2DF_EQ(
-      gfx::Vector2dF(0.125f, 0.125f),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR2DF_EQ(
-      gfx::Vector2dF(0, 0),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f),
+                      outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 0),
+                      inner_scroll_layer->CurrentScrollOffset());
   host_impl_->ScrollEnd(EndState().get());
 
   host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
@@ -1773,12 +1767,10 @@
                           InputHandler::TOUCHSCREEN);
   host_impl_->ScrollBy(
       UpdateState(gfx::Point(250, 250), gfx::Vector2dF(0.5f, 0.5f)).get());
-  EXPECT_VECTOR2DF_EQ(
-      gfx::Vector2dF(0.125f, 0.125f),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR2DF_EQ(
-      gfx::Vector2dF(0.25f, 0.25f),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f),
+                      outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.25f, 0.25f),
+                      inner_scroll_layer->CurrentScrollOffset());
   host_impl_->ScrollEnd(EndState().get());
 }
 
@@ -1800,44 +1792,37 @@
   inner_scroll_layer->SetDrawsContent(true);
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(500, 500),
-      outer_scroll_layer->MaxScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500),
+                   outer_scroll_layer->MaxScrollOffset());
 
   host_impl_->ScrollBegin(BeginState(gfx::Point(250, 250)).get(),
                           InputHandler::TOUCHSCREEN);
   host_impl_->PinchGestureBegin();
 
   host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(0, 0),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(125, 125),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
+                   outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(125, 125),
+                   inner_scroll_layer->CurrentScrollOffset());
 
   // Needed so that the pinch is accounted for in draw properties.
   DrawFrame();
 
   host_impl_->ScrollBy(
       UpdateState(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f)).get());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(0, 0),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(130, 130),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
+                   outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(130, 130),
+                   inner_scroll_layer->CurrentScrollOffset());
 
   DrawFrame();
 
   host_impl_->ScrollBy(
       UpdateState(gfx::Point(250, 250), gfx::Vector2dF(400.f, 400.f)).get());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(80, 80),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(250, 250),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(80, 80),
+                   outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250),
+                   inner_scroll_layer->CurrentScrollOffset());
 
   host_impl_->PinchGestureEnd();
   host_impl_->ScrollEnd(EndState().get());
@@ -1950,12 +1935,9 @@
       UpdateState(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f)).get());
   host_impl_->ScrollEnd(EndState().get());
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(5, 10),
-      inner_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(),
-      outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10),
+                   inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(), outer_scroll_layer->CurrentScrollOffset());
 
   // Scroll by the inner viewport's max scroll extent, the remainder
   // should bubble up to the outer viewport.
@@ -1965,12 +1947,10 @@
       UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f)).get());
   host_impl_->ScrollEnd(EndState().get());
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(50, 50),
-      inner_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(5, 10),
-      outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
+                   inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10),
+                   outer_scroll_layer->CurrentScrollOffset());
 
   // Scroll by the outer viewport's max scroll extent, it should all go to the
   // outer viewport.
@@ -1980,12 +1960,10 @@
       UpdateState(gfx::Point(0, 0), gfx::Vector2dF(190.f, 180.f)).get());
   host_impl_->ScrollEnd(EndState().get());
 
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(100, 100),
-      outer_scroll_layer->CurrentScrollOffset());
-  EXPECT_VECTOR_EQ(
-      gfx::Vector2dF(50, 50),
-      inner_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100),
+                   outer_scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
+                   inner_scroll_layer->CurrentScrollOffset());
 }
 
 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
@@ -2021,9 +1999,9 @@
 
   // Set up two scrolling children of the root, one of which is a scroll parent
   // to the other. Scrolls shouldn't bubbling from the child.
-  LayerImpl *parent;
-  LayerImpl *child;
-  LayerImpl *child_clip;
+  LayerImpl* parent;
+  LayerImpl* child;
+  LayerImpl* child_clip;
 
   std::unique_ptr<LayerImpl> scroll_parent_clip =
       LayerImpl::Create(host_impl_->active_tree(), 6);
@@ -2104,7 +2082,6 @@
   }
 }
 
-
 TEST_F(LayerTreeHostImplTest, PinchGesture) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->SetViewportSize(gfx::Size(50, 50));
@@ -2336,14 +2313,14 @@
 
   float min_page_scale = 0.5f;
   float max_page_scale = 4.f;
-  base::TimeTicks start_time = base::TimeTicks() +
-                               base::TimeDelta::FromSeconds(1);
+  base::TimeTicks start_time =
+      base::TimeTicks() + base::TimeDelta::FromSeconds(1);
   base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
   base::TimeTicks halfway_through_animation = start_time + duration / 2;
   base::TimeTicks end_time = start_time + duration;
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Non-anchor zoom-in
   {
@@ -2367,6 +2344,7 @@
     did_request_redraw_ = false;
     did_request_next_frame_ = false;
     begin_frame_args.frame_time = start_time;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_redraw_);
@@ -2376,6 +2354,7 @@
     did_request_redraw_ = false;
     did_request_next_frame_ = false;
     begin_frame_args.frame_time = halfway_through_animation;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_redraw_);
@@ -2386,6 +2365,7 @@
     did_request_next_frame_ = false;
     did_request_commit_ = false;
     begin_frame_args.frame_time = end_time;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_commit_);
@@ -2425,6 +2405,7 @@
     did_request_redraw_ = false;
     did_request_next_frame_ = false;
     begin_frame_args.frame_time = start_time;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_redraw_);
@@ -2435,6 +2416,7 @@
     did_request_commit_ = false;
     did_request_next_frame_ = false;
     begin_frame_args.frame_time = end_time;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_redraw_);
@@ -2461,14 +2443,14 @@
 
   float min_page_scale = 0.5f;
   float max_page_scale = 4.f;
-  base::TimeTicks start_time = base::TimeTicks() +
-                               base::TimeDelta::FromSeconds(1);
+  base::TimeTicks start_time =
+      base::TimeTicks() + base::TimeDelta::FromSeconds(1);
   base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
   base::TimeTicks halfway_through_animation = start_time + duration / 2;
   base::TimeTicks end_time = start_time + duration;
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Anchor zoom with unchanged page scale should not change scroll or scale.
   {
@@ -2485,17 +2467,20 @@
                                           duration)));
     host_impl_->ActivateSyncTree();
     begin_frame_args.frame_time = start_time;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     host_impl_->DidFinishImplFrame();
 
     begin_frame_args.frame_time = halfway_through_animation;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_redraw_);
     host_impl_->DidFinishImplFrame();
 
     begin_frame_args.frame_time = end_time;
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_TRUE(did_request_commit_);
@@ -2511,9 +2496,8 @@
 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
   host_impl_->CreatePendingTree();
   host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
-  CreateScrollAndContentsLayers(
-      host_impl_->pending_tree(),
-      gfx::Size(100, 100));
+  CreateScrollAndContentsLayers(host_impl_->pending_tree(),
+                                gfx::Size(100, 100));
   host_impl_->pending_tree()->BuildPropertyTreesForTesting();
   host_impl_->ActivateSyncTree();
   DrawFrame();
@@ -2527,8 +2511,8 @@
                                                        max_page_scale);
   host_impl_->ActivateSyncTree();
 
-  base::TimeTicks start_time = base::TimeTicks() +
-                               base::TimeDelta::FromSeconds(1);
+  base::TimeTicks start_time =
+      base::TimeTicks() + base::TimeDelta::FromSeconds(1);
   base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
   base::TimeTicks third_through_animation = start_time + duration / 3;
   base::TimeTicks halfway_through_animation = start_time + duration / 2;
@@ -2536,7 +2520,7 @@
   float target_scale = 2.f;
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   scroll_layer->layer_tree_impl()
       ->property_trees()
@@ -2562,6 +2546,7 @@
       std::unique_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
           gfx::Vector2d(), false, target_scale, duration)));
   begin_frame_args.frame_time = halfway_through_animation;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_FALSE(did_request_next_frame_);
@@ -2572,7 +2557,7 @@
   // It should also clear the pointer on the sync tree.
   host_impl_->ActivateSyncTree();
   EXPECT_EQ(nullptr,
-      host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
+            host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
   EXPECT_FALSE(did_request_redraw_);
   EXPECT_TRUE(did_request_next_frame_);
 
@@ -2585,6 +2570,7 @@
   did_request_redraw_ = false;
   did_request_next_frame_ = false;
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_TRUE(did_request_redraw_);
@@ -2594,6 +2580,7 @@
   did_request_redraw_ = false;
   did_request_next_frame_ = false;
   begin_frame_args.frame_time = third_through_animation;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_TRUE(did_request_redraw_);
@@ -2606,6 +2593,7 @@
   did_request_redraw_ = false;
   did_request_next_frame_ = false;
   begin_frame_args.frame_time = halfway_through_animation;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_TRUE(did_request_redraw_);
@@ -2616,6 +2604,7 @@
   did_request_next_frame_ = false;
   did_request_commit_ = false;
   begin_frame_args.frame_time = end_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_TRUE(did_request_commit_);
@@ -2644,7 +2633,7 @@
   base::TimeTicks end_time = start_time + duration;
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
   scroll_layer->layer_tree_impl()
@@ -2658,18 +2647,21 @@
           gfx::Vector2d(), false, 2.f, duration)));
   host_impl_->ActivateSyncTree();
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_FALSE(did_complete_page_scale_animation_);
   host_impl_->DidFinishImplFrame();
 
   begin_frame_args.frame_time = halfway_through_animation;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_FALSE(did_complete_page_scale_animation_);
   host_impl_->DidFinishImplFrame();
 
   begin_frame_args.frame_time = end_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_TRUE(did_complete_page_scale_animation_);
@@ -2720,7 +2712,7 @@
                           0) {}
 
   BeginFrameArgs CurrentBeginFrameArgs() const override {
-    return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
+    return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
                                           fake_current_physical_time_);
   }
 
@@ -2807,7 +2799,7 @@
 
     // Before the scrollbar animation exists, we should not get redraws.
     BeginFrameArgs begin_frame_args =
-        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
+        CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, fake_now);
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_FALSE(did_request_next_frame_);
@@ -2844,7 +2836,7 @@
     if (expecting_animations) {
       // Before the scrollbar animation begins, we should not get redraws.
       begin_frame_args =
-          CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
+          CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 3, fake_now);
       host_impl_->WillBeginImplFrame(begin_frame_args);
       host_impl_->Animate();
       EXPECT_FALSE(did_request_next_frame_);
@@ -2864,7 +2856,7 @@
 
       // After the scrollbar animation begins, we should start getting redraws.
       begin_frame_args =
-          CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
+          CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 4, fake_now);
       host_impl_->WillBeginImplFrame(begin_frame_args);
       host_impl_->Animate();
       EXPECT_TRUE(did_request_next_frame_);
@@ -2902,7 +2894,7 @@
       // Scrolling should have stopped the animation, so we should not be
       // getting redraws.
       begin_frame_args =
-          CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
+          CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 5, fake_now);
       host_impl_->WillBeginImplFrame(begin_frame_args);
       host_impl_->Animate();
       EXPECT_FALSE(did_request_next_frame_);
@@ -3306,10 +3298,11 @@
   }
 
   // Scrolling should update metadata immediately.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
   {
     CompositorFrameMetadata metadata =
@@ -4591,8 +4584,7 @@
   host_impl_->ScrollEnd(EndState().get());
 
   // The viewport offset shouldn't have changed.
-  EXPECT_EQ(viewport_offset,
-            host_impl_->active_tree()->TotalScrollOffset());
+  EXPECT_EQ(viewport_offset, host_impl_->active_tree()->TotalScrollOffset());
 
   // Scroll the viewports to max scroll offset.
   SetScrollOffsetDelta(outer_scroll, gfx::Vector2dF(0, 200.f));
@@ -4629,9 +4621,9 @@
   // Browser controls were hidden by 25px so the inner viewport should have
   // expanded by that much.
   LayerImpl* outer_container =
-            host_impl_->active_tree()->OuterViewportContainerLayer();
+      host_impl_->active_tree()->OuterViewportContainerLayer();
   LayerImpl* inner_container =
-            host_impl_->active_tree()->InnerViewportContainerLayer();
+      host_impl_->active_tree()->InnerViewportContainerLayer();
   EXPECT_EQ(gfx::SizeF(100.f, 100.f + 25.f),
             inner_container->BoundsForScrolling());
 
@@ -4826,12 +4818,13 @@
       BOTH, SHOWN, true);
   base::TimeTicks start_time = base::TimeTicks::Now();
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Pump an animation frame to put some delta in the browser controls.
   {
     begin_frame_args.frame_time =
         start_time + base::TimeDelta::FromMilliseconds(50);
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     host_impl_->UpdateAnimationState(true);
@@ -4858,6 +4851,7 @@
   {
     begin_frame_args.frame_time =
         start_time + base::TimeDelta::FromMilliseconds(200);
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     host_impl_->UpdateAnimationState(true);
@@ -4914,10 +4908,11 @@
   host_impl_->SetViewportSize(surface_size);
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
   host_impl_->ScrollEnd(EndState().get());
   EXPECT_TRUE(did_request_redraw_);
@@ -4939,10 +4934,11 @@
   host_impl_->SetViewportSize(surface_size);
   DrawFrame();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
   host_impl_->ScrollEnd(EndState().get());
   EXPECT_TRUE(did_request_redraw_);
@@ -5064,10 +5060,11 @@
   gfx::Vector2d scroll_delta(0, 10);
   gfx::Vector2d expected_scroll_delta = scroll_delta;
   gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
   host_impl_->ScrollEnd(EndState().get());
 
@@ -5114,10 +5111,11 @@
   gfx::Vector2d scroll_delta(0, 10);
   gfx::Vector2d expected_scroll_delta = scroll_delta;
   gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
   host_impl_->ScrollEnd(EndState().get());
 
@@ -5216,10 +5214,11 @@
   gfx::Vector2d scroll_delta(0, 10);
   gfx::Vector2d expected_scroll_delta(scroll_delta);
   gfx::ScrollOffset expected_max_scroll(outer_scroll->MaxScrollOffset());
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
   host_impl_->ScrollEnd(EndState().get());
 
@@ -5279,10 +5278,11 @@
   DrawFrame();
   {
     gfx::Vector2d scroll_delta(-8, -7);
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                      InputHandler::WHEEL)
-                  .thread);
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+            .thread);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
     host_impl_->ScrollEnd(EndState().get());
 
@@ -5350,8 +5350,9 @@
   {
     gfx::Vector2d scroll_delta(0, -10);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point()).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
     host_impl_->ScrollEnd(EndState().get());
@@ -5378,8 +5379,9 @@
     // The next time we scroll we should only scroll the parent.
     scroll_delta = gfx::Vector2d(0, -3);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
@@ -5400,8 +5402,9 @@
     // should still scroll the child.
     scroll_delta = gfx::Vector2d(0, 7);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
@@ -5424,8 +5427,9 @@
 
     scroll_delta = gfx::Vector2d(0, -2);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(1, 1)).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(1, 1)).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
@@ -5473,8 +5477,9 @@
   {
     gfx::Vector2d scroll_delta(0, 4);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::WHEEL)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::WHEEL)
                   .thread);
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
     host_impl_->ScrollEnd(EndState().get());
@@ -5549,10 +5554,11 @@
   host_impl_->active_tree()->DidBecomeActive();
 
   // Scrolling should still work even though we did not draw yet.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), InputHandler::WHEEL)
+          .thread);
 }
 
 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
@@ -5591,10 +5597,11 @@
   // Reset and scroll down with the wheel.
   SetScrollOffsetDelta(scroll_layer, gfx::Vector2dF());
   gfx::Vector2d wheel_scroll_delta(0, 10);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), wheel_scroll_delta).get());
   host_impl_->ScrollEnd(EndState().get());
 
@@ -5769,8 +5776,7 @@
 }
 
 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
-  LayerImpl* scroll_layer =
-      SetupScrollAndContentsLayers(gfx::Size(100, 100));
+  LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
 
   // Scale the layer to twice its normal size.
   int scale = 2;
@@ -5804,10 +5810,11 @@
   // Reset and scroll down with the wheel.
   SetScrollOffsetDelta(scroll_layer, gfx::Vector2dF());
   gfx::Vector2d wheel_scroll_delta(0, 10);
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   host_impl_->ScrollBy(UpdateState(gfx::Point(), wheel_scroll_delta).get());
   host_impl_->ScrollEnd(EndState().get());
 
@@ -5866,29 +5873,17 @@
   }
   void DeliverInputForBeginFrame() override {}
 
-  gfx::ScrollOffset last_set_scroll_offset() {
-    return last_set_scroll_offset_;
-  }
+  gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; }
 
-  gfx::ScrollOffset max_scroll_offset() const {
-    return max_scroll_offset_;
-  }
+  gfx::ScrollOffset max_scroll_offset() const { return max_scroll_offset_; }
 
-  gfx::SizeF scrollable_size() const {
-    return scrollable_size_;
-  }
+  gfx::SizeF scrollable_size() const { return scrollable_size_; }
 
-  float page_scale_factor() const {
-    return page_scale_factor_;
-  }
+  float page_scale_factor() const { return page_scale_factor_; }
 
-  float min_page_scale_factor() const {
-    return min_page_scale_factor_;
-  }
+  float min_page_scale_factor() const { return min_page_scale_factor_; }
 
-  float max_page_scale_factor() const {
-    return max_page_scale_factor_;
-  }
+  float max_page_scale_factor() const { return max_page_scale_factor_; }
 
  private:
   gfx::ScrollOffset last_set_scroll_offset_;
@@ -6050,10 +6045,11 @@
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
 
   // In-bounds scrolling does not affect overscroll.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   scroll_result = host_impl_->ScrollBy(
       UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
   EXPECT_TRUE(scroll_result.did_scroll);
@@ -6212,8 +6208,9 @@
   {
     gfx::Vector2d scroll_delta(0, -10);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point()).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     scroll_result =
         host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
@@ -6226,8 +6223,9 @@
     // should still not reach the root layer.
     scroll_delta = gfx::Vector2d(0, -30);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
@@ -6249,8 +6247,9 @@
     // should scroll the child.
     scroll_delta = gfx::Vector2d(0, 70);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
     scroll_result =
@@ -6275,8 +6274,9 @@
   {
     gfx::Vector2d scroll_delta(0, 8);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
-                                      InputHandler::WHEEL)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(),
+                                InputHandler::WHEEL)
                   .thread);
     scroll_result =
         host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
@@ -6315,10 +6315,11 @@
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
 
   // Even though the layer can't scroll the overscroll still happens.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   scroll_result = host_impl_->ScrollBy(
       UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get());
   EXPECT_FALSE(scroll_result.did_scroll);
@@ -6343,8 +6344,9 @@
     // of the content. unnecessary glow effect calls shouldn't be
     // called while scrolling up without reaching the edge of the content.
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
-                                      InputHandler::WHEEL)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
+                                InputHandler::WHEEL)
                   .thread);
     scroll_result = host_impl_->ScrollBy(
         UpdateState(gfx::Point(), gfx::Vector2dF(0, 100)).get());
@@ -6362,8 +6364,9 @@
     // unusedrootDelta should be subtracted from applied delta so that
     // unwanted glow effect calls are not called.
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
-                                      InputHandler::NON_BUBBLING_GESTURE)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
+                                InputHandler::NON_BUBBLING_GESTURE)
                   .thread);
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_->FlingScrollBegin().thread);
@@ -6384,8 +6387,9 @@
     // TestCase to check  kEpsilon, which prevents minute values to trigger
     // gloweffect without reaching edge.
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
-                                      InputHandler::WHEEL)
+              host_impl_
+                  ->ScrollBegin(BeginState(gfx::Point(0, 0)).get(),
+                                InputHandler::WHEEL)
                   .thread);
     scroll_result = host_impl_->ScrollBy(
         UpdateState(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f)).get());
@@ -6898,15 +6902,10 @@
 
     TileDrawQuad* test_blending_draw_quad =
         render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
-    test_blending_draw_quad->SetNew(shared_quad_state,
-                                    quad_rect_,
-                                    opaque_rect,
-                                    visible_quad_rect,
-                                    resource_id_,
+    test_blending_draw_quad->SetNew(shared_quad_state, quad_rect_, opaque_rect,
+                                    visible_quad_rect, resource_id_,
                                     gfx::RectF(0.f, 0.f, 1.f, 1.f),
-                                    gfx::Size(1, 1),
-                                    false,
-                                    false);
+                                    gfx::Size(1, 1), false, false);
     test_blending_draw_quad->visible_rect = quad_visible_rect_;
     EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
     EXPECT_EQ(has_render_surface_, !!render_surface());
@@ -7254,10 +7253,10 @@
 
 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
  protected:
-  LayerTreeHostImplViewportCoveredTest() :
-      gutter_quad_material_(DrawQuad::SOLID_COLOR),
-      child_(NULL),
-      did_activate_pending_tree_(false) {}
+  LayerTreeHostImplViewportCoveredTest()
+      : gutter_quad_material_(DrawQuad::SOLID_COLOR),
+        child_(NULL),
+        did_activate_pending_tree_(false) {}
 
   std::unique_ptr<CompositorFrameSink> CreateFakeCompositorFrameSink(
       bool software) {
@@ -7548,11 +7547,12 @@
   EXPECT_SCOPED(TestLayerIsLargerThanViewportWithOnDraw());
 }
 
-class FakeDrawableLayerImpl: public LayerImpl {
+class FakeDrawableLayerImpl : public LayerImpl {
  public:
   static std::unique_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
     return base::WrapUnique(new FakeDrawableLayerImpl(tree_impl, id));
   }
+
  protected:
   FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
       : LayerImpl(tree_impl, id) {}
@@ -7583,7 +7583,7 @@
   layer_tree_host_impl->SetVisible(true);
   layer_tree_host_impl->InitializeRenderer(compositor_frame_sink.get());
   layer_tree_host_impl->WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2));
   layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
 
   std::unique_ptr<LayerImpl> root =
@@ -7687,8 +7687,8 @@
     gfx::Rect visible_quad_rect(quad_rect);
     SolidColorDrawQuad* my_quad =
         render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
-    my_quad->SetNew(
-        shared_quad_state, quad_rect, visible_quad_rect, gray, false);
+    my_quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, gray,
+                    false);
   }
 
  private:
@@ -7712,7 +7712,7 @@
   my_host_impl->SetVisible(true);
   my_host_impl->InitializeRenderer(compositor_frame_sink);
   my_host_impl->WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2));
   my_host_impl->SetViewportSize(gfx::Size(100, 100));
 
   /*
@@ -7841,9 +7841,8 @@
   root_layer->SetBounds(gfx::Size(10, 10));
   root_layer->test_properties()->force_render_surface = true;
 
-  scoped_refptr<VideoFrame> softwareFrame =
-      media::VideoFrame::CreateColorFrame(
-          gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
+  scoped_refptr<VideoFrame> softwareFrame = media::VideoFrame::CreateColorFrame(
+      gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
   FakeVideoFrameProvider provider;
   provider.set_frame(softwareFrame);
   std::unique_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
@@ -7873,10 +7872,8 @@
 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
  public:
   MOCK_METHOD1(useProgram, void(GLuint program));
-  MOCK_METHOD4(drawElements, void(GLenum mode,
-                                  GLsizei count,
-                                  GLenum type,
-                                  GLintptr offset));
+  MOCK_METHOD4(drawElements,
+               void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
 };
 
 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
@@ -8612,10 +8609,11 @@
   host_impl_->SetViewportSize(surface_size);
   DrawFrame();
   {
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                      InputHandler::WHEEL)
-                  .thread);
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+            .thread);
 
     EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
               host_impl_->FlingScrollBegin().thread);
@@ -8735,10 +8733,11 @@
 
   // We should have scrolled |child_scroll| even though it does not move
   // any layer that is a drawn RSLL member.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
 
   EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
 }
@@ -8761,8 +8760,8 @@
           host_impl_->compositor_frame_sink());
 
   ui::LatencyInfo latency_info;
-  latency_info.AddLatencyNumber(
-      ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
+  latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
+                                0);
   std::unique_ptr<SwapPromise> swap_promise(
       new LatencyInfoSwapPromise(latency_info));
   host_impl_->active_tree()->QueuePinnedSwapPromise(std::move(swap_promise));
@@ -8925,8 +8924,8 @@
                                 InputHandler::TOUCHSCREEN)
                   .thread);
     EXPECT_TRUE(
-        host_impl_->ScrollBy(
-                      UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
+        host_impl_
+            ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
             .did_scroll);
     host_impl_->ScrollEnd(EndState().get());
 
@@ -8943,8 +8942,8 @@
                                 InputHandler::TOUCHSCREEN)
                   .thread);
     EXPECT_TRUE(
-        host_impl_->ScrollBy(
-                      UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
+        host_impl_
+            ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get())
             .did_scroll);
     host_impl_->ScrollEnd(EndState().get());
 
@@ -8977,7 +8976,7 @@
       ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->id(),
                                                      gfx::ScrollOffset(0, 10));
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2);
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   EXPECT_FALSE(did_request_redraw_);
@@ -9110,10 +9109,11 @@
 
   LayerImpl* viewport_layer = host_impl_->InnerViewportScrollLayer();
 
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+          .thread);
   EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer->CurrentScrollOffset());
 
@@ -9121,8 +9121,8 @@
   // directly through to the viewport.
   const float delta = top_controls_height_;
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, delta)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, delta)).get())
           .did_scroll);
   EXPECT_FLOAT_EQ(0,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -9130,8 +9130,8 @@
                    viewport_layer->CurrentScrollOffset());
 
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, delta)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, delta)).get())
           .did_scroll);
   EXPECT_FLOAT_EQ(0,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -9162,8 +9162,8 @@
   const float residue = 35;
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
           .did_scroll);
   EXPECT_FLOAT_EQ(-offset,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -9184,7 +9184,7 @@
   // The browser controls should properly animate until finished, despite the
   // scroll offset being at the origin.
   BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
+      BEGINFRAME_FROM_HERE, 0, 1, base::TimeTicks::Now());
   while (did_request_next_frame_) {
     did_request_redraw_ = false;
     did_request_next_frame_ = false;
@@ -9194,6 +9194,7 @@
         host_impl_->browser_controls_manager()->ControlsTopOffset();
 
     begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
     EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -9246,8 +9247,8 @@
   const float residue = 15;
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
           .did_scroll);
   EXPECT_FLOAT_EQ(-offset,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -9267,7 +9268,7 @@
 
   // Animate the browser controls to the limit.
   BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
+      BEGINFRAME_FROM_HERE, 0, 1, base::TimeTicks::Now());
   while (did_request_next_frame_) {
     did_request_redraw_ = false;
     did_request_next_frame_ = false;
@@ -9277,6 +9278,7 @@
         host_impl_->browser_controls_manager()->ControlsTopOffset();
 
     begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
 
@@ -9322,8 +9324,8 @@
   const float residue = 15;
   float offset = top_controls_height_ - residue;
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
           .did_scroll);
   EXPECT_FLOAT_EQ(-offset,
                   host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -9343,7 +9345,7 @@
 
   // Animate the browser controls to the limit.
   BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
+      BEGINFRAME_FROM_HERE, 0, 1, base::TimeTicks::Now());
   while (did_request_next_frame_) {
     did_request_redraw_ = false;
     did_request_next_frame_ = false;
@@ -9353,6 +9355,7 @@
         host_impl_->browser_controls_manager()->ControlsTopOffset();
 
     begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
+    begin_frame_args.sequence_number++;
     host_impl_->WillBeginImplFrame(begin_frame_args);
     host_impl_->Animate();
 
@@ -9391,8 +9394,8 @@
 
   float offset = 50;
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
           .did_scroll);
   EXPECT_EQ(-offset,
             host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -9400,15 +9403,15 @@
             scroll_layer->CurrentScrollOffset().ToString());
 
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
           .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
 
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, offset)).get())
           .did_scroll);
 
   // Should have fully scrolled
@@ -9418,28 +9421,29 @@
   float overscrollamount = 10;
 
   // Overscroll the content
-  EXPECT_FALSE(
-      host_impl_->ScrollBy(UpdateState(gfx::Point(),
-                                       gfx::Vector2d(0, overscrollamount))
-                               .get())
-          .did_scroll);
+  EXPECT_FALSE(host_impl_
+                   ->ScrollBy(UpdateState(gfx::Point(),
+                                          gfx::Vector2d(0, overscrollamount))
+                                  .get())
+                   .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
   EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
             host_impl_->accumulated_root_overscroll().ToString());
 
-  EXPECT_TRUE(host_impl_->ScrollBy(UpdateState(gfx::Point(),
-                                               gfx::Vector2d(0, -2 * offset))
-                                       .get())
-                  .did_scroll);
+  EXPECT_TRUE(
+      host_impl_
+          ->ScrollBy(
+              UpdateState(gfx::Point(), gfx::Vector2d(0, -2 * offset)).get())
+          .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
   EXPECT_EQ(-offset,
             host_impl_->browser_controls_manager()->ControlsTopOffset());
 
   EXPECT_TRUE(
-      host_impl_->ScrollBy(
-                    UpdateState(gfx::Point(), gfx::Vector2d(0, -offset)).get())
+      host_impl_
+          ->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, -offset)).get())
           .did_scroll);
   EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
             scroll_layer->CurrentScrollOffset().ToString());
@@ -10290,7 +10294,7 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   EXPECT_EQ(
       InputHandler::SCROLL_ON_IMPL_THREAD,
@@ -10300,6 +10304,7 @@
   EXPECT_EQ(host_impl_->OuterViewportScrollLayer(), scrolling_layer);
 
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10309,6 +10314,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(50);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10324,6 +10330,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(200);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10335,6 +10342,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(250);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10371,8 +10379,9 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(200);
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
   host_impl_->DidFinishImplFrame();
@@ -10389,6 +10398,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(250);
+  begin_frame_args.sequence_number++;
   // This is when the animation above gets promoted to STARTING.
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
@@ -10396,6 +10406,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(300);
+  begin_frame_args.sequence_number++;
   // This is when the animation above gets ticked.
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
@@ -10419,7 +10430,7 @@
   base::TimeTicks start_time =
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Create animation with a 100ms delay.
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
@@ -10432,6 +10443,7 @@
 
   // First tick, animation is started.
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
@@ -10441,6 +10453,7 @@
   // the duration due to delay is 100ms.
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(50);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(50, scrolling_layer->CurrentScrollOffset().y());
@@ -10457,6 +10470,7 @@
   // target was called with a large value of jank.
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(100);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->UpdateAnimationState(true);
   EXPECT_LT(100, scrolling_layer->CurrentScrollOffset().y());
@@ -10475,7 +10489,7 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Perform animated scroll.
   EXPECT_EQ(
@@ -10485,6 +10499,7 @@
   LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
 
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10497,6 +10512,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(50);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10505,10 +10521,11 @@
   EXPECT_TRUE(y > 1 && y < 49);
 
   // Perform instant scroll.
-  EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-            host_impl_->ScrollBegin(BeginState(gfx::Point(0, y)).get(),
-                                    InputHandler::WHEEL)
-                .thread);
+  EXPECT_EQ(
+      InputHandler::SCROLL_ON_IMPL_THREAD,
+      host_impl_
+          ->ScrollBegin(BeginState(gfx::Point(0, y)).get(), InputHandler::WHEEL)
+          .thread);
   EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y),
                                                       InputHandler::WHEEL));
   host_impl_->ScrollBy(
@@ -10546,7 +10563,7 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   // Perform animated scroll.
   EXPECT_EQ(
@@ -10556,6 +10573,7 @@
   LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
 
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10568,6 +10586,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(50);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10600,7 +10619,7 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   EXPECT_EQ(
       InputHandler::SCROLL_ON_IMPL_THREAD,
@@ -10608,6 +10627,7 @@
 
   LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10617,6 +10637,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(50);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10632,6 +10653,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(200);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10643,6 +10665,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(250);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10676,7 +10699,7 @@
   base::TimeTicks start_time =
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(250);
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
   EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
             host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(10.f, 20.f))
                 .thread);
@@ -10684,6 +10707,7 @@
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(inner_scroll_layer, host_impl_->CurrentlyScrollingLayer());
 
+  begin_frame_args.sequence_number++;
   BeginImplFrameAndAnimate(begin_frame_args, start_time);
   EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10),
                    inner_scroll_layer->CurrentScrollOffset());
@@ -10701,6 +10725,7 @@
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(inner_scroll_layer, host_impl_->CurrentlyScrollingLayer());
 
+  begin_frame_args.sequence_number++;
   BeginImplFrameAndAnimate(begin_frame_args,
                            start_time + base::TimeDelta::FromMilliseconds(350));
   EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
@@ -10718,6 +10743,7 @@
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(outer_scroll_layer, host_impl_->CurrentlyScrollingLayer());
 
+  begin_frame_args.sequence_number++;
   BeginImplFrameAndAnimate(begin_frame_args,
                            start_time + base::TimeDelta::FromMilliseconds(850));
   EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
@@ -10735,6 +10761,7 @@
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(inner_scroll_layer, host_impl_->CurrentlyScrollingLayer());
 
+  begin_frame_args.sequence_number++;
   BeginImplFrameAndAnimate(
       begin_frame_args, start_time + base::TimeDelta::FromMilliseconds(1200));
   EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
@@ -10764,7 +10791,7 @@
   base::TimeTicks start_time =
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(50);
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
   EXPECT_EQ(
       InputHandler::SCROLL_ON_IMPL_THREAD,
       host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(90, 90)).thread);
@@ -10772,6 +10799,7 @@
   host_impl_->UpdateAnimationState(true);
   EXPECT_EQ(inner_scroll_layer, host_impl_->CurrentlyScrollingLayer());
 
+  begin_frame_args.sequence_number++;
   BeginImplFrameAndAnimate(begin_frame_args, start_time);
   float inner_x = inner_scroll_layer->CurrentScrollOffset().x();
   float inner_y = inner_scroll_layer->CurrentScrollOffset().y();
@@ -10790,6 +10818,7 @@
 
   // Verify that all the delta is applied to the inner viewport and nothing is
   // carried forward.
+  begin_frame_args.sequence_number++;
   BeginImplFrameAndAnimate(begin_frame_args,
                            start_time + base::TimeDelta::FromMilliseconds(350));
   EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50),
@@ -10816,7 +10845,7 @@
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
 
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   EXPECT_EQ(
       InputHandler::SCROLL_ON_IMPL_THREAD,
@@ -10824,6 +10853,7 @@
 
   LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10833,6 +10863,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(50);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10850,6 +10881,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(200);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10861,6 +10893,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(250);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10885,12 +10918,13 @@
   base::TimeTicks start_time =
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
 
   host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(500, 500));
   LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
 
   begin_frame_args.frame_time = start_time;
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -10904,6 +10938,7 @@
 
   begin_frame_args.frame_time =
       start_time + base::TimeDelta::FromMilliseconds(200);
+  begin_frame_args.sequence_number++;
   host_impl_->WillBeginImplFrame(begin_frame_args);
   host_impl_->Animate();
   host_impl_->UpdateAnimationState(true);
@@ -11016,10 +11051,11 @@
     host_impl_->ScrollEnd(EndState().get());
 
     gfx::Vector2dF scroll_delta(0, 5);
-    EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
-              host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
-                                      InputHandler::WHEEL)
-                  .thread);
+    EXPECT_EQ(
+        InputHandler::SCROLL_ON_IMPL_THREAD,
+        host_impl_
+            ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL)
+            .thread);
     EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
 
     host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get());
@@ -11193,7 +11229,7 @@
 
 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2);
   FakeVideoFrameController controller;
 
   host_impl_->WillBeginImplFrame(begin_frame_args);
@@ -11216,7 +11252,7 @@
 
 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
   BeginFrameArgs begin_frame_args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2);
   FakeVideoFrameController controller;
 
   host_impl_->WillBeginImplFrame(begin_frame_args);
@@ -11226,7 +11262,7 @@
   host_impl_->AddVideoFrameController(&controller);
   EXPECT_FALSE(controller.begin_frame_args().IsValid());
 
-  begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
+  begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 3);
   EXPECT_FALSE(controller.begin_frame_args().IsValid());
   host_impl_->WillBeginImplFrame(begin_frame_args);
   EXPECT_TRUE(controller.begin_frame_args().IsValid());
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 593a7dc0..f30413a 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -450,7 +450,7 @@
   }
 
   BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(),
+      BEGINFRAME_FROM_HERE, 0, 1, frame_begin_time, base::TimeTicks(),
       BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL));
 
   // Start the impl frame.
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index cc1d268..17cc03d 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1518,8 +1518,9 @@
 }
 
 void RenderWidgetHostViewAndroid::SendBeginFrame(cc::BeginFrameArgs args) {
-  TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
-               "frame_time_us", args.frame_time.ToInternalValue());
+  TRACE_EVENT2("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
+               "frame_number", args.sequence_number, "frame_time_us",
+               args.frame_time.ToInternalValue());
 
   // Synchronous compositor does not use deadline-based scheduling.
   // TODO(brianderson): Replace this hardcoded deadline after Android
diff --git a/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc b/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc
index 97f67a36..d990a60 100644
--- a/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc
+++ b/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc
@@ -45,7 +45,7 @@
   int route_id = 0;
 
   ViewMsg_BeginFrame msg(
-      route_id, cc::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
+      route_id, cc::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1));
 
   CompositorForwardingMessageFilter::Handler plus_handler =
       base::Bind(&CompositorForwardingMessageFilterTestHandler::OnPlusMethod,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index fda7d476..30442f5 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -105,11 +105,13 @@
 }
 
 void WillBeginFrameIdleTask(RendererScheduler* scheduler,
+                            uint64_t sequence_number,
                             base::SimpleTestTickClock* clock,
                             base::TimeTicks deadline) {
   scheduler->WillBeginFrame(cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
+      BEGINFRAME_FROM_HERE, 0, sequence_number, clock->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL));
 }
 
 void UpdateClockToDeadlineIdleTestTask(base::SimpleTestTickClock* clock,
@@ -314,8 +316,9 @@
 
   void DoMainFrame() {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = false;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidCommitFrameToCompositor();
@@ -323,8 +326,9 @@
 
   void DoMainFrameOnCriticalPath() {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
   }
@@ -667,6 +671,7 @@
   scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
   bool simulate_timer_task_ran_;
   bool simulate_compositor_task_ran_;
+  uint64_t next_begin_frame_number_ = cc::BeginFrameArgs::kStartingFrameNumber;
 
   DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest);
 };
@@ -715,8 +720,9 @@
   EXPECT_EQ(0, run_count);  // Shouldn't run yet as no WillBeginFrame.
 
   scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL));
   RunUntilIdle();
   EXPECT_EQ(0, run_count);  // Shouldn't run as no DidCommitFrameToCompositor.
 
@@ -726,8 +732,9 @@
   EXPECT_EQ(0, run_count);  // We missed the deadline.
 
   scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL));
   clock_->Advance(base::TimeDelta::FromMilliseconds(800));
   scheduler_->DidCommitFrameToCompositor();
   RunUntilIdle();
@@ -787,16 +794,18 @@
 
   // Trigger the beginning of an idle period for 1000ms.
   scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL));
   DoMainFrame();
 
   // End the idle period early (after 500ms), and send a WillBeginFrame which
   // specifies that the next idle period should end 1000ms from now.
   clock_->Advance(base::TimeDelta::FromMilliseconds(500));
   scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL));
 
   RunUntilIdle();
   EXPECT_EQ(0, run_count);  // Not currently in an idle period.
@@ -2079,8 +2088,9 @@
                  base::RetainedRef(idle_task_runner_), &run_count, clock_.get(),
                  idle_task_runtime, &actual_deadlines));
   idle_task_runner_->PostIdleTask(
-      FROM_HERE, base::Bind(&WillBeginFrameIdleTask,
-                            base::Unretained(scheduler_.get()), clock_.get()));
+      FROM_HERE,
+      base::Bind(&WillBeginFrameIdleTask, base::Unretained(scheduler_.get()),
+                 next_begin_frame_number_++, clock_.get()));
   RunUntilIdle();
   EXPECT_EQ(4, run_count);
 }
@@ -2159,8 +2169,9 @@
   // Next long idle period will be for the maximum time, so
   // CanExceedIdleDeadlineIfRequired should return true.
   scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL));
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL));
   EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired());
 }
 
@@ -2371,8 +2382,9 @@
   ASSERT_FALSE(scheduler_->BeginMainFrameOnCriticalPath());
 
   cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
+      cc::BeginFrameArgs::NORMAL);
   scheduler_->WillBeginFrame(begin_frame_args);
   ASSERT_TRUE(scheduler_->BeginMainFrameOnCriticalPath());
 
@@ -2748,8 +2760,9 @@
     simulate_timer_task_ran_ = false;
 
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = false;
     scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -2786,8 +2799,9 @@
     simulate_timer_task_ran_ = false;
 
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = false;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidAnimateForInputOnCompositorThread();
@@ -2827,8 +2841,9 @@
     simulate_timer_task_ran_ = false;
 
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = false;
     scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -2891,8 +2906,9 @@
   SimulateMainThreadGestureStart(TouchEventPolicy::SEND_TOUCH_START,
                                  blink::WebInputEvent::GestureScrollUpdate);
   cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+      cc::BeginFrameArgs::NORMAL);
   begin_frame_args.on_critical_path = false;
   scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -2914,8 +2930,9 @@
     RendererSchedulerImplTest,
     EstimateLongestJankFreeTaskDuration_UseCase_MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
   cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+      cc::BeginFrameArgs::NORMAL);
   begin_frame_args.on_critical_path = false;
   scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -2938,8 +2955,9 @@
   SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
 
   cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+      cc::BeginFrameArgs::NORMAL);
   begin_frame_args.on_critical_path = true;
   scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -3049,8 +3067,9 @@
   SimulateCompositorGestureStart(TouchEventPolicy::DONT_SEND_TOUCH_START);
 
   cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+      cc::BeginFrameArgs::NORMAL);
   begin_frame_args.on_critical_path = true;
   scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -3094,8 +3113,9 @@
 
   for (int i = 0; i < 1000; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3157,8 +3177,9 @@
   bool suspended = false;
   for (int i = 0; i < 1000; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3214,8 +3235,9 @@
 
   for (int i = 0; i < 1000; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3253,8 +3275,9 @@
       RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
 
   cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-      base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+      base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+      cc::BeginFrameArgs::NORMAL);
   begin_frame_args.on_critical_path = true;
   scheduler_->WillBeginFrame(begin_frame_args);
 
@@ -3314,8 +3337,9 @@
 
   for (int i = 0; i < 100; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3355,8 +3379,9 @@
 
   for (int i = 0; i < 100; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3398,8 +3423,9 @@
 
   for (int i = 0; i < 100; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3522,8 +3548,9 @@
 
   for (int i = 0; i < 1000; i++) {
     cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create(
-        BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(),
-        base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL);
+        BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_->NowTicks(),
+        base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
+        cc::BeginFrameArgs::NORMAL);
     begin_frame_args.on_critical_path = true;
     scheduler_->WillBeginFrame(begin_frame_args);
     scheduler_->DidHandleInputEventOnCompositorThread(
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc
index 79110f33..770fda4 100644
--- a/ui/android/window_android.cc
+++ b/ui/android/window_android.cc
@@ -33,6 +33,7 @@
   explicit WindowBeginFrameSource(WindowAndroid* window)
       : window_(window),
         observer_count_(0),
+        next_sequence_number_(cc::BeginFrameArgs::kStartingFrameNumber),
         in_on_vsync_(false) {}
   ~WindowBeginFrameSource() override {}
 
@@ -43,14 +44,14 @@
                       size_t remaining_frames) override {}
   bool IsThrottled() const override { return true; }
 
-  void OnVSync(base::TimeTicks frame_time,
-               base::TimeDelta vsync_period);
+  void OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period);
 
  private:
   WindowAndroid* const window_;
   base::ObserverList<cc::BeginFrameObserver> observers_;
   int observer_count_;
   cc::BeginFrameArgs last_begin_frame_args_;
+  uint64_t next_sequence_number_;
   bool in_on_vsync_;
 };
 
@@ -70,6 +71,9 @@
     cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
     if (!last_args.IsValid() ||
         last_args.frame_time < last_begin_frame_args_.frame_time) {
+      DCHECK(last_args.sequence_number <
+                 last_begin_frame_args_.sequence_number ||
+             last_args.source_id != last_begin_frame_args_.source_id);
       last_begin_frame_args_.type = cc::BeginFrameArgs::MISSED;
       // TODO(crbug.com/602485): A deadline doesn't make too much sense
       // for a missed BeginFrame (the intention rather is 'immediately'),
@@ -98,10 +102,11 @@
     base::TimeDelta vsync_period) {
   // frame time is in the past, so give the next vsync period as the deadline.
   base::TimeTicks deadline = frame_time + vsync_period;
-  last_begin_frame_args_ =
-      cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
-                                 vsync_period, cc::BeginFrameArgs::NORMAL);
+  last_begin_frame_args_ = cc::BeginFrameArgs::Create(
+      BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, frame_time,
+      deadline, vsync_period, cc::BeginFrameArgs::NORMAL);
   DCHECK(last_begin_frame_args_.IsValid());
+  next_sequence_number_++;
 
   // We support adding/removing observers during observer iteration through
   // base::ObserverList. We also prevent observers that are added during