diff --git a/DEPS b/DEPS
index 9018480b..e43bb64 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '4c6e4103a246c27bdd1302a9c7fba64367758dcc',
+  'skia_revision': 'ba8ca0a12985f7c715cb69898fbc60956b65613d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '2783d5390f40a85a6588da2e2f2784fd9349ad86',
+  'v8_revision': '7dda9f883e06f3f00bbcec93601877ea7b9b6c65',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/base/trace_event/process_memory_totals.h b/base/trace_event/process_memory_totals.h
index 12d6dfb..48edc36 100644
--- a/base/trace_event/process_memory_totals.h
+++ b/base/trace_event/process_memory_totals.h
@@ -43,7 +43,6 @@
     uint64_t compressed_bytes = 0;
 
     // Linux, Android, ChromeOS
-    // TODO(hjd): https://crbug.com/707019
     uint64_t rss_anon_bytes = 0;
     uint64_t vm_swap_bytes = 0;
 
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index a957fa7..0684f0fc 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -592,6 +592,8 @@
     "test/layer_tree_pixel_test.h",
     "test/layer_tree_test.cc",
     "test/layer_tree_test.h",
+    "test/mock_compositor_frame_sink_support_client.cc",
+    "test/mock_compositor_frame_sink_support_client.h",
     "test/mock_helper.h",
     "test/mock_occlusion_tracker.h",
     "test/ordered_simple_task_runner.cc",
@@ -857,11 +859,11 @@
     "surfaces/display_unittest.cc",
     "surfaces/referenced_surface_tracker_unittest.cc",
     "surfaces/surface_aggregator_unittest.cc",
-    "surfaces/surface_factory_unittest.cc",
     "surfaces/surface_hittest_unittest.cc",
     "surfaces/surface_manager_ref_unittest.cc",
     "surfaces/surface_manager_unittest.cc",
     "surfaces/surface_sequence_generator_unittest.cc",
+    "surfaces/surface_synchronization_unittest.cc",
     "surfaces/surface_unittest.cc",
     "surfaces/surfaces_pixeltest.cc",
 
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn
index 0ea753ab..154f01e 100644
--- a/cc/surfaces/BUILD.gn
+++ b/cc/surfaces/BUILD.gn
@@ -61,9 +61,6 @@
     "surface_aggregator.h",
     "surface_dependency_tracker.cc",
     "surface_dependency_tracker.h",
-    "surface_factory.cc",
-    "surface_factory.h",
-    "surface_factory_client.h",
     "surface_hittest.cc",
     "surface_hittest.h",
     "surface_hittest_delegate.h",
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc
index 6caf493..77e317f 100644
--- a/cc/surfaces/compositor_frame_sink_support.cc
+++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -12,6 +12,7 @@
 #include "cc/surfaces/compositor_frame_sink_support_client.h"
 #include "cc/surfaces/display.h"
 #include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_info.h"
 #include "cc/surfaces/surface_manager.h"
 #include "cc/surfaces/surface_reference.h"
 
@@ -27,8 +28,9 @@
     bool needs_sync_points) {
   std::unique_ptr<CompositorFrameSinkSupport> support =
       base::WrapUnique(new CompositorFrameSinkSupport(
-          client, frame_sink_id, is_root, handles_frame_sink_id_invalidation));
-  support->Init(surface_manager, needs_sync_points);
+          client, frame_sink_id, is_root, handles_frame_sink_id_invalidation,
+          needs_sync_points));
+  support->Init(surface_manager);
   return support;
 }
 
@@ -43,33 +45,12 @@
       reference_tracker_.current_surface_id().is_valid())
     RemoveTopLevelRootReference(reference_tracker_.current_surface_id());
 
-  // SurfaceFactory's destructor will attempt to return resources which will
-  // call back into here and access |client_| so we should destroy
-  // |surface_factory_|'s resources early on.
-  surface_factory_->EvictSurface();
+  EvictFrame();
   surface_manager_->UnregisterFrameSinkManagerClient(frame_sink_id_);
   if (handles_frame_sink_id_invalidation_)
     surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
 }
 
-void CompositorFrameSinkSupport::ReferencedSurfacesChanged(
-    const LocalSurfaceId& local_surface_id,
-    const std::vector<SurfaceId>* active_referenced_surfaces) {
-  if (!surface_manager_->using_surface_references())
-    return;
-
-  SurfaceId last_surface_id = reference_tracker_.current_surface_id();
-
-  // Populate list of surface references to add and remove based on reference
-  // surfaces in current frame compared with the last frame. The list of
-  // surface references includes references from both the pending and active
-  // frame if any.
-  reference_tracker_.UpdateReferences(local_surface_id,
-                                      active_referenced_surfaces);
-
-  UpdateSurfaceReferences(last_surface_id, local_surface_id);
-}
-
 void CompositorFrameSinkSupport::ReturnResources(
     const ReturnedResourceArray& resources) {
   if (resources.empty())
@@ -94,8 +75,9 @@
 }
 
 void CompositorFrameSinkSupport::EvictFrame() {
-  DCHECK(surface_factory_);
-  surface_factory_->EvictSurface();
+  if (!current_surface_)
+    return;
+  DestroyCurrentSurface();
 }
 
 void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
@@ -119,7 +101,8 @@
 void CompositorFrameSinkSupport::SubmitCompositorFrame(
     const LocalSurfaceId& local_surface_id,
     CompositorFrame frame) {
-  DCHECK(surface_factory_);
+  TRACE_EVENT0("cc", "CompositorFrameSinkSupport::SubmitCompositorFrame");
+  DCHECK(local_surface_id.is_valid());
   DCHECK_GE(frame.metadata.begin_frame_ack.sequence_number,
             BeginFrameArgs::kStartingFrameNumber);
   DCHECK(!frame.render_pass_list.empty());
@@ -130,13 +113,41 @@
   frame.metadata.begin_frame_ack.has_damage = true;
 
   BeginFrameAck ack = frame.metadata.begin_frame_ack;
-  surface_factory_->SubmitCompositorFrame(
-      local_surface_id, std::move(frame),
+
+  if (!ui::LatencyInfo::Verify(frame.metadata.latency_info,
+                               "RenderWidgetHostImpl::OnSwapCompositorFrame")) {
+    std::vector<ui::LatencyInfo>().swap(frame.metadata.latency_info);
+  }
+  for (ui::LatencyInfo& latency : frame.metadata.latency_info) {
+    if (latency.latency_components().size() > 0) {
+      latency.AddLatencyNumber(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT,
+                               0, 0);
+    }
+  }
+
+  std::unique_ptr<Surface> surface;
+  bool create_new_surface =
+      (!current_surface_ ||
+       local_surface_id != current_surface_->surface_id().local_surface_id());
+  if (!create_new_surface) {
+    surface = std::move(current_surface_);
+  } else {
+    surface = CreateSurface(local_surface_id);
+  }
+
+  surface->QueueFrame(
+      std::move(frame),
       base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
                  weak_factory_.GetWeakPtr()),
       base::BindRepeating(&CompositorFrameSinkSupport::WillDrawSurface,
                           weak_factory_.GetWeakPtr()));
 
+  if (current_surface_) {
+    surface->SetPreviousFrameSurface(current_surface_.get());
+    DestroyCurrentSurface();
+  }
+  current_surface_ = std::move(surface);
+
   // TODO(eseckler): The CompositorFrame submitted below might not be activated
   // right away b/c of surface synchronization. We should only send the
   // BeginFrameAck to DisplayScheduler when it is activated. This also means
@@ -191,11 +202,30 @@
   surface_manager_->RemoveSurfaceReferences({reference});
 }
 
+void CompositorFrameSinkSupport::ReferencedSurfacesChanged(
+    const LocalSurfaceId& local_surface_id,
+    const std::vector<SurfaceId>* active_referenced_surfaces) {
+  if (!surface_manager_->using_surface_references())
+    return;
+
+  SurfaceId last_surface_id = reference_tracker_.current_surface_id();
+
+  // Populate list of surface references to add and remove based on reference
+  // surfaces in current frame compared with the last frame. The list of
+  // surface references includes references from both the pending and active
+  // frame if any.
+  reference_tracker_.UpdateReferences(local_surface_id,
+                                      active_referenced_surfaces);
+
+  UpdateSurfaceReferences(last_surface_id, local_surface_id);
+}
+
 void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
   DCHECK_GT(ack_pending_count_, 0);
   ack_pending_count_--;
   if (!client_)
     return;
+
   client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
   surface_returned_resources_.clear();
 }
@@ -212,27 +242,41 @@
   surface_manager_->AssignTemporaryReference(surface_id, frame_sink_id_);
 }
 
+void CompositorFrameSinkSupport::ReceiveFromChild(
+    const TransferableResourceArray& resources) {
+  surface_resource_holder_.ReceiveFromChild(resources);
+}
+
+void CompositorFrameSinkSupport::RefResources(
+    const TransferableResourceArray& resources) {
+  surface_resource_holder_.RefResources(resources);
+}
+
+void CompositorFrameSinkSupport::UnrefResources(
+    const ReturnedResourceArray& resources) {
+  surface_resource_holder_.UnrefResources(resources);
+}
+
 CompositorFrameSinkSupport::CompositorFrameSinkSupport(
     CompositorFrameSinkSupportClient* client,
     const FrameSinkId& frame_sink_id,
     bool is_root,
-    bool handles_frame_sink_id_invalidation)
+    bool handles_frame_sink_id_invalidation,
+    bool needs_sync_points)
     : client_(client),
       frame_sink_id_(frame_sink_id),
+      surface_resource_holder_(this),
       reference_tracker_(frame_sink_id),
       is_root_(is_root),
+      needs_sync_points_(needs_sync_points),
       handles_frame_sink_id_invalidation_(handles_frame_sink_id_invalidation),
       weak_factory_(this) {}
 
-void CompositorFrameSinkSupport::Init(SurfaceManager* surface_manager,
-                                      bool needs_sync_points) {
+void CompositorFrameSinkSupport::Init(SurfaceManager* surface_manager) {
   surface_manager_ = surface_manager;
-  surface_factory_ = base::MakeUnique<SurfaceFactory>(
-      frame_sink_id_, surface_manager_, this, this);
   if (handles_frame_sink_id_invalidation_)
     surface_manager_->RegisterFrameSinkId(frame_sink_id_);
   surface_manager_->RegisterFrameSinkManagerClient(frame_sink_id_, this);
-  surface_factory_->set_needs_sync_points(needs_sync_points);
 }
 
 void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
@@ -249,6 +293,41 @@
 
 void CompositorFrameSinkSupport::OnBeginFrameSourcePausedChanged(bool paused) {}
 
+void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
+  DCHECK(surface->HasActiveFrame());
+  // TODO(staraz): Notify BeginFrameSource about the last activated sequence
+  // number.
+  if (!seen_first_frame_activation_) {
+    seen_first_frame_activation_ = true;
+
+    const CompositorFrame& frame = surface->GetActiveFrame();
+    // CompositorFrames might not be populated with a RenderPass in unit tests.
+    gfx::Size frame_size;
+    if (!frame.render_pass_list.empty())
+      frame_size = frame.render_pass_list.back()->output_rect.size();
+
+    // SurfaceCreated only applies for the first Surface activation. Thus,
+    // SurfaceFactory stops observing new activations after the first one.
+    surface_manager_->SurfaceCreated(SurfaceInfo(
+        surface->surface_id(), frame.metadata.device_scale_factor, frame_size));
+  }
+  // Fire SurfaceCreated first so that a temporary reference is added before it
+  // is potentially transformed into a real reference by the client.
+  ReferencedSurfacesChanged(surface->surface_id().local_surface_id(),
+                            surface->active_referenced_surfaces());
+  if (!surface_manager_->SurfaceModified(surface->surface_id())) {
+    TRACE_EVENT_INSTANT0("cc", "Damage not visible.", TRACE_EVENT_SCOPE_THREAD);
+    surface->RunDrawCallback();
+  }
+}
+
+void CompositorFrameSinkSupport::OnSurfaceDependenciesChanged(
+    Surface* surface,
+    const base::flat_set<SurfaceId>& added_dependencies,
+    const base::flat_set<SurfaceId>& removed_dependencies) {}
+
+void CompositorFrameSinkSupport::OnSurfaceDiscarded(Surface* surface) {}
+
 void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
   if (!begin_frame_source_)
     return;
@@ -263,10 +342,28 @@
     begin_frame_source_->RemoveObserver(this);
 }
 
+std::unique_ptr<Surface> CompositorFrameSinkSupport::CreateSurface(
+    const LocalSurfaceId& local_surface_id) {
+  seen_first_frame_activation_ = false;
+  std::unique_ptr<Surface> surface = surface_manager_->CreateSurface(
+      weak_factory_.GetWeakPtr(), local_surface_id);
+  surface->AddObserver(this);
+  return surface;
+}
+
+void CompositorFrameSinkSupport::DestroyCurrentSurface() {
+  current_surface_->RemoveObserver(this);
+  surface_manager_->DestroySurface(std::move(current_surface_));
+}
+
 void CompositorFrameSinkSupport::RequestCopyOfSurface(
-    std::unique_ptr<CopyOutputRequest> request) {
-  DCHECK(surface_factory_);
-  surface_factory_->RequestCopyOfSurface(std::move(request));
+    std::unique_ptr<CopyOutputRequest> copy_request) {
+  if (!current_surface_)
+    return;
+
+  DCHECK(current_surface_->compositor_frame_sink_support().get() == this);
+  current_surface_->RequestCopyOfOutput(std::move(copy_request));
+  surface_manager_->SurfaceModified(current_surface_->surface_id());
 }
 
 }  // namespace cc
diff --git a/cc/surfaces/compositor_frame_sink_support.h b/cc/surfaces/compositor_frame_sink_support.h
index 247bc1e7..6713fa35 100644
--- a/cc/surfaces/compositor_frame_sink_support.h
+++ b/cc/surfaces/compositor_frame_sink_support.h
@@ -14,10 +14,10 @@
 #include "cc/output/compositor_frame.h"
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/surfaces/frame_sink_manager_client.h"
+#include "cc/surfaces/pending_frame_observer.h"
 #include "cc/surfaces/referenced_surface_tracker.h"
-#include "cc/surfaces/surface_factory.h"
-#include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_resource_holder.h"
 #include "cc/surfaces/surface_resource_holder_client.h"
 #include "cc/surfaces/surfaces_export.h"
 
@@ -27,10 +27,10 @@
 class SurfaceManager;
 
 class CC_SURFACES_EXPORT CompositorFrameSinkSupport
-    : public SurfaceFactoryClient,
-      public BeginFrameObserver,
+    : public BeginFrameObserver,
       public SurfaceResourceHolderClient,
-      public FrameSinkManagerClient {
+      public FrameSinkManagerClient,
+      public PendingFrameObserver {
  public:
   static std::unique_ptr<CompositorFrameSinkSupport> Create(
       CompositorFrameSinkSupportClient* client,
@@ -44,19 +44,14 @@
 
   const FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
 
-  Surface* current_surface_for_testing() {
-    return surface_factory_->current_surface_for_testing();
-  }
+  Surface* current_surface_for_testing() { return current_surface_.get(); }
+  SurfaceManager* surface_manager() { return surface_manager_; }
+  bool needs_sync_points() { return needs_sync_points_; }
 
   const ReferencedSurfaceTracker& ReferenceTrackerForTesting() const {
     return reference_tracker_;
   }
 
-  // SurfaceFactoryClient implementation.
-  void ReferencedSurfacesChanged(
-      const LocalSurfaceId& local_surface_id,
-      const std::vector<SurfaceId>* active_referenced_surfaces) override;
-
   // SurfaceResourceHolderClient implementation.
   void ReturnResources(const ReturnedResourceArray& resources) override;
 
@@ -71,13 +66,19 @@
   void RequestCopyOfSurface(std::unique_ptr<CopyOutputRequest> request);
   void ClaimTemporaryReference(const SurfaceId& surface_id);
 
+  // TODO(staraz): Move the following 3 methods to private.
+  void ReceiveFromChild(const TransferableResourceArray& resources);
+  void RefResources(const TransferableResourceArray& resources);
+  void UnrefResources(const ReturnedResourceArray& resources);
+
  protected:
   CompositorFrameSinkSupport(CompositorFrameSinkSupportClient* client,
                              const FrameSinkId& frame_sink_id,
                              bool is_root,
-                             bool handles_frame_sink_id_invalidation);
+                             bool handles_frame_sink_id_invalidation,
+                             bool needs_sync_points);
 
-  void Init(SurfaceManager* surface_manager, bool needs_sync_points);
+  void Init(SurfaceManager* surface_manager);
 
  private:
   // Update surface references with SurfaceManager for current CompositorFrame
@@ -89,6 +90,9 @@
 
   void AddTopLevelRootReference(const SurfaceId& surface_id);
   void RemoveTopLevelRootReference(const SurfaceId& surface_id);
+  void ReferencedSurfacesChanged(
+      const LocalSurfaceId& local_surface_id,
+      const std::vector<SurfaceId>* active_referenced_surfaces);
 
   void DidReceiveCompositorFrameAck();
   void WillDrawSurface(const LocalSurfaceId& local_surface_id,
@@ -99,7 +103,18 @@
   const BeginFrameArgs& LastUsedBeginFrameArgs() const override;
   void OnBeginFrameSourcePausedChanged(bool paused) override;
 
+  // PendingFrameObserver implementation.
+  void OnSurfaceActivated(Surface* surface) override;
+  void OnSurfaceDependenciesChanged(
+      Surface* surface,
+      const base::flat_set<SurfaceId>& added_dependencies,
+      const base::flat_set<SurfaceId>& removed_dependencies) override;
+  void OnSurfaceDiscarded(Surface* surface) override;
+
   void UpdateNeedsBeginFramesInternal();
+  std::unique_ptr<Surface> CreateSurface(
+      const LocalSurfaceId& local_surface_id);
+  void DestroyCurrentSurface();
 
   CompositorFrameSinkSupportClient* const client_;
 
@@ -107,7 +122,9 @@
 
   const FrameSinkId frame_sink_id_;
 
-  std::unique_ptr<SurfaceFactory> surface_factory_;
+  SurfaceResourceHolder surface_resource_holder_;
+
+  std::unique_ptr<Surface> current_surface_;
   // Counts the number of CompositorFrames that have been submitted and have not
   // yet received an ACK.
   int ack_pending_count_ = 0;
@@ -130,6 +147,8 @@
   ReferencedSurfaceTracker reference_tracker_;
 
   const bool is_root_;
+  const bool needs_sync_points_;
+  bool seen_first_frame_activation_ = false;
 
   // TODO(staraz): Remove this flag once ui::Compositor no longer needs to call
   // RegisterFrameSinkId().
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc
index 7451f8cb..bdaa1ec 100644
--- a/cc/surfaces/compositor_frame_sink_support_unittest.cc
+++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -6,13 +6,18 @@
 
 #include "base/macros.h"
 #include "cc/output/compositor_frame.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
+#include "cc/resources/resource_provider.h"
 #include "cc/surfaces/compositor_frame_sink_support_client.h"
 #include "cc/surfaces/frame_sink_id.h"
 #include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_info.h"
 #include "cc/surfaces/surface_manager.h"
 #include "cc/test/begin_frame_args_test.h"
 #include "cc/test/compositor_frame_helpers.h"
 #include "cc/test/fake_external_begin_frame_source.h"
+#include "cc/test/mock_compositor_frame_sink_support_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -24,1409 +29,761 @@
 using testing::Eq;
 
 namespace cc {
+namespace test {
 namespace {
 
-constexpr FrameSinkId kDisplayFrameSink(2, 0);
-constexpr FrameSinkId kParentFrameSink(3, 0);
-constexpr FrameSinkId kChildFrameSink1(65563, 0);
-constexpr FrameSinkId kChildFrameSink2(65564, 0);
-constexpr FrameSinkId kArbitraryFrameSink(1337, 7331);
+constexpr bool kIsRoot = true;
+constexpr bool kIsChildRoot = false;
+constexpr bool kHandlesFrameSinkIdInvalidation = true;
+constexpr bool kNeedsSyncPoints = true;
 
-class MockCompositorFrameSinkSupportClient
+constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
+constexpr FrameSinkId kAnotherArbitraryFrameSinkId(2, 2);
+constexpr FrameSinkId kYetAnotherArbitraryFrameSinkId(3, 3);
+
+const base::UnguessableToken kArbitraryToken = base::UnguessableToken::Create();
+const base::UnguessableToken kArbitrarySourceId1 =
+    base::UnguessableToken::Deserialize(0xdead, 0xbeef);
+const base::UnguessableToken kArbitrarySourceId2 =
+    base::UnguessableToken::Deserialize(0xdead, 0xbee0);
+
+gpu::SyncToken GenTestSyncToken(int id) {
+  gpu::SyncToken token;
+  token.Set(gpu::CommandBufferNamespace::GPU_IO, 0,
+            gpu::CommandBufferId::FromUnsafeValue(id), 1);
+  return token;
+}
+
+class FakeCompositorFrameSinkSupportClient
     : public CompositorFrameSinkSupportClient {
  public:
-  MockCompositorFrameSinkSupportClient() {
-    ON_CALL(*this, ReclaimResources(_))
-        .WillByDefault(Invoke(
-            this,
-            &MockCompositorFrameSinkSupportClient::ReclaimResourcesInternal));
-    ON_CALL(*this, DidReceiveCompositorFrameAck(_))
-        .WillByDefault(Invoke(
-            this,
-            &MockCompositorFrameSinkSupportClient::ReclaimResourcesInternal));
+  FakeCompositorFrameSinkSupportClient() = default;
+  ~FakeCompositorFrameSinkSupportClient() override = default;
+
+  void DidReceiveCompositorFrameAck(
+      const ReturnedResourceArray& resources) override {
+    InsertResources(resources);
   }
 
-  ReturnedResourceArray& last_returned_resources() {
-    return last_returned_resources_;
+  void OnBeginFrame(const BeginFrameArgs& args) override {}
+
+  void ReclaimResources(const ReturnedResourceArray& resources) override {
+    InsertResources(resources);
   }
 
-  // CompositorFrameSinkSupportClient implementation.
-  MOCK_METHOD1(DidReceiveCompositorFrameAck,
-               void(const ReturnedResourceArray&));
-  MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&));
-  MOCK_METHOD1(ReclaimResources, void(const ReturnedResourceArray&));
-  MOCK_METHOD2(WillDrawSurface, void(const LocalSurfaceId&, const gfx::Rect&));
+  void WillDrawSurface(const LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override {}
+
+  void clear_returned_resources() { returned_resources_.clear(); }
+  const ReturnedResourceArray& returned_resources() {
+    return returned_resources_;
+  }
 
  private:
-  void ReclaimResourcesInternal(const ReturnedResourceArray& resources) {
-    last_returned_resources_ = resources;
+  void InsertResources(const ReturnedResourceArray& resources) {
+    returned_resources_.insert(returned_resources_.end(), resources.begin(),
+                               resources.end());
   }
 
-  ReturnedResourceArray last_returned_resources_;
+  ReturnedResourceArray returned_resources_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeCompositorFrameSinkSupportClient);
 };
 
-std::vector<SurfaceId> empty_surface_ids() {
-  return std::vector<SurfaceId>();
-}
-
-SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) {
-  return SurfaceId(
-      frame_sink_id,
-      LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
-}
-
-CompositorFrame MakeCompositorFrame(
-    std::vector<SurfaceId> activation_dependencies,
-    std::vector<SurfaceId> referenced_surfaces,
-    TransferableResourceArray resource_list) {
-  CompositorFrame compositor_frame = test::MakeCompositorFrame();
-  compositor_frame.metadata.begin_frame_ack = BeginFrameAck(0, 1, 1, true);
-  compositor_frame.metadata.activation_dependencies =
-      std::move(activation_dependencies);
-  compositor_frame.metadata.referenced_surfaces =
-      std::move(referenced_surfaces);
-  compositor_frame.resource_list = std::move(resource_list);
-  return compositor_frame;
-}
-
-CompositorFrame MakeCompositorFrame() {
-  return MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
-                             TransferableResourceArray());
-}
-
-CompositorFrame MakeCompositorFrame(
-    std::vector<SurfaceId> activation_dependencies) {
-  return MakeCompositorFrame(activation_dependencies, activation_dependencies,
-                             TransferableResourceArray());
-}
-
-CompositorFrame MakeCompositorFrame(
-    std::vector<SurfaceId> activation_dependencies,
-    std::vector<SurfaceId> referenced_surfaces) {
-  return MakeCompositorFrame(std::move(activation_dependencies),
-                             std::move(referenced_surfaces),
-                             TransferableResourceArray());
-}
-
-CompositorFrame MakeCompositorFrameWithResources(
-    std::vector<SurfaceId> activation_dependencies,
-    TransferableResourceArray resource_list) {
-  return MakeCompositorFrame(activation_dependencies, empty_surface_ids(),
-                             std::move(resource_list));
-}
-
-TransferableResource MakeResource(ResourceId id,
-                                  ResourceFormat format,
-                                  uint32_t filter,
-                                  const gfx::Size& size) {
-  TransferableResource resource;
-  resource.id = id;
-  resource.format = format;
-  resource.filter = filter;
-  resource.size = size;
-  return resource;
-}
-
-}  // namespace
-
 class CompositorFrameSinkSupportTest : public testing::Test,
                                        public SurfaceObserver {
  public:
   CompositorFrameSinkSupportTest()
-      : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {}
-  ~CompositorFrameSinkSupportTest() override {}
-
-  CompositorFrameSinkSupport& display_support() { return *supports_[0]; }
-  Surface* display_surface() {
-    return display_support().current_surface_for_testing();
+      : support_(
+            CompositorFrameSinkSupport::Create(&fake_support_client_,
+                                               &manager_,
+                                               kArbitraryFrameSinkId,
+                                               kIsRoot,
+                                               kHandlesFrameSinkIdInvalidation,
+                                               kNeedsSyncPoints)),
+        local_surface_id_(3, kArbitraryToken),
+        frame_sync_token_(GenTestSyncToken(4)),
+        consumer_sync_token_(GenTestSyncToken(5)) {
+    manager_.AddObserver(this);
+  }
+  ~CompositorFrameSinkSupportTest() override {
+    manager_.RemoveObserver(this);
+    support_->EvictFrame();
   }
 
-  CompositorFrameSinkSupport& parent_support() { return *supports_[1]; }
-  Surface* parent_surface() {
-    return parent_support().current_surface_for_testing();
-  }
-  const ReferencedSurfaceTracker& parent_reference_tracker() {
-    return parent_support().ReferenceTrackerForTesting();
+  const SurfaceId& last_created_surface_id() const {
+    return last_created_surface_id_;
   }
 
-  CompositorFrameSinkSupport& child_support1() { return *supports_[2]; }
-  Surface* child_surface1() {
-    return child_support1().current_surface_for_testing();
+  // SurfaceObserver implementation.
+  void OnSurfaceCreated(const SurfaceInfo& surface_info) override {
+    last_created_surface_id_ = surface_info.id();
+    last_surface_info_ = surface_info;
+  }
+  void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
+    *changed = true;
   }
 
-  CompositorFrameSinkSupport& child_support2() { return *supports_[3]; }
-  Surface* child_surface2() {
-    return child_support2().current_surface_for_testing();
+  void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
+                                          size_t num_resource_ids) {
+    CompositorFrame frame = MakeCompositorFrame();
+    for (size_t i = 0u; i < num_resource_ids; ++i) {
+      TransferableResource resource;
+      resource.id = resource_ids[i];
+      resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
+      resource.mailbox_holder.sync_token = frame_sync_token_;
+      frame.resource_list.push_back(resource);
+    }
+    support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
+    EXPECT_EQ(last_created_surface_id_.local_surface_id(), local_surface_id_);
   }
 
-  CompositorFrameSinkSupport& support(int index) { return *supports_[index]; }
-  Surface* surface(int index) {
-    return support(index).current_surface_for_testing();
+  void UnrefResources(ResourceId* ids_to_unref,
+                      int* counts_to_unref,
+                      size_t num_ids_to_unref) {
+    ReturnedResourceArray unref_array;
+    for (size_t i = 0; i < num_ids_to_unref; ++i) {
+      ReturnedResource resource;
+      resource.sync_token = consumer_sync_token_;
+      resource.id = ids_to_unref[i];
+      resource.count = counts_to_unref[i];
+      unref_array.push_back(resource);
+    }
+    support_->UnrefResources(unref_array);
   }
 
-  SurfaceManager& surface_manager() { return surface_manager_; }
-
-  // Returns all the references where |surface_id| is the parent.
-  const SurfaceManager::SurfaceIdSet& GetChildReferences(
-      const SurfaceId& surface_id) {
-    return surface_manager().parent_to_child_refs_[surface_id];
+  void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids,
+                                           int* expected_returned_counts,
+                                           size_t expected_resources,
+                                           gpu::SyncToken expected_sync_token) {
+    const ReturnedResourceArray& actual_resources =
+        fake_support_client_.returned_resources();
+    ASSERT_EQ(expected_resources, actual_resources.size());
+    for (size_t i = 0; i < expected_resources; ++i) {
+      ReturnedResource resource = actual_resources[i];
+      EXPECT_EQ(expected_sync_token, resource.sync_token);
+      EXPECT_EQ(expected_returned_ids[i], resource.id);
+      EXPECT_EQ(expected_returned_counts[i], resource.count);
+    }
+    fake_support_client_.clear_returned_resources();
   }
 
-  // Returns true if there is a temporary reference for |surface_id|.
-  bool HasTemporaryReference(const SurfaceId& surface_id) {
-    return surface_manager().HasTemporaryReference(surface_id);
-  }
-
-  SurfaceDependencyTracker& dependency_tracker() {
-    return *surface_manager_.dependency_tracker();
-  }
-
-  FakeExternalBeginFrameSource* begin_frame_source() {
-    return begin_frame_source_.get();
-  }
-
-  // testing::Test:
-  void SetUp() override {
-    testing::Test::SetUp();
-    constexpr bool is_root = true;
-    constexpr bool is_child_root = false;
-    constexpr bool handles_frame_sink_id_invalidation = true;
-    constexpr bool needs_sync_points = true;
-    begin_frame_source_ =
-        base::MakeUnique<FakeExternalBeginFrameSource>(0.f, false);
-    surface_manager_.SetDependencyTracker(
-        base::MakeUnique<SurfaceDependencyTracker>(&surface_manager_,
-                                                   begin_frame_source_.get()));
-    surface_manager_.AddObserver(this);
-    supports_.push_back(CompositorFrameSinkSupport::Create(
-        &support_client_, &surface_manager_, kDisplayFrameSink, is_root,
-        handles_frame_sink_id_invalidation, needs_sync_points));
-    supports_.push_back(CompositorFrameSinkSupport::Create(
-        &support_client_, &surface_manager_, kParentFrameSink, is_child_root,
-        handles_frame_sink_id_invalidation, needs_sync_points));
-    supports_.push_back(CompositorFrameSinkSupport::Create(
-        &support_client_, &surface_manager_, kChildFrameSink1, is_child_root,
-        handles_frame_sink_id_invalidation, needs_sync_points));
-    supports_.push_back(CompositorFrameSinkSupport::Create(
-        &support_client_, &surface_manager_, kChildFrameSink2, is_child_root,
-        handles_frame_sink_id_invalidation, needs_sync_points));
-
-    // Normally, the BeginFrameSource would be registered by the Display. We
-    // register it here so that BeginFrames are received by the display support,
-    // for use in the PassesOnBeginFrameAcks test. Other supports do not receive
-    // BeginFrames, since the frame sink hierarchy is not set up in this test.
-    surface_manager_.RegisterBeginFrameSource(begin_frame_source_.get(),
-                                              kDisplayFrameSink);
-  }
-
-  void TearDown() override {
-    surface_manager_.RemoveObserver(this);
-    surface_manager_.SetDependencyTracker(nullptr);
-    surface_manager_.UnregisterBeginFrameSource(begin_frame_source_.get());
-
-    // SurfaceDependencyTracker depends on this BeginFrameSource and so it must
-    // be destroyed AFTER the dependency tracker is destroyed.
-    begin_frame_source_.reset();
-
-    supports_.clear();
-
-    damaged_surfaces_.clear();
-  }
-
-  bool IsSurfaceDamaged(const SurfaceId& surface_id) const {
-    return damaged_surfaces_.count(surface_id) > 0;
-  }
-
-  // SurfaceObserver implementation:
-  void OnSurfaceCreated(const SurfaceInfo& surface_info) override {}
-  void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) override {
-    damaged_surfaces_.insert(surface_id);
+  void RefCurrentFrameResources() {
+    Surface* surface = manager_.GetSurfaceForId(
+        SurfaceId(support_->frame_sink_id(), local_surface_id_));
+    support_->RefResources(surface->GetActiveFrame().resource_list);
   }
 
  protected:
-  testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_;
+  SurfaceManager manager_;
+  FakeCompositorFrameSinkSupportClient fake_support_client_;
+  std::unique_ptr<CompositorFrameSinkSupport> support_;
+  LocalSurfaceId local_surface_id_;
+  SurfaceId last_created_surface_id_;
+  SurfaceInfo last_surface_info_;
 
- private:
-  base::flat_set<SurfaceId> damaged_surfaces_;
-  SurfaceManager surface_manager_;
-  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_;
-  std::vector<std::unique_ptr<CompositorFrameSinkSupport>> supports_;
+  // This is the sync token submitted with the frame. It should never be
+  // returned to the client.
+  const gpu::SyncToken frame_sync_token_;
 
-  DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupportTest);
+  // This is the sync token returned by the consumer. It should always be
+  // returned to the client.
+  const gpu::SyncToken consumer_sync_token_;
 };
 
-// The display root surface should have a surface reference from the top-level
-// root added/removed when a CompositorFrame is submitted with a new SurfaceId.
-TEST_F(CompositorFrameSinkSupportTest, RootSurfaceReceivesReferences) {
-  const SurfaceId display_id_first = MakeSurfaceId(kDisplayFrameSink, 1);
-  const SurfaceId display_id_second = MakeSurfaceId(kDisplayFrameSink, 2);
+// Tests submitting a frame with resources followed by one with no resources
+// with no resource provider action in between.
+TEST_F(CompositorFrameSinkSupportTest, ResourceLifetimeSimple) {
+  ResourceId first_frame_ids[] = {1, 2, 3};
+  SubmitCompositorFrameWithResources(first_frame_ids,
+                                     arraysize(first_frame_ids));
 
-  // Submit a CompositorFrame for the first display root surface.
-  display_support().SubmitCompositorFrame(display_id_first.local_surface_id(),
-                                          MakeCompositorFrame());
+  // All of the resources submitted in the first frame are still in use at this
+  // time by virtue of being in the pending frame, so none can be returned to
+  // the client yet.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+  fake_support_client_.clear_returned_resources();
 
-  // A surface reference from the top-level root is added and there shouldn't be
-  // a temporary reference.
-  EXPECT_FALSE(HasTemporaryReference(display_id_first));
-  EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()),
-              UnorderedElementsAre(display_id_first));
+  // The second frame references no resources of first frame and thus should
+  // make all resources of first frame available to be returned.
+  SubmitCompositorFrameWithResources(NULL, 0);
 
-  // Submit a CompositorFrame for the second display root surface.
-  display_support().SubmitCompositorFrame(display_id_second.local_surface_id(),
-                                          MakeCompositorFrame());
+  ResourceId expected_returned_ids[] = {1, 2, 3};
+  int expected_returned_counts[] = {1, 1, 1};
+  // Resources were never consumed so no sync token should be set.
+  CheckReturnedResourcesMatchExpected(
+      expected_returned_ids, expected_returned_counts,
+      arraysize(expected_returned_counts), gpu::SyncToken());
 
-  // A surface reference from the top-level root to |display_id_second| should
-  // be added and the reference to |display_root_first| removed.
-  EXPECT_FALSE(HasTemporaryReference(display_id_second));
-  EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()),
-              UnorderedElementsAre(display_id_second));
+  ResourceId third_frame_ids[] = {4, 5, 6};
+  SubmitCompositorFrameWithResources(third_frame_ids,
+                                     arraysize(third_frame_ids));
 
-  // Surface |display_id_first| is unreachable and should get deleted.
-  EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(display_id_first));
+  // All of the resources submitted in the third frame are still in use at this
+  // time by virtue of being in the pending frame, so none can be returned to
+  // the client yet.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+  fake_support_client_.clear_returned_resources();
+
+  // The forth frame references no resources of third frame and thus should
+  // make all resources of third frame available to be returned.
+  ResourceId forth_frame_ids[] = {7, 8, 9};
+  SubmitCompositorFrameWithResources(forth_frame_ids,
+                                     arraysize(forth_frame_ids));
+
+  ResourceId forth_expected_returned_ids[] = {4, 5, 6};
+  int forth_expected_returned_counts[] = {1, 1, 1};
+  // Resources were never consumed so no sync token should be set.
+  CheckReturnedResourcesMatchExpected(
+      forth_expected_returned_ids, forth_expected_returned_counts,
+      arraysize(forth_expected_returned_counts), gpu::SyncToken());
 }
 
-// The parent Surface is blocked on |child_id1| and |child_id2|.
-TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedOnTwo) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
-
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id1, child_id2}, empty_surface_ids()));
-
-  // parent_support is blocked on |child_id1| and |child_id2|.
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1, child_id2));
-
-  // Submit a CompositorFrame without any dependencies to |child_id1|.
-  // parent_support should now only be blocked on |child_id2|.
-  child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
-                                         MakeCompositorFrame());
-
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
-
-  // Submit a CompositorFrame without any dependencies to |child_id2|.
-  // parent_support should be activated.
-  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
-                                         MakeCompositorFrame());
-
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-}
-
-// The parent Surface is blocked on |child_id2| which is blocked on |child_id3|.
-TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedChain) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
-
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id1}, empty_surface_ids()));
-
-  // parent_support is blocked on |child_id1|.
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1));
-  // The parent should not report damage until it activates.
-  EXPECT_FALSE(IsSurfaceDamaged(parent_id));
-
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrame({child_id2}, empty_surface_ids()));
-
-  // child_support1 should now be blocked on |child_id2|.
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(child_surface1()->HasActiveFrame());
-  EXPECT_TRUE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
-  // The parent and child should not report damage until they activate.
-  EXPECT_FALSE(IsSurfaceDamaged(parent_id));
-  EXPECT_FALSE(IsSurfaceDamaged(child_id1));
-
-  // The parent should still be blocked on |child_id1| because it's pending.
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1));
-
-  // Submit a CompositorFrame without any dependencies to |child_id2|.
-  // parent_support should be activated.
-  child_support2().SubmitCompositorFrame(
-      child_id2.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
-
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-
-  // child_surface1 should now be active.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-
-  // parent_surface should now be active.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-
-  // All three surfaces |parent_id|, |child_id1|, and |child_id2| should
-  // now report damage. This would trigger a new display frame.
-  EXPECT_TRUE(IsSurfaceDamaged(parent_id));
-  EXPECT_TRUE(IsSurfaceDamaged(child_id1));
-  EXPECT_TRUE(IsSurfaceDamaged(child_id2));
-}
-
-// parent_surface and child_surface1 are blocked on |child_id2|.
+// Tests submitting a frame with resources followed by one with no resources
+// with the resource provider holding everything alive.
 TEST_F(CompositorFrameSinkSupportTest,
-       DisplayCompositorLockingTwoBlockedOnOne) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+       ResourceLifetimeSimpleWithProviderHoldingAlive) {
+  ResourceId first_frame_ids[] = {1, 2, 3};
+  SubmitCompositorFrameWithResources(first_frame_ids,
+                                     arraysize(first_frame_ids));
 
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id2}, empty_surface_ids()));
+  // All of the resources submitted in the first frame are still in use at this
+  // time by virtue of being in the pending frame, so none can be returned to
+  // the client yet.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+  fake_support_client_.clear_returned_resources();
 
-  // parent_support is blocked on |child_id2|.
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
+  // Hold on to everything.
+  RefCurrentFrameResources();
 
-  // child_support1 should now be blocked on |child_id2|.
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrame({child_id2}, empty_surface_ids()));
+  // The second frame references no resources and thus should make all resources
+  // available to be returned as soon as the resource provider releases them.
+  SubmitCompositorFrameWithResources(NULL, 0);
 
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(child_surface1()->HasActiveFrame());
-  EXPECT_TRUE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+  fake_support_client_.clear_returned_resources();
 
-  // The parent should still be blocked on |child_id2|.
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
+  int release_counts[] = {1, 1, 1};
+  UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
 
-  // Submit a CompositorFrame without any dependencies to |child_id2|.
-  // parent_support should be activated.
-  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
-                                         MakeCompositorFrame());
+  // None is returned to the client since DidReceiveCompositorAck is not
+  // invoked.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
 
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-
-  // child_surface1 should now be active.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-
-  // parent_surface should now be active.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+  // Submitting an empty frame causes previous resources referenced by the
+  // previous frame to be returned to client.
+  SubmitCompositorFrameWithResources(nullptr, 0);
+  ResourceId expected_returned_ids[] = {1, 2, 3};
+  int expected_returned_counts[] = {1, 1, 1};
+  CheckReturnedResourcesMatchExpected(
+      expected_returned_ids, expected_returned_counts,
+      arraysize(expected_returned_counts), consumer_sync_token_);
 }
 
-// parent_surface is blocked on |child_id1|, and child_surface2 is blocked on
-// |child_id2| until the deadline hits.
-TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingDeadlineHits) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+// Tests referencing a resource, unref'ing it to zero, then using it again
+// before returning it to the client.
+TEST_F(CompositorFrameSinkSupportTest, ResourceReusedBeforeReturn) {
+  ResourceId first_frame_ids[] = {7};
+  SubmitCompositorFrameWithResources(first_frame_ids,
+                                     arraysize(first_frame_ids));
 
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id1}, empty_surface_ids()));
+  // This removes all references to resource id 7.
+  SubmitCompositorFrameWithResources(NULL, 0);
 
-  // parent_support is blocked on |child_id1|.
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1));
+  // This references id 7 again.
+  SubmitCompositorFrameWithResources(first_frame_ids,
+                                     arraysize(first_frame_ids));
 
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrame({child_id2}, empty_surface_ids()));
+  // This removes it again.
+  SubmitCompositorFrameWithResources(NULL, 0);
 
-  // child_support1 should now be blocked on |child_id2|.
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(child_surface1()->HasActiveFrame());
-  EXPECT_TRUE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
+  // Now it should be returned.
+  // We don't care how many entries are in the returned array for 7, so long as
+  // the total returned count matches the submitted count.
+  const ReturnedResourceArray& returned =
+      fake_support_client_.returned_resources();
+  size_t return_count = 0;
+  for (size_t i = 0; i < returned.size(); ++i) {
+    EXPECT_EQ(7u, returned[i].id);
+    return_count += returned[i].count;
+  }
+  EXPECT_EQ(2u, return_count);
+}
 
-  // The parent should still be blocked on |child_id1| because it's pending.
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1));
+// Tests having resources referenced multiple times, as if referenced by
+// multiple providers.
+TEST_F(CompositorFrameSinkSupportTest, ResourceRefMultipleTimes) {
+  ResourceId first_frame_ids[] = {3, 4};
+  SubmitCompositorFrameWithResources(first_frame_ids,
+                                     arraysize(first_frame_ids));
 
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  // Ref resources from the first frame twice.
+  RefCurrentFrameResources();
+  RefCurrentFrameResources();
 
-  for (int i = 0; i < 3; ++i) {
-    begin_frame_source()->TestOnBeginFrame(args);
-    // There is still a looming deadline! Eeek!
-    EXPECT_TRUE(dependency_tracker().has_deadline());
+  ResourceId second_frame_ids[] = {4, 5};
+  SubmitCompositorFrameWithResources(second_frame_ids,
+                                     arraysize(second_frame_ids));
 
-    // parent_support is still blocked on |child_id1|.
-    EXPECT_FALSE(parent_surface()->HasActiveFrame());
-    EXPECT_TRUE(parent_surface()->HasPendingFrame());
-    EXPECT_THAT(parent_surface()->blocking_surfaces(),
-                UnorderedElementsAre(child_id1));
+  // Ref resources from the second frame 3 times.
+  RefCurrentFrameResources();
+  RefCurrentFrameResources();
+  RefCurrentFrameResources();
 
-    // child_support1 is still blocked on |child_id2|.
-    EXPECT_FALSE(child_surface1()->HasActiveFrame());
-    EXPECT_TRUE(child_surface1()->HasPendingFrame());
-    EXPECT_THAT(child_surface1()->blocking_surfaces(),
-                UnorderedElementsAre(child_id2));
+  // Submit a frame with no resources to remove all current frame refs from
+  // submitted resources.
+  SubmitCompositorFrameWithResources(NULL, 0);
+
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+  fake_support_client_.clear_returned_resources();
+
+  // Expected current refs:
+  //  3 -> 2
+  //  4 -> 2 + 3 = 5
+  //  5 -> 3
+  {
+    SCOPED_TRACE("unref all 3");
+    ResourceId ids_to_unref[] = {3, 4, 5};
+    int counts[] = {1, 1, 1};
+    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+
+    EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+    fake_support_client_.clear_returned_resources();
+
+    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+    SubmitCompositorFrameWithResources(nullptr, 0);
+    ResourceId expected_returned_ids[] = {3};
+    int expected_returned_counts[] = {1};
+    CheckReturnedResourcesMatchExpected(
+        expected_returned_ids, expected_returned_counts,
+        arraysize(expected_returned_counts), consumer_sync_token_);
   }
 
-  begin_frame_source()->TestOnBeginFrame(args);
+  // Expected refs remaining:
+  //  4 -> 3
+  //  5 -> 1
+  {
+    SCOPED_TRACE("unref 4 and 5");
+    ResourceId ids_to_unref[] = {4, 5};
+    int counts[] = {1, 1};
+    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+    SubmitCompositorFrameWithResources(nullptr, 0);
 
-  // The deadline has passed.
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-
-  // parent_surface has been activated.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-
-  // child_surface1 has been activated.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-}
-
-// Verifies that the deadline does not reset if we submit CompositorFrames
-// to new Surfaces with unresolved dependencies.
-TEST_F(CompositorFrameSinkSupportTest,
-       DisplayCompositorLockingFramesSubmittedAfterDeadlineSet) {
-  const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  for (int i = 0; i < 3; ++i) {
-    LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
-    support(i).SubmitCompositorFrame(
-        local_surface_id,
-        MakeCompositorFrame({arbitrary_id}, empty_surface_ids()));
-    // The deadline has been set.
-    EXPECT_TRUE(dependency_tracker().has_deadline());
-
-    // support(i) should be blocked on arbitrary_id.
-    EXPECT_FALSE(surface(i)->HasActiveFrame());
-    EXPECT_TRUE(surface(i)->HasPendingFrame());
-    EXPECT_THAT(surface(i)->blocking_surfaces(),
-                UnorderedElementsAre(arbitrary_id));
-
-    // Issue a BeginFrame to get closer to the deadline.
-    begin_frame_source()->TestOnBeginFrame(args);
+    ResourceId expected_returned_ids[] = {5};
+    int expected_returned_counts[] = {1};
+    CheckReturnedResourcesMatchExpected(
+        expected_returned_ids, expected_returned_counts,
+        arraysize(expected_returned_counts), consumer_sync_token_);
   }
 
-  // The deadline hits and all the Surfaces should activate.
-  begin_frame_source()->TestOnBeginFrame(args);
-  for (int i = 0; i < 3; ++i) {
-    EXPECT_TRUE(surface(i)->HasActiveFrame());
-    EXPECT_FALSE(surface(i)->HasPendingFrame());
-    EXPECT_THAT(surface(i)->blocking_surfaces(), IsEmpty());
+  // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
+  // the returned count is correct.
+  {
+    SCOPED_TRACE("unref only 4");
+    ResourceId ids_to_unref[] = {4};
+    int counts[] = {2};
+    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+    SubmitCompositorFrameWithResources(nullptr, 0);
+
+    ResourceId expected_returned_ids[] = {4};
+    int expected_returned_counts[] = {2};
+    CheckReturnedResourcesMatchExpected(
+        expected_returned_ids, expected_returned_counts,
+        arraysize(expected_returned_counts), consumer_sync_token_);
   }
 }
 
-// This test verifies at the Surface activates once a CompositorFrame is
-// submitted that has no unresolved dependencies.
-TEST_F(CompositorFrameSinkSupportTest,
-       DisplayCompositorLockingNewFrameOverridesOldDependencies) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
+TEST_F(CompositorFrameSinkSupportTest, ResourceLifetime) {
+  ResourceId first_frame_ids[] = {1, 2, 3};
+  SubmitCompositorFrameWithResources(first_frame_ids,
+                                     arraysize(first_frame_ids));
 
-  // Submit a CompositorFrame that depends on |arbitrary_id|.
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({arbitrary_id}, empty_surface_ids()));
+  // All of the resources submitted in the first frame are still in use at this
+  // time by virtue of being in the pending frame, so none can be returned to
+  // the client yet.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+  fake_support_client_.clear_returned_resources();
 
-  // Verify that the CompositorFrame is blocked on |arbitrary_id|.
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(arbitrary_id));
+  // The second frame references some of the same resources, but some different
+  // ones. We expect to receive back resource 1 with a count of 1 since it was
+  // only referenced by the first frame.
+  ResourceId second_frame_ids[] = {2, 3, 4};
+  SubmitCompositorFrameWithResources(second_frame_ids,
+                                     arraysize(second_frame_ids));
+  {
+    SCOPED_TRACE("second frame");
+    ResourceId expected_returned_ids[] = {1};
+    int expected_returned_counts[] = {1};
+    CheckReturnedResourcesMatchExpected(
+        expected_returned_ids, expected_returned_counts,
+        arraysize(expected_returned_counts), gpu::SyncToken());
+  }
 
-  // Submit a CompositorFrame that has no dependencies.
-  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
-                                         MakeCompositorFrame());
+  // The third frame references a disjoint set of resources, so we expect to
+  // receive back all resources from the first and second frames. Resource IDs 2
+  // and 3 will have counts of 2, since they were used in both frames, and
+  // resource ID 4 will have a count of 1.
+  ResourceId third_frame_ids[] = {10, 11, 12, 13};
+  SubmitCompositorFrameWithResources(third_frame_ids,
+                                     arraysize(third_frame_ids));
 
-  // Verify that the CompositorFrame has been activated.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+  {
+    SCOPED_TRACE("third frame");
+    ResourceId expected_returned_ids[] = {2, 3, 4};
+    int expected_returned_counts[] = {2, 2, 1};
+    CheckReturnedResourcesMatchExpected(
+        expected_returned_ids, expected_returned_counts,
+        arraysize(expected_returned_counts), gpu::SyncToken());
+  }
+
+  // Simulate a ResourceProvider taking a ref on all of the resources.
+  RefCurrentFrameResources();
+
+  ResourceId fourth_frame_ids[] = {12, 13};
+  SubmitCompositorFrameWithResources(fourth_frame_ids,
+                                     arraysize(fourth_frame_ids));
+
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+
+  RefCurrentFrameResources();
+
+  // All resources are still being used by the external reference, so none can
+  // be returned to the client.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+
+  // Release resources associated with the first RefCurrentFrameResources() call
+  // first.
+  {
+    ResourceId ids_to_unref[] = {10, 11, 12, 13};
+    int counts[] = {1, 1, 1, 1};
+    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+  }
+
+  // Nothing is returned to the client yet since DidReceiveCompositorFrameAck
+  // is not invoked.
+  {
+    SCOPED_TRACE("fourth frame, first unref");
+    CheckReturnedResourcesMatchExpected(nullptr, nullptr, 0,
+                                        consumer_sync_token_);
+  }
+
+  {
+    ResourceId ids_to_unref[] = {12, 13};
+    int counts[] = {1, 1};
+    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+  }
+
+  // Resources 12 and 13 are still in use by the current frame, so they
+  // shouldn't be available to be returned.
+  EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
+
+  // If we submit an empty frame, however, they should become available.
+  // Resources that were previously unref'd also return at this point.
+  SubmitCompositorFrameWithResources(NULL, 0u);
+
+  {
+    SCOPED_TRACE("fourth frame, second unref");
+    ResourceId expected_returned_ids[] = {10, 11, 12, 13};
+    int expected_returned_counts[] = {1, 1, 2, 2};
+    CheckReturnedResourcesMatchExpected(
+        expected_returned_ids, expected_returned_counts,
+        arraysize(expected_returned_counts), consumer_sync_token_);
+  }
 }
 
-// This test verifies that a pending CompositorFrame does not affect surface
-// references. A new surface from a child will continue to exist as a temporary
-// reference until the parent's frame activates.
-TEST_F(CompositorFrameSinkSupportTest,
-       OnlyActiveFramesAffectSurfaceReferences) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+TEST_F(CompositorFrameSinkSupportTest, AddDuringEviction) {
+  MockCompositorFrameSinkSupportClient mock_client;
+  std::unique_ptr<CompositorFrameSinkSupport> support =
+      CompositorFrameSinkSupport::Create(
+          &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
+          kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
+  LocalSurfaceId local_surface_id(6, kArbitraryToken);
+  support->SubmitCompositorFrame(local_surface_id, MakeCompositorFrame());
 
-  // child_support1 submits a CompositorFrame without any dependencies.
-  // DidReceiveCompositorFrameAck should call on immediate activation.
-  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(1);
-  child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
-                                         MakeCompositorFrame());
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // Verify that the child surface is not blocked.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-
-  // Verify that there's a temporary reference for |child_id1|.
-  EXPECT_TRUE(HasTemporaryReference(child_id1));
-
-  // parent_support submits a CompositorFrame that depends on |child_id1|
-  // (which is already active) and |child_id2|. Thus, the parent should not
-  // activate immediately. DidReceiveCompositorFrameAck should not be called
-  // immediately because the parent CompositorFrame is also blocked on
-  // |child_id2|.
-  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id2}, {child_id1}));
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
-  EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // Verify that there's a temporary reference for |child_id1| that still
-  // exists.
-  EXPECT_TRUE(HasTemporaryReference(child_id1));
-
-  // child_support2 submits a CompositorFrame without any dependencies.
-  // Both the child and the parent should immediately ACK CompositorFrames
-  // on activation.
-  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2);
-  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
-                                         MakeCompositorFrame());
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // Verify that the child surface is not blocked.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-
-  // Verify that the parent surface's CompositorFrame has activated and that the
-  // temporary reference has been replaced by a permanent one.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-  EXPECT_FALSE(HasTemporaryReference(child_id1));
-  EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
+  EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(_))
+      .WillOnce(testing::InvokeWithoutArgs([&support, &mock_client]() {
+        LocalSurfaceId new_id(7, base::UnguessableToken::Create());
+        support->SubmitCompositorFrame(new_id, MakeCompositorFrame());
+      }))
+      .WillRepeatedly(testing::Return());
+  support->EvictFrame();
 }
 
-// This test verifies that we do not double count returned resources when a
-// CompositorFrame starts out as pending, then becomes active, and then is
-// replaced with another active CompositorFrame.
-TEST_F(CompositorFrameSinkSupportTest,
-       DisplayCompositorLockingResourcesOnlyReturnedOnce) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
-
-  // The parent submits a CompositorFrame that depends on |child_id| before the
-  // child submits a CompositorFrame. The CompositorFrame also has resources in
-  // its resource list.
-  TransferableResource resource =
-      MakeResource(1337 /* id */, ALPHA_8 /* format */, 1234 /* filter */,
-                   gfx::Size(1234, 5678));
-  TransferableResourceArray resource_list = {resource};
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrameWithResources({child_id}, resource_list));
-
-  // Verify that the CompositorFrame is blocked on |child_id|.
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id));
-
-  child_support1().SubmitCompositorFrame(
-      child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
-
-  // Verify that the child CompositorFrame activates immediately.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-
-  // Verify that the parent has activated.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-
-  // The parent submits a CompositorFrame without any dependencies. That frame
-  // should activate immediately, replacing the earlier frame. The resource from
-  // the earlier frame should be returned to the client.
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(), MakeCompositorFrame({empty_surface_ids()}));
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-  ReturnedResource returned_resource = resource.ToReturnedResource();
-  EXPECT_THAT(support_client_.last_returned_resources(),
-              UnorderedElementsAre(returned_resource));
-}
-
-// The parent Surface is blocked on |child_id2| which is blocked on |child_id3|.
-// child_support1 evicts its blocked Surface. The parent surface should
-// activate.
-TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithPendingFrame) {
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
-
-  // Submit a CompositorFrame that depends on |child_id1|.
-  parent_support().SubmitCompositorFrame(
-      parent_id1.local_surface_id(),
-      MakeCompositorFrame({child_id1}, empty_surface_ids()));
-
-  // Verify that the CompositorFrame is blocked on |child_id1|.
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1));
-
-  // Submit a CompositorFrame that depends on |child_id2|.
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrame({child_id2}, empty_surface_ids()));
-
-  // Verify that the CompositorFrame is blocked on |child_id2|.
-  EXPECT_FALSE(child_surface1()->HasActiveFrame());
-  EXPECT_TRUE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
-
-  // Evict child_support1's current Surface.
-  // TODO(fsamuel): EvictFrame => EvictCurrentSurface.
-  child_support1().EvictFrame();
-
-  // The parent Surface should immediately activate.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-}
-
-// This test verifies that if a surface has both a pending and active
-// CompositorFrame and the pending CompositorFrame activates, replacing the
-// existing active CompositorFrame, then the surface reference hierarchy will be
-// updated allowing garbage collection of surfaces that are no longer
-// referenced.
-TEST_F(CompositorFrameSinkSupportTest, DropStaleReferencesAfterActivation) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
-
-  // The parent submits a CompositorFrame that depends on |child_id1| before the
-  // child submits a CompositorFrame.
-  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id1}, empty_surface_ids()));
-
-  // Verify that the CompositorFrame is blocked on |child_id|.
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id1));
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // Verify that no references are added while the CompositorFrame is pending.
-  EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
-
-  // DidReceiveCompositorFrameAck should get called twice: once for the child
-  // and once for the now active parent CompositorFrame.
-  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2);
-  child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
-                                         MakeCompositorFrame());
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // Verify that the child CompositorFrame activates immediately.
-  EXPECT_TRUE(child_surface1()->HasActiveFrame());
-  EXPECT_FALSE(child_surface1()->HasPendingFrame());
-  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
-
-  // Verify that the parent Surface has activated.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-
-  // Submit a new parent CompositorFrame to add a reference.
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame(empty_surface_ids(), {child_id1}));
-
-  // Verify that the parent Surface has activated.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-
-  // Verify that there is no temporary reference for the child and that
-  // the reference from the parent to the child still exists.
-  EXPECT_FALSE(HasTemporaryReference(child_id1));
-  EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
-
-  // The parent submits another CompositorFrame that depends on |child_id2|.
-  // Submitting a pending CompositorFrame will not trigger a CompositorFrameAck.
-  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrame({child_id2}, empty_surface_ids()));
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // The parent surface should now have both a pending and activate
-  // CompositorFrame. Verify that the set of child references from
-  // |parent_id| are only from the active CompositorFrame.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(),
-              UnorderedElementsAre(child_id2));
-  EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
-
-  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
-                                         MakeCompositorFrame());
-
-  // Verify that the parent Surface has activated and no longer has a pending
-  // CompositorFrame. Also verify that |child_id1| is no longer a child
-  // reference of |parent_id|.
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
-  // The parent will not immediately refer to the child until it submits a new
-  // CompositorFrame with the reference.
-  EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
-}
-
-// Checks whether the latency info are moved to the new surface from the old
-// one when LocalSurfaceId changes. No frame has unresolved dependencies.
-TEST_F(CompositorFrameSinkSupportTest,
-       LatencyInfoCarriedOverOnResize_NoUnresolvedDependencies) {
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
-  const ui::LatencyComponentType latency_type1 =
-      ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
-  const int64_t latency_id1 = 234;
-  const int64_t latency_sequence_number1 = 5645432;
-  const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
-  const int64_t latency_id2 = 31434351;
-  const int64_t latency_sequence_number2 = 663788;
-
-  // Submit a frame with latency info
-  ui::LatencyInfo info;
-  info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
-
-  CompositorFrame frame = MakeCompositorFrame();
-  frame.metadata.latency_info.push_back(info);
-
-  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
-                                         std::move(frame));
-
-  // Verify that the old surface has an active frame and no pending frame.
-  Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1);
-  ASSERT_NE(nullptr, old_surface);
-  EXPECT_TRUE(old_surface->HasActiveFrame());
-  EXPECT_FALSE(old_surface->HasPendingFrame());
-
-  // Submit another frame with some other latency info and a different
-  // LocalSurfaceId.
-  ui::LatencyInfo info2;
-  info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
-
-  CompositorFrame frame2 = MakeCompositorFrame();
-  frame2.metadata.latency_info.push_back(info2);
-
-  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
-                                         std::move(frame2));
-
-  // Verify that the new surface has an active frame and no pending frames.
-  Surface* surface = surface_manager().GetSurfaceForId(parent_id2);
-  ASSERT_NE(nullptr, surface);
-  EXPECT_TRUE(surface->HasActiveFrame());
-  EXPECT_FALSE(surface->HasPendingFrame());
-
-  // Verify that the new surface has both latency info elements.
-  std::vector<ui::LatencyInfo> info_list;
-  surface->TakeLatencyInfo(&info_list);
-  EXPECT_EQ(2u, info_list.size());
-
-  ui::LatencyInfo aggregated_latency_info = info_list[0];
-  aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
-
-  // Two components are the original ones, and the third one is
-  // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
-  // submit.
-  EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
-
-  ui::LatencyInfo::LatencyComponent comp1;
-  EXPECT_TRUE(
-      aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
-  EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
-  EXPECT_TRUE(
-      aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
-  EXPECT_TRUE(aggregated_latency_info.FindLatency(
-      ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
-}
-
-// Checks whether the latency info are moved to the new surface from the old
-// one when LocalSurfaceId changes. Old surface has unresolved dependencies.
-TEST_F(CompositorFrameSinkSupportTest,
-       LatencyInfoCarriedOverOnResize_OldSurfaceHasPendingAndActiveFrame) {
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
-
-  const ui::LatencyComponentType latency_type1 =
-      ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
-  const int64_t latency_id1 = 234;
-  const int64_t latency_sequence_number1 = 5645432;
-  const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
-  const int64_t latency_id2 = 31434351;
-  const int64_t latency_sequence_number2 = 663788;
-
-  // Submit a frame with no unresolved dependecy.
-  ui::LatencyInfo info;
-  info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
-
-  CompositorFrame frame = MakeCompositorFrame();
-  frame.metadata.latency_info.push_back(info);
-
-  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
-                                         std::move(frame));
-
-  // Submit a frame with unresolved dependencies.
-  ui::LatencyInfo info2;
-  info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
-
-  CompositorFrame frame2 = MakeCompositorFrame({child_id}, empty_surface_ids());
-  frame2.metadata.latency_info.push_back(info2);
-
-  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
-                                         std::move(frame2));
-
-  // Verify that the old surface has both an active and a pending frame.
-  Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1);
-  ASSERT_NE(nullptr, old_surface);
-  EXPECT_TRUE(old_surface->HasActiveFrame());
-  EXPECT_TRUE(old_surface->HasPendingFrame());
-
-  // Submit a frame with a new local surface id.
-  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
-                                         MakeCompositorFrame());
-
-  // Verify that the new surface has an active frame only.
-  Surface* surface = surface_manager().GetSurfaceForId(parent_id2);
-  ASSERT_NE(nullptr, surface);
-  EXPECT_TRUE(surface->HasActiveFrame());
-  EXPECT_FALSE(surface->HasPendingFrame());
-
-  // Verify that the new surface has latency info from both active and pending
-  // frame of the old surface.
-  std::vector<ui::LatencyInfo> info_list;
-  surface->TakeLatencyInfo(&info_list);
-  EXPECT_EQ(2u, info_list.size());
-
-  ui::LatencyInfo aggregated_latency_info = info_list[0];
-  aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
-
-  // Two components are the original ones, and the third one is
-  // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
-  // submit.
-  EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
-
-  ui::LatencyInfo::LatencyComponent comp1;
-  EXPECT_TRUE(
-      aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
-  EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
-  EXPECT_TRUE(
-      aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
-  EXPECT_TRUE(aggregated_latency_info.FindLatency(
-      ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
-}
-
-// Checks whether the latency info are moved to the new surface from the old
-// one when LocalSurfaceId changes. The new surface has unresolved dependencies.
-TEST_F(CompositorFrameSinkSupportTest,
-       LatencyInfoCarriedOverOnResize_NewSurfaceHasPendingFrame) {
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
-
-  const ui::LatencyComponentType latency_type1 =
-      ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
-  const int64_t latency_id1 = 234;
-  const int64_t latency_sequence_number1 = 5645432;
-  const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
-  const int64_t latency_id2 = 31434351;
-  const int64_t latency_sequence_number2 = 663788;
-
-  // Submit a frame with no unresolved dependencies.
-  ui::LatencyInfo info;
-  info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
-
-  CompositorFrame frame = MakeCompositorFrame();
-  frame.metadata.latency_info.push_back(info);
-
-  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
-                                         std::move(frame));
-
-  // Verify that the old surface has an active frame only.
-  Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1);
-  ASSERT_NE(nullptr, old_surface);
-  EXPECT_TRUE(old_surface->HasActiveFrame());
-  EXPECT_FALSE(old_surface->HasPendingFrame());
-
-  // Submit a frame with a new local surface id and with unresolved
-  // dependencies.
-  ui::LatencyInfo info2;
-  info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
-
-  CompositorFrame frame2 = MakeCompositorFrame({child_id}, empty_surface_ids());
-  frame2.metadata.latency_info.push_back(info2);
-
-  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
-                                         std::move(frame2));
-
-  // Verify that the new surface has a pending frame and no active frame.
-  Surface* surface = surface_manager().GetSurfaceForId(parent_id2);
-  ASSERT_NE(nullptr, surface);
-  EXPECT_TRUE(surface->HasPendingFrame());
-  EXPECT_FALSE(surface->HasActiveFrame());
-
-  // Resolve the dependencies. The frame in parent's surface must become active.
-  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
-                                         MakeCompositorFrame());
-  EXPECT_FALSE(surface->HasPendingFrame());
-  EXPECT_TRUE(surface->HasActiveFrame());
-
-  // Both latency info elements must exist in the now-activated frame of the
-  // new surface.
-  std::vector<ui::LatencyInfo> info_list;
-  surface->TakeLatencyInfo(&info_list);
-  EXPECT_EQ(2u, info_list.size());
-
-  ui::LatencyInfo aggregated_latency_info = info_list[0];
-  aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
-
-  // Two components are the original ones, and the third one is
-  // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
-  // submit.
-  EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
-
-  ui::LatencyInfo::LatencyComponent comp1;
-  EXPECT_TRUE(
-      aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
-  EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
-  EXPECT_TRUE(
-      aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
-  EXPECT_TRUE(aggregated_latency_info.FindLatency(
-      ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
-}
-
-TEST_F(CompositorFrameSinkSupportTest, PassesOnBeginFrameAcks) {
-  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
-
-  // Request BeginFrames.
-  display_support().SetNeedsBeginFrame(true);
-
-  // Issue a BeginFrame.
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  begin_frame_source()->TestOnBeginFrame(args);
-
-  // Check that the support forwards a BeginFrameDidNotSwap ack to the
-  // BeginFrameSource.
-  BeginFrameAck ack(0, 1, 1, false);
-  display_support().BeginFrameDidNotSwap(ack);
-  EXPECT_EQ(ack, begin_frame_source()->LastAckForObserver(&display_support()));
-
-  // Issue another BeginFrame.
-  args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2);
-  begin_frame_source()->TestOnBeginFrame(args);
-
-  // Check that the support forwards the BeginFrameAck attached
-  // to a CompositorFrame to the BeginFrameSource.
-  BeginFrameAck ack2(0, 2, 2, true);
-  CompositorFrame frame = MakeCompositorFrame();
-  frame.metadata.begin_frame_ack = ack2;
-  display_support().SubmitCompositorFrame(display_id.local_surface_id(),
-                                          std::move(frame));
-  EXPECT_EQ(ack2, begin_frame_source()->LastAckForObserver(&display_support()));
-}
+// Tests doing an EvictFrame before shutting down the factory.
+TEST_F(CompositorFrameSinkSupportTest, EvictFrame) {
+  MockCompositorFrameSinkSupportClient mock_client;
+  std::unique_ptr<CompositorFrameSinkSupport> support =
+      CompositorFrameSinkSupport::Create(
+          &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
+          kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
+  LocalSurfaceId local_surface_id(7, kArbitraryToken);
+  SurfaceId id(kAnotherArbitraryFrameSinkId, local_surface_id);
 
-// Checks that resources and ack are sent together if possible.
-TEST_F(CompositorFrameSinkSupportTest, ReturnResourcesWithAck) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
   TransferableResource resource;
-  resource.id = 1234;
-  parent_support().SubmitCompositorFrame(
-      parent_id.local_surface_id(),
-      MakeCompositorFrameWithResources(empty_surface_ids(), {resource}));
+  resource.id = 1;
+  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.resource_list.push_back(resource);
+  support->SubmitCompositorFrame(local_surface_id, std::move(frame));
+  EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
+  local_surface_id_ = LocalSurfaceId();
+
+  ReturnedResourceArray returned_resources = {resource.ToReturnedResource()};
+  EXPECT_TRUE(manager_.GetSurfaceForId(id));
+  EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources))
+      .Times(1);
+  support->EvictFrame();
+  EXPECT_FALSE(manager_.GetSurfaceForId(id));
+}
+
+// Tests doing an EvictSurface which has unregistered dependency.
+TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceDependencyUnRegistered) {
+  MockCompositorFrameSinkSupportClient mock_client;
+  std::unique_ptr<CompositorFrameSinkSupport> support =
+      CompositorFrameSinkSupport::Create(
+          &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
+          kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
+  LocalSurfaceId local_surface_id(7, kArbitraryToken);
+
+  TransferableResource resource;
+  resource.id = 1;
+  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.resource_list.push_back(resource);
+  support->SubmitCompositorFrame(local_surface_id, std::move(frame));
+  EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
+  local_surface_id_ = LocalSurfaceId();
+
+  SurfaceId surface_id(kAnotherArbitraryFrameSinkId, local_surface_id);
+  Surface* surface = manager_.GetSurfaceForId(surface_id);
+  surface->AddDestructionDependency(
+      SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
+
+  ReturnedResourceArray returned_resource = {resource.ToReturnedResource()};
+
+  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
+  EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resource))
+      .Times(1);
+  support->EvictFrame();
+  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
+}
+
+// Tests doing an EvictSurface which has registered dependency.
+TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceDependencyRegistered) {
+  MockCompositorFrameSinkSupportClient mock_client;
+  std::unique_ptr<CompositorFrameSinkSupport> support =
+      CompositorFrameSinkSupport::Create(
+          &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
+          kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
+  LocalSurfaceId local_surface_id(7, kArbitraryToken);
+
+  TransferableResource resource;
+  resource.id = 1;
+  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.resource_list.push_back(resource);
+  uint32_t execute_count = 0;
+  support->SubmitCompositorFrame(local_surface_id, std::move(frame));
+  EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
+  local_surface_id_ = LocalSurfaceId();
+
+  manager_.RegisterFrameSinkId(kYetAnotherArbitraryFrameSinkId);
+
+  SurfaceId surface_id(kAnotherArbitraryFrameSinkId, local_surface_id);
+  Surface* surface = manager_.GetSurfaceForId(surface_id);
+  surface->AddDestructionDependency(
+      SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
+
   ReturnedResourceArray returned_resources;
-  TransferableResource::ReturnResources({resource}, &returned_resources);
-  EXPECT_CALL(support_client_, ReclaimResources(_)).Times(0);
-  EXPECT_CALL(support_client_,
-              DidReceiveCompositorFrameAck(Eq(returned_resources)));
-  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
-                                         MakeCompositorFrame());
+  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
+  support->EvictFrame();
+  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
+  EXPECT_EQ(0u, execute_count);
+
+  returned_resources.push_back(resource.ToReturnedResource());
+  EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources))
+      .Times(1);
+  manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
+  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
 }
 
-// Verifies that if a surface is marked destroyed and a new frame arrives for
-// it, it will be recovered.
-TEST_F(CompositorFrameSinkSupportTest, SurfaceResurrection) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3);
+TEST_F(CompositorFrameSinkSupportTest, DestroySequence) {
+  LocalSurfaceId local_surface_id2(5, kArbitraryToken);
+  std::unique_ptr<CompositorFrameSinkSupport> support2 =
+      CompositorFrameSinkSupport::Create(
+          &fake_support_client_, &manager_, kYetAnotherArbitraryFrameSinkId,
+          kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
+  SurfaceId id2(kYetAnotherArbitraryFrameSinkId, local_surface_id2);
+  support2->SubmitCompositorFrame(local_surface_id2, MakeCompositorFrame());
 
-  // Create the child surface by submitting a frame to it.
-  EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id));
-  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
-                                         MakeCompositorFrame());
+  // Check that waiting before the sequence is satisfied works.
+  manager_.GetSurfaceForId(id2)->AddDestructionDependency(
+      SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
+  support2->EvictFrame();
 
-  // Verify that the child surface is created.
-  Surface* surface = surface_manager().GetSurfaceForId(child_id);
-  EXPECT_NE(nullptr, surface);
+  DCHECK(manager_.GetSurfaceForId(id2));
+  manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
+  manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 6));
+  DCHECK(!manager_.GetSurfaceForId(id2));
 
-  // Add a reference from the parent to the child.
-  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
-                                         MakeCompositorFrame({child_id}));
-
-  // Attempt to destroy the child surface. The surface must still exist since
-  // the parent needs it but it will be marked as destroyed.
-  child_support1().EvictFrame();
-  surface = surface_manager().GetSurfaceForId(child_id);
-  EXPECT_NE(nullptr, surface);
-  EXPECT_TRUE(surface->destroyed());
-
-  // Child submits another frame to the same local surface id that is marked
-  // destroyed.
-  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
-                                         MakeCompositorFrame());
-
-  // Verify that the surface that was marked destroyed is recovered and is being
-  // used again.
-  Surface* surface2 = surface_manager().GetSurfaceForId(child_id);
-  EXPECT_EQ(surface, surface2);
-  EXPECT_FALSE(surface2->destroyed());
+  // Check that waiting after the sequence is satisfied works.
+  support2->SubmitCompositorFrame(local_surface_id2, MakeCompositorFrame());
+  DCHECK(manager_.GetSurfaceForId(id2));
+  manager_.GetSurfaceForId(id2)->AddDestructionDependency(
+      SurfaceSequence(kAnotherArbitraryFrameSinkId, 6));
+  support2->EvictFrame();
+  DCHECK(!manager_.GetSurfaceForId(id2));
 }
 
-// Verifies that if a LocalSurfaceId belonged to a surface that doesn't exist
-// anymore, it can still be reused for new surfaces.
-TEST_F(CompositorFrameSinkSupportTest, LocalSurfaceIdIsReusable) {
-  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3);
+// Tests that Surface ID namespace invalidation correctly allows
+// Sequences to be ignored.
+TEST_F(CompositorFrameSinkSupportTest, InvalidFrameSinkId) {
+  FrameSinkId frame_sink_id(1234, 5678);
 
-  // Submit the first frame. Creates the surface.
-  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
-                                         MakeCompositorFrame());
-  EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id));
+  LocalSurfaceId local_surface_id(5, kArbitraryToken);
+  SurfaceId id(support_->frame_sink_id(), local_surface_id);
+  support_->SubmitCompositorFrame(local_surface_id, MakeCompositorFrame());
 
-  // Add a reference from parent.
-  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
-                                         MakeCompositorFrame({child_id}));
+  manager_.RegisterFrameSinkId(frame_sink_id);
+  manager_.GetSurfaceForId(id)->AddDestructionDependency(
+      SurfaceSequence(frame_sink_id, 4));
 
-  // Remove the reference from parant. This allows us to destroy the surface.
-  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
-                                         MakeCompositorFrame());
+  support_->EvictFrame();
 
-  // Destroy the surface.
-  child_support1().EvictFrame();
-  EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id));
+  // Verify the dependency has prevented the surface from getting destroyed.
+  EXPECT_TRUE(manager_.GetSurfaceForId(id));
 
-  // Submit another frame with the same local surface id. This should work fine
-  // and a new surface must be created.
-  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
-                                         MakeCompositorFrame());
-  EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id));
+  manager_.InvalidateFrameSinkId(frame_sink_id);
+
+  // Verify that the invalidated namespace caused the unsatisfied sequence
+  // to be ignored.
+  EXPECT_FALSE(manager_.GetSurfaceForId(id));
 }
 
-// This test verifies that a crash does not occur if garbage collection is
-// triggered during surface dependency resolution. This test triggers garbage
-// collection during surface resolution, by causing an activation to remove
-// a surface subtree from the root. Both the old subtree and the new
-// activated subtree refer to the same dependency. The old subtree was activated
-// by deadline, and the new subtree was activated by a dependency finally
-// resolving.
-TEST_F(CompositorFrameSinkSupportTest, DependencyTrackingGarbageCollection) {
-  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
-
-  parent_support().SubmitCompositorFrame(
-      parent_id1.local_surface_id(),
-      MakeCompositorFrame({child_id}, empty_surface_ids()));
-  display_support().SubmitCompositorFrame(
-      display_id.local_surface_id(),
-      MakeCompositorFrame({parent_id1}, empty_surface_ids()));
-
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-
-  // Advance BeginFrames to trigger a deadline.
-  for (int i = 0; i < 3; ++i) {
-    begin_frame_source()->TestOnBeginFrame(args);
-    EXPECT_TRUE(dependency_tracker().has_deadline());
+TEST_F(CompositorFrameSinkSupportTest, DestroyCycle) {
+  LocalSurfaceId local_surface_id2(5, kArbitraryToken);
+  SurfaceId id2(kYetAnotherArbitraryFrameSinkId, local_surface_id2);
+  std::unique_ptr<CompositorFrameSinkSupport> support2 =
+      CompositorFrameSinkSupport::Create(
+          &fake_support_client_, &manager_, kYetAnotherArbitraryFrameSinkId,
+          kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
+  manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
+  // Give id2 a frame that references local_surface_id_.
+  {
+    std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
+    CompositorFrame frame = MakeCompositorFrame();
+    frame.render_pass_list.push_back(std::move(render_pass));
+    frame.metadata.referenced_surfaces.push_back(
+        SurfaceId(support_->frame_sink_id(), local_surface_id_));
+    support2->SubmitCompositorFrame(local_surface_id2, std::move(frame));
+    EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id2);
   }
-  begin_frame_source()->TestOnBeginFrame(args);
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-
-  EXPECT_TRUE(display_surface()->HasActiveFrame());
-  EXPECT_FALSE(display_surface()->HasPendingFrame());
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-
-  parent_support().SubmitCompositorFrame(
-      parent_id2.local_surface_id(),
-      MakeCompositorFrame({child_id}, empty_surface_ids()));
-  display_support().SubmitCompositorFrame(
-      display_id.local_surface_id(),
-      MakeCompositorFrame({parent_id2}, empty_surface_ids()));
-
-  // The display surface now has two CompositorFrames. One that is pending,
-  // indirectly blocked on child_id and one that is active, also indirectly
-  // referring to child_id, but activated due to the deadline above.
-  EXPECT_TRUE(display_surface()->HasActiveFrame());
-  EXPECT_TRUE(display_surface()->HasPendingFrame());
-
-  // Submitting a CompositorFrame will trigger garbage collection of the
-  // |parent_id1| subtree. This should not crash.
-  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
-                                         MakeCompositorFrame());
-}
-
-// This test verifies that a crash does not occur if garbage collection is
-// triggered when a deadline forces frame activation. This test triggers garbage
-// collection during deadline activation by causing the activation of a display
-// frame to replace a previously activated display frame that was referring to
-// a now-unreachable surface subtree. That subtree gets garbage collected during
-// deadline activation. SurfaceDependencyTracker is also tracking a surface
-// from that subtree due to an unresolved dependency. This test verifies that
-// this dependency resolution does not crash.
-TEST_F(CompositorFrameSinkSupportTest, GarbageCollectionOnDeadline) {
-  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
-  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
-
-  // |parent_id1| is blocked on |child_id|.
-  parent_support().SubmitCompositorFrame(
-      parent_id1.local_surface_id(),
-      MakeCompositorFrame({child_id}, empty_surface_ids()));
-
-  display_support().SubmitCompositorFrame(display_id.local_surface_id(),
-                                          MakeCompositorFrame({parent_id1}));
-
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_TRUE(display_surface()->HasPendingFrame());
-  EXPECT_FALSE(display_surface()->HasActiveFrame());
-
-  // Advance BeginFrames to trigger a deadline. This activates the
-  // CompositorFrame submitted above.
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  for (int i = 0; i < 3; ++i) {
-    begin_frame_source()->TestOnBeginFrame(args);
-    EXPECT_TRUE(dependency_tracker().has_deadline());
+  manager_.GetSurfaceForId(id2)->AddDestructionDependency(
+      SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
+  support2->EvictFrame();
+  // Give local_surface_id_ a frame that references id2.
+  {
+    std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
+    CompositorFrame frame = MakeCompositorFrame();
+    frame.render_pass_list.push_back(std::move(render_pass));
+    frame.metadata.referenced_surfaces.push_back(id2);
+    support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
   }
-  begin_frame_source()->TestOnBeginFrame(args);
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(display_surface()->HasPendingFrame());
-  EXPECT_TRUE(display_surface()->HasActiveFrame());
+  support_->EvictFrame();
+  EXPECT_TRUE(manager_.GetSurfaceForId(id2));
+  // local_surface_id_ should be retained by reference from id2.
+  EXPECT_TRUE(manager_.GetSurfaceForId(
+      SurfaceId(support_->frame_sink_id(), local_surface_id_)));
 
-  // By submitting a display CompositorFrame, and replacing the parent's
-  // CompositorFrame with another surface ID, parent_id1 becomes unreachable and
-  // a candidate for garbage collection.
-  display_support().SubmitCompositorFrame(
-      display_id.local_surface_id(),
-      MakeCompositorFrame({parent_id2}, empty_surface_ids()));
+  // Satisfy last destruction dependency for id2.
+  manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
 
-  // Now |parent_id1| is only kept alive by the active |display_id| frame.
-  parent_support().SubmitCompositorFrame(
-      parent_id2.local_surface_id(),
-      MakeCompositorFrame({child_id}, empty_surface_ids()));
+  // id2 and local_surface_id_ are in a reference cycle that has no surface
+  // sequences holding on to it, so they should be destroyed.
+  EXPECT_TRUE(!manager_.GetSurfaceForId(id2));
+  EXPECT_TRUE(!manager_.GetSurfaceForId(
+      SurfaceId(support_->frame_sink_id(), local_surface_id_)));
 
-  // SurfaceDependencyTracker should now be tracking |display_id|, |parent_id1|
-  // and |parent_id2|. By activating the pending |display_id| frame by deadline,
-  // |parent_id1| becomes unreachable and is garbage collected while
-  // SurfaceDependencyTracker is in the process of activating surfaces. This
-  // should not cause a crash or use-after-free.
-  for (int i = 0; i < 3; ++i) {
-    begin_frame_source()->TestOnBeginFrame(args);
-    EXPECT_TRUE(dependency_tracker().has_deadline());
+  local_surface_id_ = LocalSurfaceId();
+}
+
+void CopyRequestTestCallback(bool* called,
+                             std::unique_ptr<CopyOutputResult> result) {
+  *called = true;
+}
+
+TEST_F(CompositorFrameSinkSupportTest, DuplicateCopyRequest) {
+  {
+    std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
+    CompositorFrame frame = MakeCompositorFrame();
+    frame.render_pass_list.push_back(std::move(render_pass));
+    frame.metadata.referenced_surfaces.push_back(
+        SurfaceId(support_->frame_sink_id(), local_surface_id_));
+    support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
+    EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id_);
   }
-  begin_frame_source()->TestOnBeginFrame(args);
-  EXPECT_FALSE(dependency_tracker().has_deadline());
+
+  bool called1 = false;
+  std::unique_ptr<CopyOutputRequest> request;
+  request = CopyOutputRequest::CreateRequest(
+      base::Bind(&CopyRequestTestCallback, &called1));
+  request->set_source(kArbitrarySourceId1);
+
+  support_->RequestCopyOfSurface(std::move(request));
+  EXPECT_FALSE(called1);
+
+  bool called2 = false;
+  request = CopyOutputRequest::CreateRequest(
+      base::Bind(&CopyRequestTestCallback, &called2));
+  request->set_source(kArbitrarySourceId2);
+
+  support_->RequestCopyOfSurface(std::move(request));
+  // Callbacks have different sources so neither should be called.
+  EXPECT_FALSE(called1);
+  EXPECT_FALSE(called2);
+
+  bool called3 = false;
+  request = CopyOutputRequest::CreateRequest(
+      base::Bind(&CopyRequestTestCallback, &called3));
+  request->set_source(kArbitrarySourceId1);
+
+  support_->RequestCopyOfSurface(std::move(request));
+  // Two callbacks are from source1, so the first should be called.
+  EXPECT_TRUE(called1);
+  EXPECT_FALSE(called2);
+  EXPECT_FALSE(called3);
+
+  support_->EvictFrame();
+  local_surface_id_ = LocalSurfaceId();
+  EXPECT_TRUE(called1);
+  EXPECT_TRUE(called2);
+  EXPECT_TRUE(called3);
 }
 
-// This test verifies that a CompositorFrame will only blocked on embedded
-// surfaces but not on other retained surface IDs in the CompositorFrame.
-TEST_F(CompositorFrameSinkSupportTest, OnlyBlockOnEmbeddedSurfaces) {
-  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+// Check whether the SurfaceInfo object is created and populated correctly
+// after the frame submission.
+TEST_F(CompositorFrameSinkSupportTest, SurfaceInfo) {
+  CompositorFrame frame = MakeCompositorFrame();
 
-  // Submitting a CompositorFrame with |parent_id2| so that the display
-  // CompositorFrame can hold a reference to it.
-  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
-                                         MakeCompositorFrame());
+  auto render_pass = RenderPass::Create();
+  render_pass->SetNew(1, gfx::Rect(5, 6), gfx::Rect(), gfx::Transform());
+  frame.render_pass_list.push_back(std::move(render_pass));
 
-  display_support().SubmitCompositorFrame(
-      display_id.local_surface_id(),
-      MakeCompositorFrame({parent_id1}, {parent_id2}));
+  render_pass = RenderPass::Create();
+  render_pass->SetNew(2, gfx::Rect(7, 8), gfx::Rect(), gfx::Transform());
+  frame.render_pass_list.push_back(std::move(render_pass));
 
-  EXPECT_TRUE(display_surface()->HasPendingFrame());
-  EXPECT_FALSE(display_surface()->HasActiveFrame());
-  EXPECT_TRUE(dependency_tracker().has_deadline());
+  frame.metadata.device_scale_factor = 2.5f;
 
-  // Verify that the display CompositorFrame will only block on |parent_id1| but
-  // not |parent_id2|.
-  EXPECT_THAT(display_surface()->blocking_surfaces(),
-              UnorderedElementsAre(parent_id1));
-  // Verify that the display surface holds no references while its
-  // CompositorFrame is pending.
-  EXPECT_THAT(GetChildReferences(display_id), IsEmpty());
-
-  // Submitting a CompositorFrame with |parent_id1| should unblock the display
-  // CompositorFrame.
-  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
-                                         MakeCompositorFrame());
-
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(display_surface()->HasPendingFrame());
-  EXPECT_TRUE(display_surface()->HasActiveFrame());
-  EXPECT_THAT(display_surface()->blocking_surfaces(), IsEmpty());
+  support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
+  SurfaceId expected_surface_id(support_->frame_sink_id(), local_surface_id_);
+  EXPECT_EQ(expected_surface_id, last_surface_info_.id());
+  EXPECT_EQ(2.5f, last_surface_info_.device_scale_factor());
+  EXPECT_EQ(gfx::Size(7, 8), last_surface_info_.size_in_pixels());
 }
 
-// This test verifies that a late arriving CompositorFrame activates immediately
-// and does not trigger a new deadline.
-TEST_F(CompositorFrameSinkSupportTest, LateArrivingDependency) {
-  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+}  // namespace
 
-  display_support().SubmitCompositorFrame(
-      display_id.local_surface_id(),
-      MakeCompositorFrame({parent_id1}, empty_surface_ids()));
-
-  EXPECT_TRUE(display_surface()->HasPendingFrame());
-  EXPECT_FALSE(display_surface()->HasActiveFrame());
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-
-  // Advance BeginFrames to trigger a deadline. This activates the
-  // CompositorFrame submitted above.
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  for (int i = 0; i < 3; ++i) {
-    begin_frame_source()->TestOnBeginFrame(args);
-    EXPECT_TRUE(dependency_tracker().has_deadline());
-  }
-  begin_frame_source()->TestOnBeginFrame(args);
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(display_surface()->HasPendingFrame());
-  EXPECT_TRUE(display_surface()->HasActiveFrame());
-
-  // A late arriving CompositorFrame should activate immediately without
-  // scheduling a deadline and without waiting for dependencies to resolve.
-  parent_support().SubmitCompositorFrame(
-      parent_id1.local_surface_id(),
-      MakeCompositorFrame({child_id1}, empty_surface_ids()));
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-}
-
-// This test verifies that CompositorFrames submitted to a surface referenced
-// by a parent CompositorFrame as a fallback will be rejected and ACK'ed
-// immediately.
-TEST_F(CompositorFrameSinkSupportTest, FallbackSurfacesClosed) {
-  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
-  // This is the fallback child surface that the parent holds a reference to.
-  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
-  // This is the primary child surface that the parent wants to block on.
-  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 2);
-
-  // child_support1 submits a CompositorFrame without any dependencies.
-  // DidReceiveCompositorFrameAck should call on immediate activation.
-  // However, resources will not be returned because this frame is a candidate
-  // for display.
-  TransferableResource resource =
-      MakeResource(1337 /* id */, ALPHA_8 /* format */, 1234 /* filter */,
-                   gfx::Size(1234, 5678));
-  ReturnedResourceArray returned_resources;
-  TransferableResource::ReturnResources({resource}, &returned_resources);
-
-  EXPECT_CALL(support_client_,
-              DidReceiveCompositorFrameAck(Eq(ReturnedResourceArray())));
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrameWithResources(empty_surface_ids(), {resource}));
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // The parent is blocked on |child_id2| and references |child_id1|. The
-  // surface corresponding to |child_id1| will not accept new CompositorFrames
-  // while the parent CompositorFrame is blocked.
-  parent_support().SubmitCompositorFrame(
-      parent_id1.local_surface_id(),
-      MakeCompositorFrame({child_id2}, {child_id1}));
-  EXPECT_TRUE(dependency_tracker().has_deadline());
-  EXPECT_TRUE(parent_surface()->HasPendingFrame());
-  EXPECT_FALSE(parent_surface()->HasActiveFrame());
-
-  // Resources will be returned immediately because |child_id1|'s surface is
-  // closed.
-  TransferableResource resource2 =
-      MakeResource(1246 /* id */, ALPHA_8 /* format */, 1357 /* filter */,
-                   gfx::Size(8765, 4321));
-  ReturnedResourceArray returned_resources2;
-  TransferableResource::ReturnResources({resource2}, &returned_resources2);
-  EXPECT_CALL(support_client_,
-              DidReceiveCompositorFrameAck(Eq(returned_resources2)));
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrameWithResources(empty_surface_ids(), {resource2}));
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-
-  // Advance BeginFrames to trigger a deadline. This activates the
-  // CompositorFrame submitted to the parent.
-  BeginFrameArgs args =
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
-  for (int i = 0; i < 3; ++i) {
-    begin_frame_source()->TestOnBeginFrame(args);
-    EXPECT_TRUE(dependency_tracker().has_deadline());
-  }
-  begin_frame_source()->TestOnBeginFrame(args);
-  EXPECT_FALSE(dependency_tracker().has_deadline());
-  EXPECT_FALSE(parent_surface()->HasPendingFrame());
-  EXPECT_TRUE(parent_surface()->HasActiveFrame());
-
-  // Resources will be returned immediately because |child_id1|'s surface is
-  // closed forever.
-  EXPECT_CALL(support_client_,
-              DidReceiveCompositorFrameAck(Eq(returned_resources2)));
-  child_support1().SubmitCompositorFrame(
-      child_id1.local_surface_id(),
-      MakeCompositorFrameWithResources(empty_surface_ids(), {resource2}));
-  testing::Mock::VerifyAndClearExpectations(&support_client_);
-}
+}  // namespace test
 
 }  // namespace cc
diff --git a/cc/surfaces/direct_compositor_frame_sink.h b/cc/surfaces/direct_compositor_frame_sink.h
index 98d4cecd..06ac4c3bb 100644
--- a/cc/surfaces/direct_compositor_frame_sink.h
+++ b/cc/surfaces/direct_compositor_frame_sink.h
@@ -13,8 +13,6 @@
 #include "cc/surfaces/compositor_frame_sink_support_client.h"
 #include "cc/surfaces/display_client.h"
 #include "cc/surfaces/local_surface_id_allocator.h"
-#include "cc/surfaces/surface_factory.h"
-#include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surfaces_export.h"
 
 namespace cc {
diff --git a/cc/surfaces/frame_sink_manager.cc b/cc/surfaces/frame_sink_manager.cc
index 7e9095c..c16a921 100644
--- a/cc/surfaces/frame_sink_manager.cc
+++ b/cc/surfaces/frame_sink_manager.cc
@@ -9,7 +9,6 @@
 
 #include "base/logging.h"
 #include "cc/surfaces/frame_sink_manager_client.h"
-#include "cc/surfaces/surface_factory_client.h"
 
 #if DCHECK_IS_ON()
 #include <sstream>
@@ -28,8 +27,8 @@
 FrameSinkManager::FrameSinkManager() {}
 
 FrameSinkManager::~FrameSinkManager() {
-  // All surface factory clients should be unregistered prior to SurfaceManager
-  // destruction.
+  // All CompositorFrameSinks should be unregistered prior to
+  // SurfaceManager destruction.
   DCHECK_EQ(clients_.size(), 0u);
   DCHECK_EQ(registered_sources_.size(), 0u);
 }
@@ -207,7 +206,7 @@
   }
   DCHECK(found_child);
 
-  // The SurfaceFactoryClient and hierarchy can be registered/unregistered
+  // The CompositorFrameSinkSupport and hierarchy can be registered/unregistered
   // in either order, so empty frame_sink_source_map entries need to be
   // checked when removing either clients or relationships.
   if (!iter->second.has_children() && !clients_.count(parent_frame_sink_id) &&
diff --git a/cc/surfaces/frame_sink_manager.h b/cc/surfaces/frame_sink_manager.h
index b48642f2..0d54a8e3 100644
--- a/cc/surfaces/frame_sink_manager.h
+++ b/cc/surfaces/frame_sink_manager.h
@@ -21,7 +21,7 @@
 class FrameSinkManagerClient;
 
 namespace test {
-class CompositorFrameSinkSupportTest;
+class SurfaceSynchronizationTest;
 }
 
 class CC_SURFACES_EXPORT FrameSinkManager {
@@ -35,8 +35,8 @@
   // possibly because a renderer process has crashed.
   void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id);
 
-  // SurfaceFactoryClient, hierarchy, and BeginFrameSource can be registered
-  // and unregistered in any order with respect to each other.
+  // CompositorFrameSinkSupport, hierarchy, and BeginFrameSource can be
+  // registered and unregistered in any order with respect to each other.
   //
   // This happens in practice, e.g. the relationship to between ui::Compositor /
   // DelegatedFrameHost is known before ui::Compositor has a surface/client).
@@ -73,7 +73,7 @@
   }
 
  private:
-  friend class test::CompositorFrameSinkSupportTest;
+  friend class test::SurfaceSynchronizationTest;
 
   void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id,
                                          BeginFrameSource* source);
@@ -90,8 +90,9 @@
   // considered satisfied.
   std::unordered_set<FrameSinkId, FrameSinkIdHash> valid_frame_sink_ids_;
 
-  // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient
-  // pointers guaranteed alive by callers until unregistered.
+  // Begin frame source routing. Both BeginFrameSource and
+  // CompositorFrameSinkSupport pointers guaranteed alive by callers until
+  // unregistered.
   struct FrameSinkSourceMapping {
     FrameSinkSourceMapping();
     FrameSinkSourceMapping(const FrameSinkSourceMapping& other);
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index eed066f..3db1e82 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -12,10 +12,9 @@
 #include "base/stl_util.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/copy_output_request.h"
+#include "cc/surfaces/compositor_frame_sink_support.h"
 #include "cc/surfaces/local_surface_id_allocator.h"
 #include "cc/surfaces/pending_frame_observer.h"
-#include "cc/surfaces/surface_factory.h"
-#include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surface_manager.h"
 #include "cc/surfaces/surface_resource_holder_client.h"
 
@@ -25,10 +24,12 @@
 // completely damaged the first time they're drawn from.
 static const int kFrameIndexStart = 2;
 
-Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory)
+Surface::Surface(
+    const SurfaceId& id,
+    base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support)
     : surface_id_(id),
       previous_frame_surface_id_(id),
-      factory_(factory),
+      compositor_frame_sink_support_(std::move(compositor_frame_sink_support)),
       frame_index_(kFrameIndexStart),
       destroyed_(false) {}
 
@@ -57,13 +58,13 @@
 }
 
 void Surface::QueueFrame(CompositorFrame frame,
-                         const DrawCallback& callback,
+                         const base::Closure& callback,
                          const WillDrawCallback& will_draw_callback) {
   if (closed_) {
-    if (factory_ && factory_->resource_holder_client()) {
+    if (compositor_frame_sink_support_) {
       ReturnedResourceArray resources;
       TransferableResource::ReturnResources(frame.resource_list, &resources);
-      factory_->resource_holder_client()->ReturnResources(resources);
+      compositor_frame_sink_support_->ReturnResources(resources);
     }
     callback.Run();
     return;
@@ -79,7 +80,7 @@
 
   // Receive and track the resources referenced from the CompositorFrame
   // regardless of whether it's pending or active.
-  factory_->ReceiveFromChild(frame.resource_list);
+  compositor_frame_sink_support_->ReceiveFromChild(frame.resource_list);
 
   bool is_pending_frame = !blocking_surfaces_.empty();
 
@@ -98,7 +99,9 @@
       bool is_fallback_surface =
           frame_sink_ids_for_dependencies.count(surface_id.frame_sink_id()) > 0;
       if (is_fallback_surface) {
-        Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
+        Surface* surface =
+            compositor_frame_sink_support_->surface_manager()->GetSurfaceForId(
+                surface_id);
         DCHECK(surface);
         surface->Close();
       }
@@ -107,7 +110,8 @@
         FrameData(std::move(frame), callback, will_draw_callback);
     // Ask the surface manager to inform |this| when its dependencies are
     // resolved.
-    factory_->manager()->RequestSurfaceResolution(this);
+    compositor_frame_sink_support_->surface_manager()->RequestSurfaceResolution(
+        this);
   } else {
     // If there are no blockers, then immediately activate the frame.
     ActivateFrame(FrameData(std::move(frame), callback, will_draw_callback));
@@ -175,7 +179,7 @@
 }
 
 Surface::FrameData::FrameData(CompositorFrame&& frame,
-                              const DrawCallback& draw_callback,
+                              const base::Closure& draw_callback,
                               const WillDrawCallback& will_draw_callback)
     : frame(std::move(frame)),
       draw_callback(draw_callback),
@@ -197,7 +201,7 @@
 // deadline has hit and the frame was forcibly activated by the display
 // compositor.
 void Surface::ActivateFrame(FrameData frame_data) {
-  DCHECK(factory_);
+  DCHECK(compositor_frame_sink_support_);
 
   // Save root pass copy requests.
   std::vector<std::unique_ptr<CopyOutputRequest>> old_copy_requests;
@@ -231,7 +235,8 @@
                                      const CompositorFrame& current_frame) {
   // If there is no SurfaceDependencyTracker installed then the |current_frame|
   // does not block on anything.
-  if (!factory_->manager()->dependency_tracker()) {
+  if (!compositor_frame_sink_support_->surface_manager()
+           ->dependency_tracker()) {
     blocking_surfaces_.clear();
     return;
   }
@@ -240,7 +245,9 @@
 
   for (const SurfaceId& surface_id :
        current_frame.metadata.activation_dependencies) {
-    Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
+    Surface* surface =
+        compositor_frame_sink_support_->surface_manager()->GetSurfaceForId(
+            surface_id);
     // If a referenced surface does not have a corresponding active frame in the
     // display compositor, then it blocks this frame.
     if (!surface || !surface->HasActiveFrame())
@@ -308,8 +315,8 @@
 
 void Surface::RunDrawCallback() {
   if (active_frame_data_ && !active_frame_data_->draw_callback.is_null()) {
-    DrawCallback callback = active_frame_data_->draw_callback;
-    active_frame_data_->draw_callback = DrawCallback();
+    base::Closure callback = active_frame_data_->draw_callback;
+    active_frame_data_->draw_callback = base::Closure();
     callback.Run();
   }
 }
@@ -338,7 +345,7 @@
 
 void Surface::UnrefFrameResourcesAndRunDrawCallback(
     base::Optional<FrameData> frame_data) {
-  if (!frame_data || !factory_)
+  if (!frame_data || !compositor_frame_sink_support_)
     return;
 
   ReturnedResourceArray resources;
@@ -347,7 +354,7 @@
   // No point in returning same sync token to sender.
   for (auto& resource : resources)
     resource.sync_token.Clear();
-  factory_->UnrefResources(resources);
+  compositor_frame_sink_support_->UnrefResources(resources);
 
   if (!frame_data->draw_callback.is_null())
     frame_data->draw_callback.Run();
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h
index 63371d6..08addef 100644
--- a/cc/surfaces/surface.h
+++ b/cc/surfaces/surface.h
@@ -19,9 +19,9 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "cc/output/copy_output_request.h"
+#include "cc/surfaces/compositor_frame_sink_support.h"
 #include "cc/surfaces/frame_sink_id.h"
 #include "cc/surfaces/pending_frame_observer.h"
-#include "cc/surfaces/surface_factory.h"
 #include "cc/surfaces/surface_id.h"
 #include "cc/surfaces/surface_sequence.h"
 #include "cc/surfaces/surfaces_export.h"
@@ -35,14 +35,15 @@
 
 class CompositorFrame;
 class CopyOutputRequest;
-class SurfaceFactory;
 
 class CC_SURFACES_EXPORT Surface {
  public:
-  using DrawCallback = SurfaceFactory::DrawCallback;
-  using WillDrawCallback = SurfaceFactory::WillDrawCallback;
+  using WillDrawCallback =
+      base::RepeatingCallback<void(const LocalSurfaceId&, const gfx::Rect&)>;
 
-  Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory);
+  Surface(
+      const SurfaceId& id,
+      base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support);
   ~Surface();
 
   const SurfaceId& surface_id() const { return surface_id_; }
@@ -58,7 +59,7 @@
   // |will_draw_callback| is called when |surface| is scheduled for a draw and
   // there is visible damage.
   void QueueFrame(CompositorFrame frame,
-                  const DrawCallback& draw_callback,
+                  const base::Closure& draw_callback,
                   const WillDrawCallback& will_draw_callback);
   void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> copy_request);
 
@@ -93,7 +94,9 @@
   void RunDrawCallback();
   void RunWillDrawCallback(const gfx::Rect& damage_rect);
 
-  base::WeakPtr<SurfaceFactory> factory() { return factory_; }
+  base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support() {
+    return compositor_frame_sink_support_;
+  }
 
   // Add a SurfaceSequence that must be satisfied before the Surface is
   // destroyed.
@@ -127,13 +130,13 @@
  private:
   struct FrameData {
     FrameData(CompositorFrame&& frame,
-              const DrawCallback& draw_callback,
+              const base::Closure& draw_callback,
               const WillDrawCallback& will_draw_callback);
     FrameData(FrameData&& other);
     ~FrameData();
     FrameData& operator=(FrameData&& other);
     CompositorFrame frame;
-    DrawCallback draw_callback;
+    base::Closure draw_callback;
     WillDrawCallback will_draw_callback;
   };
 
@@ -159,7 +162,7 @@
 
   const SurfaceId surface_id_;
   SurfaceId previous_frame_surface_id_;
-  base::WeakPtr<SurfaceFactory> factory_;
+  base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support_;
 
   base::Optional<FrameData> pending_frame_data_;
   base::Optional<FrameData> active_frame_data_;
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index b9a679f..93530ff6 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -25,6 +25,7 @@
 #include "cc/quads/surface_draw_quad.h"
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/resources/resource_provider.h"
+#include "cc/surfaces/compositor_frame_sink_support.h"
 #include "cc/surfaces/surface.h"
 #include "cc/surfaces/surface_manager.h"
 #include "cc/trees/blocking_task_runner.h"
@@ -120,11 +121,12 @@
   return out_clip;
 }
 
-static void UnrefHelper(base::WeakPtr<SurfaceFactory> surface_factory,
-                        const ReturnedResourceArray& resources,
-                        BlockingTaskRunner* main_thread_task_runner) {
-  if (surface_factory)
-    surface_factory->UnrefResources(resources);
+static void UnrefHelper(
+    base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support,
+    const ReturnedResourceArray& resources,
+    BlockingTaskRunner* main_thread_task_runner) {
+  if (compositor_frame_sink_support)
+    compositor_frame_sink_support->UnrefResources(resources);
 }
 
 int SurfaceAggregator::RemapPassId(int surface_local_pass_id,
@@ -145,11 +147,12 @@
 int SurfaceAggregator::ChildIdForSurface(Surface* surface) {
   auto it = surface_id_to_resource_child_id_.find(surface->surface_id());
   if (it == surface_id_to_resource_child_id_.end()) {
-    int child_id =
-        provider_->CreateChild(base::Bind(&UnrefHelper, surface->factory()));
-    if (surface->factory()) {
+    int child_id = provider_->CreateChild(
+        base::Bind(&UnrefHelper, surface->compositor_frame_sink_support()));
+    if (surface->compositor_frame_sink_support()) {
       provider_->SetChildNeedsSyncTokens(
-          child_id, surface->factory()->needs_sync_points());
+          child_id,
+          surface->compositor_frame_sink_support()->needs_sync_points());
     }
     surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
     return child_id;
@@ -609,8 +612,9 @@
   // TODO(jbauman): hack for unit tests that don't set up rp
   if (provider_) {
     child_id = ChildIdForSurface(surface);
-    if (surface->factory())
-      surface->factory()->RefResources(frame.resource_list);
+    if (surface->compositor_frame_sink_support())
+      surface->compositor_frame_sink_support()->RefResources(
+          frame.resource_list);
     provider_->ReceiveFromChild(child_id, frame.resource_list);
   }
   CHECK(debug_weak_this.get());
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc
deleted file mode 100644
index e4fd41e7..0000000
--- a/cc/surfaces/surface_factory.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/surfaces/surface_factory.h"
-
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_factory_client.h"
-#include "cc/surfaces/surface_info.h"
-#include "cc/surfaces/surface_manager.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace cc {
-SurfaceFactory::SurfaceFactory(
-    const FrameSinkId& frame_sink_id,
-    SurfaceManager* manager,
-    SurfaceFactoryClient* client,
-    SurfaceResourceHolderClient* resource_holder_client)
-    : frame_sink_id_(frame_sink_id),
-      manager_(manager),
-      client_(client),
-      resource_holder_client_(resource_holder_client),
-      holder_(resource_holder_client),
-      needs_sync_points_(true),
-      weak_factory_(this) {}
-
-SurfaceFactory::~SurfaceFactory() {
-  // This is to prevent troubles when a factory that resides in a client is
-  // being destroyed. In such cases, the factory might attempt to return
-  // resources to the client while it's in the middle of destruction and this
-  // could cause a crash or some unexpected behaviour.
-  DCHECK(!current_surface_) << "Please call EvictSurface before destruction";
-}
-
-void SurfaceFactory::EvictSurface() {
-  if (!current_surface_)
-    return;
-  Destroy(std::move(current_surface_));
-}
-
-void SurfaceFactory::SubmitCompositorFrame(
-    const LocalSurfaceId& local_surface_id,
-    CompositorFrame frame,
-    const DrawCallback& callback,
-    const WillDrawCallback& will_draw_callback) {
-  TRACE_EVENT0("cc", "SurfaceFactory::SubmitCompositorFrame");
-  DCHECK(local_surface_id.is_valid());
-  DCHECK(!frame.render_pass_list.empty());
-
-  if (!ui::LatencyInfo::Verify(frame.metadata.latency_info,
-                               "RenderWidgetHostImpl::OnSwapCompositorFrame")) {
-    std::vector<ui::LatencyInfo>().swap(frame.metadata.latency_info);
-  }
-
-  for (ui::LatencyInfo& latency : frame.metadata.latency_info) {
-    if (latency.latency_components().size() > 0) {
-      latency.AddLatencyNumber(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT,
-                               0, 0);
-    }
-  }
-
-  std::unique_ptr<Surface> surface;
-  bool create_new_surface =
-      (!current_surface_ ||
-       local_surface_id != current_surface_->surface_id().local_surface_id());
-  if (!create_new_surface) {
-    surface = std::move(current_surface_);
-  } else {
-    surface = Create(local_surface_id);
-  }
-  surface->QueueFrame(std::move(frame), callback, will_draw_callback);
-
-  if (current_surface_ && create_new_surface) {
-    surface->SetPreviousFrameSurface(current_surface_.get());
-    Destroy(std::move(current_surface_));
-  }
-  current_surface_ = std::move(surface);
-}
-
-void SurfaceFactory::RequestCopyOfSurface(
-    std::unique_ptr<CopyOutputRequest> copy_request) {
-  if (!current_surface_) {
-    copy_request->SendEmptyResult();
-    return;
-  }
-  DCHECK(current_surface_->factory().get() == this);
-  current_surface_->RequestCopyOfOutput(std::move(copy_request));
-  manager_->SurfaceModified(current_surface_->surface_id());
-}
-
-void SurfaceFactory::ReceiveFromChild(
-    const TransferableResourceArray& resources) {
-  holder_.ReceiveFromChild(resources);
-}
-
-void SurfaceFactory::RefResources(const TransferableResourceArray& resources) {
-  holder_.RefResources(resources);
-}
-
-void SurfaceFactory::UnrefResources(const ReturnedResourceArray& resources) {
-  holder_.UnrefResources(resources);
-}
-
-void SurfaceFactory::OnSurfaceActivated(Surface* surface) {
-  DCHECK(surface->HasActiveFrame());
-  if (!seen_first_frame_activation_) {
-    seen_first_frame_activation_ = true;
-
-    const CompositorFrame& frame = surface->GetActiveFrame();
-    gfx::Size frame_size = frame.render_pass_list.back()->output_rect.size();
-
-    // SurfaceCreated only applies for the first Surface activation. Thus,
-    // SurfaceFactory stops observing new activations after the first one.
-    manager_->SurfaceCreated(SurfaceInfo(
-        surface->surface_id(), frame.metadata.device_scale_factor, frame_size));
-  }
-  // Fire SurfaceCreated first so that a temporary reference is added before it
-  // is potentially transformed into a real reference by the client.
-  client_->ReferencedSurfacesChanged(surface->surface_id().local_surface_id(),
-                                     surface->active_referenced_surfaces());
-  if (!manager_->SurfaceModified(surface->surface_id())) {
-    TRACE_EVENT_INSTANT0("cc", "Damage not visible.", TRACE_EVENT_SCOPE_THREAD);
-    surface->RunDrawCallback();
-  }
-}
-
-void SurfaceFactory::OnSurfaceDependenciesChanged(
-    Surface* surface,
-    const base::flat_set<SurfaceId>& added_dependencies,
-    const base::flat_set<SurfaceId>& removed_dependencies) {}
-
-void SurfaceFactory::OnSurfaceDiscarded(Surface* surface) {}
-
-std::unique_ptr<Surface> SurfaceFactory::Create(
-    const LocalSurfaceId& local_surface_id) {
-  seen_first_frame_activation_ = false;
-  std::unique_ptr<Surface> surface =
-      manager_->CreateSurface(weak_factory_.GetWeakPtr(), local_surface_id);
-  surface->AddObserver(this);
-  return surface;
-}
-
-void SurfaceFactory::Destroy(std::unique_ptr<Surface> surface) {
-  surface->RemoveObserver(this);
-  manager_->DestroySurface(std::move(surface));
-}
-
-}  // namespace cc
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h
deleted file mode 100644
index 5c31eab..0000000
--- a/cc/surfaces/surface_factory.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_SURFACES_SURFACE_FACTORY_H_
-#define CC_SURFACES_SURFACE_FACTORY_H_
-
-#include <memory>
-#include <set>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/surfaces/pending_frame_observer.h"
-#include "cc/surfaces/surface_id.h"
-#include "cc/surfaces/surface_resource_holder.h"
-#include "cc/surfaces/surface_sequence.h"
-#include "cc/surfaces/surfaces_export.h"
-
-namespace cc {
-class CopyOutputRequest;
-class Surface;
-class SurfaceFactoryClient;
-class SurfaceManager;
-
-// This class is used for creating surfaces and submitting compositor frames to
-// them. Surfaces are created lazily each time SubmitCompositorFrame is
-// called with a local frame id that is different from the last call. Only one
-// surface is owned by this class at a time, and upon constructing a new surface
-// the old one will be destructed. Resources submitted to surfaces created by a
-// particular factory will be returned to that factory's client when they are no
-// longer being used. This is the only class most users of surfaces will need to
-// directly interact with.
-class CC_SURFACES_EXPORT SurfaceFactory : public PendingFrameObserver {
- public:
-  using DrawCallback = base::Callback<void()>;
-  using WillDrawCallback =
-      base::RepeatingCallback<void(const LocalSurfaceId&, const gfx::Rect&)>;
-
-  SurfaceFactory(const FrameSinkId& frame_sink_id,
-                 SurfaceManager* manager,
-                 SurfaceFactoryClient* client,
-                 SurfaceResourceHolderClient* resource_holder_client);
-  ~SurfaceFactory() override;
-
-  const FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
-
-  // Destroys the current surface. You need to call this method before the
-  // factory is destroyed, or when you would like to get rid of the surface as
-  // soon as possible (otherwise, the next time you call SubmitCompositorFrame
-  // the old surface will be dealt with).
-  void EvictSurface();
-
-  // Submits the frame to the current surface being managed by the factory if
-  // the local frame ids match, or creates a new surface with the given local
-  // frame id, destroys the old one, and submits the frame to this new surface.
-  // The frame can contain references to any surface, regardless of which
-  // factory owns it. The callback is called the first time this frame is used
-  // to draw, or if the frame is discarded.
-  void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
-                             CompositorFrame frame,
-                             const DrawCallback& callback,
-                             const WillDrawCallback& will_draw_callback);
-  void RequestCopyOfSurface(std::unique_ptr<CopyOutputRequest> copy_request);
-
-  SurfaceFactoryClient* client() { return client_; }
-
-  SurfaceResourceHolderClient* resource_holder_client() {
-    return resource_holder_client_;
-  }
-
-  void ReceiveFromChild(const TransferableResourceArray& resources);
-  void RefResources(const TransferableResourceArray& resources);
-  void UnrefResources(const ReturnedResourceArray& resources);
-
-  SurfaceManager* manager() { return manager_; }
-
-  Surface* current_surface_for_testing() { return current_surface_.get(); }
-
-  // This can be set to false if resources from this SurfaceFactory don't need
-  // to have sync points set on them when returned from the Display, for
-  // example if the Display shares a context with the creator.
-  bool needs_sync_points() const { return needs_sync_points_; }
-  void set_needs_sync_points(bool needs) { needs_sync_points_ = needs; }
-
- private:
-  // PendingFrameObserver implementation.
-  void OnSurfaceActivated(Surface* surface) override;
-  void OnSurfaceDependenciesChanged(
-      Surface* surface,
-      const base::flat_set<SurfaceId>& added_dependencies,
-      const base::flat_set<SurfaceId>& removed_dependencies) override;
-  void OnSurfaceDiscarded(Surface* surface) override;
-
-  std::unique_ptr<Surface> Create(const LocalSurfaceId& local_surface_id);
-  void Destroy(std::unique_ptr<Surface> surface);
-
-  const FrameSinkId frame_sink_id_;
-  SurfaceManager* manager_;
-  SurfaceFactoryClient* client_;
-  SurfaceResourceHolderClient* resource_holder_client_;
-  SurfaceResourceHolder holder_;
-  bool needs_sync_points_;
-  bool seen_first_frame_activation_ = false;
-  std::unique_ptr<Surface> current_surface_;
-  base::WeakPtrFactory<SurfaceFactory> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SurfaceFactory);
-};
-
-}  // namespace cc
-
-#endif  // CC_SURFACES_SURFACE_FACTORY_H_
diff --git a/cc/surfaces/surface_factory_client.h b/cc/surfaces/surface_factory_client.h
deleted file mode 100644
index bbcf545b..0000000
--- a/cc/surfaces/surface_factory_client.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_SURFACES_SURFACE_FACTORY_CLIENT_H_
-#define CC_SURFACES_SURFACE_FACTORY_CLIENT_H_
-
-#include "cc/resources/returned_resource.h"
-#include "cc/surfaces/local_surface_id.h"
-#include "cc/surfaces/surfaces_export.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace cc {
-
-class SurfaceId;
-
-class CC_SURFACES_EXPORT SurfaceFactoryClient {
- public:
-  virtual ~SurfaceFactoryClient() = default;
-
-  virtual void ReferencedSurfacesChanged(
-      const LocalSurfaceId& local_surface_id,
-      const std::vector<SurfaceId>* active_referenced_surfaces) = 0;
-};
-
-}  // namespace cc
-
-#endif  // CC_SURFACES_SURFACE_FACTORY_CLIENT_H_
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
deleted file mode 100644
index 6d7d30b7..0000000
--- a/cc/surfaces/surface_factory_unittest.cc
+++ /dev/null
@@ -1,769 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/surfaces/surface_factory.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/resources/resource_provider.h"
-#include "cc/surfaces/frame_sink_manager_client.h"
-#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_factory_client.h"
-#include "cc/surfaces/surface_info.h"
-#include "cc/surfaces/surface_manager.h"
-#include "cc/surfaces/surface_resource_holder_client.h"
-#include "cc/test/compositor_frame_helpers.h"
-#include "cc/test/fake_surface_resource_holder_client.h"
-#include "cc/test/scheduler_test_common.h"
-#include "cc/test/stub_surface_factory_client.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace cc {
-namespace {
-
-static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
-static constexpr FrameSinkId kAnotherArbitraryFrameSinkId(2, 2);
-static const base::UnguessableToken kArbitraryToken =
-    base::UnguessableToken::Create();
-static auto kArbitrarySourceId1 =
-    base::UnguessableToken::Deserialize(0xdead, 0xbeef);
-static auto kArbitrarySourceId2 =
-    base::UnguessableToken::Deserialize(0xdead, 0xbee0);
-
-gpu::SyncToken GenTestSyncToken(int id) {
-  gpu::SyncToken token;
-  token.Set(gpu::CommandBufferNamespace::GPU_IO, 0,
-            gpu::CommandBufferId::FromUnsafeValue(id), 1);
-  return token;
-}
-
-class SurfaceFactoryTest : public testing::Test, public SurfaceObserver {
- public:
-  SurfaceFactoryTest()
-      : factory_(new SurfaceFactory(kArbitraryFrameSinkId,
-                                    &manager_,
-                                    &stub_surface_factory_client_,
-                                    &fake_surface_resource_holder_client_)),
-        local_surface_id_(3, kArbitraryToken),
-        frame_sync_token_(GenTestSyncToken(4)),
-        consumer_sync_token_(GenTestSyncToken(5)) {
-    manager_.AddObserver(this);
-  }
-
-  const SurfaceId& last_created_surface_id() const {
-    return last_created_surface_id_;
-  }
-
-  // SurfaceObserver implementation.
-  void OnSurfaceCreated(const SurfaceInfo& surface_info) override {
-    EXPECT_EQ(kArbitraryFrameSinkId, surface_info.id().frame_sink_id());
-    last_created_surface_id_ = surface_info.id();
-    last_surface_info_ = surface_info;
-  }
-
-  void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
-    *changed = true;
-  }
-
-  ~SurfaceFactoryTest() override {
-    manager_.RemoveObserver(this);
-    factory_->EvictSurface();
-  }
-
-  void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
-                                          size_t num_resource_ids) {
-    CompositorFrame frame = test::MakeCompositorFrame();
-    for (size_t i = 0u; i < num_resource_ids; ++i) {
-      TransferableResource resource;
-      resource.id = resource_ids[i];
-      resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-      resource.mailbox_holder.sync_token = frame_sync_token_;
-      frame.resource_list.push_back(resource);
-    }
-    factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
-                                    SurfaceFactory::DrawCallback(),
-                                    SurfaceFactory::WillDrawCallback());
-    EXPECT_EQ(last_created_surface_id_.local_surface_id(), local_surface_id_);
-  }
-
-  void UnrefResources(ResourceId* ids_to_unref,
-                      int* counts_to_unref,
-                      size_t num_ids_to_unref) {
-    ReturnedResourceArray unref_array;
-    for (size_t i = 0; i < num_ids_to_unref; ++i) {
-      ReturnedResource resource;
-      resource.sync_token = consumer_sync_token_;
-      resource.id = ids_to_unref[i];
-      resource.count = counts_to_unref[i];
-      unref_array.push_back(resource);
-    }
-    factory_->UnrefResources(unref_array);
-  }
-
-  void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids,
-                                           int* expected_returned_counts,
-                                           size_t expected_resources,
-                                           gpu::SyncToken expected_sync_token) {
-    const ReturnedResourceArray& actual_resources =
-        fake_surface_resource_holder_client_.returned_resources();
-    ASSERT_EQ(expected_resources, actual_resources.size());
-    for (size_t i = 0; i < expected_resources; ++i) {
-      ReturnedResource resource = actual_resources[i];
-      EXPECT_EQ(expected_sync_token, resource.sync_token);
-      EXPECT_EQ(expected_returned_ids[i], resource.id);
-      EXPECT_EQ(expected_returned_counts[i], resource.count);
-    }
-    fake_surface_resource_holder_client_.clear_returned_resources();
-  }
-
-  void RefCurrentFrameResources() {
-    Surface* surface = manager_.GetSurfaceForId(
-        SurfaceId(factory_->frame_sink_id(), local_surface_id_));
-    factory_->RefResources(surface->GetActiveFrame().resource_list);
-  }
-
- protected:
-  SurfaceManager manager_;
-  StubSurfaceFactoryClient stub_surface_factory_client_;
-  FakeSurfaceResourceHolderClient fake_surface_resource_holder_client_;
-  std::unique_ptr<SurfaceFactory> factory_;
-  LocalSurfaceId local_surface_id_;
-  SurfaceId last_created_surface_id_;
-  SurfaceInfo last_surface_info_;
-
-  // This is the sync token submitted with the frame. It should never be
-  // returned to the client.
-  const gpu::SyncToken frame_sync_token_;
-
-  // This is the sync token returned by the consumer. It should always be
-  // returned to the client.
-  const gpu::SyncToken consumer_sync_token_;
-};
-
-// Tests submitting a frame with resources followed by one with no resources
-// with no resource provider action in between.
-TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
-  ResourceId first_frame_ids[] = {1, 2, 3};
-  SubmitCompositorFrameWithResources(first_frame_ids,
-                                     arraysize(first_frame_ids));
-
-  // All of the resources submitted in the first frame are still in use at this
-  // time by virtue of being in the pending frame, so none can be returned to
-  // the client yet.
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-  fake_surface_resource_holder_client_.clear_returned_resources();
-
-  // The second frame references no resources of first frame and thus should
-  // make all resources of first frame available to be returned.
-  SubmitCompositorFrameWithResources(NULL, 0);
-
-  ResourceId expected_returned_ids[] = {1, 2, 3};
-  int expected_returned_counts[] = {1, 1, 1};
-  // Resources were never consumed so no sync token should be set.
-  CheckReturnedResourcesMatchExpected(
-      expected_returned_ids, expected_returned_counts,
-      arraysize(expected_returned_counts), gpu::SyncToken());
-
-  ResourceId third_frame_ids[] = {4, 5, 6};
-  SubmitCompositorFrameWithResources(third_frame_ids,
-                                     arraysize(third_frame_ids));
-
-  // All of the resources submitted in the third frame are still in use at this
-  // time by virtue of being in the pending frame, so none can be returned to
-  // the client yet.
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-  fake_surface_resource_holder_client_.clear_returned_resources();
-
-  // The forth frame references no resources of third frame and thus should
-  // make all resources of third frame available to be returned.
-  ResourceId forth_frame_ids[] = {7, 8, 9};
-  SubmitCompositorFrameWithResources(forth_frame_ids,
-                                     arraysize(forth_frame_ids));
-
-  ResourceId forth_expected_returned_ids[] = {4, 5, 6};
-  int forth_expected_returned_counts[] = {1, 1, 1};
-  // Resources were never consumed so no sync token should be set.
-  CheckReturnedResourcesMatchExpected(
-      forth_expected_returned_ids, forth_expected_returned_counts,
-      arraysize(forth_expected_returned_counts), gpu::SyncToken());
-}
-
-// Tests submitting a frame with resources followed by one with no resources
-// with the resource provider holding everything alive.
-TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
-  ResourceId first_frame_ids[] = {1, 2, 3};
-  SubmitCompositorFrameWithResources(first_frame_ids,
-                                     arraysize(first_frame_ids));
-
-  // All of the resources submitted in the first frame are still in use at this
-  // time by virtue of being in the pending frame, so none can be returned to
-  // the client yet.
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-  fake_surface_resource_holder_client_.clear_returned_resources();
-
-  // Hold on to everything.
-  RefCurrentFrameResources();
-
-  // The second frame references no resources and thus should make all resources
-  // available to be returned as soon as the resource provider releases them.
-  SubmitCompositorFrameWithResources(NULL, 0);
-
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-  fake_surface_resource_holder_client_.clear_returned_resources();
-
-  int release_counts[] = {1, 1, 1};
-  UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
-
-  ResourceId expected_returned_ids[] = {1, 2, 3};
-  int expected_returned_counts[] = {1, 1, 1};
-  CheckReturnedResourcesMatchExpected(
-      expected_returned_ids, expected_returned_counts,
-      arraysize(expected_returned_counts), consumer_sync_token_);
-}
-
-// Tests referencing a resource, unref'ing it to zero, then using it again
-// before returning it to the client.
-TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
-  ResourceId first_frame_ids[] = {7};
-  SubmitCompositorFrameWithResources(first_frame_ids,
-                                     arraysize(first_frame_ids));
-
-  // This removes all references to resource id 7.
-  SubmitCompositorFrameWithResources(NULL, 0);
-
-  // This references id 7 again.
-  SubmitCompositorFrameWithResources(first_frame_ids,
-                                     arraysize(first_frame_ids));
-
-  // This removes it again.
-  SubmitCompositorFrameWithResources(NULL, 0);
-
-  // Now it should be returned.
-  // We don't care how many entries are in the returned array for 7, so long as
-  // the total returned count matches the submitted count.
-  const ReturnedResourceArray& returned =
-      fake_surface_resource_holder_client_.returned_resources();
-  size_t return_count = 0;
-  for (size_t i = 0; i < returned.size(); ++i) {
-    EXPECT_EQ(7u, returned[i].id);
-    return_count += returned[i].count;
-  }
-  EXPECT_EQ(2u, return_count);
-}
-
-// Tests having resources referenced multiple times, as if referenced by
-// multiple providers.
-TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
-  ResourceId first_frame_ids[] = {3, 4};
-  SubmitCompositorFrameWithResources(first_frame_ids,
-                                     arraysize(first_frame_ids));
-
-  // Ref resources from the first frame twice.
-  RefCurrentFrameResources();
-  RefCurrentFrameResources();
-
-  ResourceId second_frame_ids[] = {4, 5};
-  SubmitCompositorFrameWithResources(second_frame_ids,
-                                     arraysize(second_frame_ids));
-
-  // Ref resources from the second frame 3 times.
-  RefCurrentFrameResources();
-  RefCurrentFrameResources();
-  RefCurrentFrameResources();
-
-  // Submit a frame with no resources to remove all current frame refs from
-  // submitted resources.
-  SubmitCompositorFrameWithResources(NULL, 0);
-
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-  fake_surface_resource_holder_client_.clear_returned_resources();
-
-  // Expected current refs:
-  //  3 -> 2
-  //  4 -> 2 + 3 = 5
-  //  5 -> 3
-  {
-    SCOPED_TRACE("unref all 3");
-    ResourceId ids_to_unref[] = {3, 4, 5};
-    int counts[] = {1, 1, 1};
-    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
-
-    EXPECT_EQ(0u,
-              fake_surface_resource_holder_client_.returned_resources().size());
-    fake_surface_resource_holder_client_.clear_returned_resources();
-
-    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
-
-    ResourceId expected_returned_ids[] = {3};
-    int expected_returned_counts[] = {1};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), consumer_sync_token_);
-  }
-
-  // Expected refs remaining:
-  //  4 -> 3
-  //  5 -> 1
-  {
-    SCOPED_TRACE("unref 4 and 5");
-    ResourceId ids_to_unref[] = {4, 5};
-    int counts[] = {1, 1};
-    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
-
-    ResourceId expected_returned_ids[] = {5};
-    int expected_returned_counts[] = {1};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), consumer_sync_token_);
-  }
-
-  // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
-  // the returned count is correct.
-  {
-    SCOPED_TRACE("unref only 4");
-    ResourceId ids_to_unref[] = {4};
-    int counts[] = {2};
-    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
-
-    ResourceId expected_returned_ids[] = {4};
-    int expected_returned_counts[] = {2};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), consumer_sync_token_);
-  }
-}
-
-TEST_F(SurfaceFactoryTest, ResourceLifetime) {
-  ResourceId first_frame_ids[] = {1, 2, 3};
-  SubmitCompositorFrameWithResources(first_frame_ids,
-                                     arraysize(first_frame_ids));
-
-  // All of the resources submitted in the first frame are still in use at this
-  // time by virtue of being in the pending frame, so none can be returned to
-  // the client yet.
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-  fake_surface_resource_holder_client_.clear_returned_resources();
-
-  // The second frame references some of the same resources, but some different
-  // ones. We expect to receive back resource 1 with a count of 1 since it was
-  // only referenced by the first frame.
-  ResourceId second_frame_ids[] = {2, 3, 4};
-  SubmitCompositorFrameWithResources(second_frame_ids,
-                                     arraysize(second_frame_ids));
-
-  {
-    SCOPED_TRACE("second frame");
-    ResourceId expected_returned_ids[] = {1};
-    int expected_returned_counts[] = {1};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), gpu::SyncToken());
-  }
-
-  // The third frame references a disjoint set of resources, so we expect to
-  // receive back all resources from the first and second frames. Resource IDs 2
-  // and 3 will have counts of 2, since they were used in both frames, and
-  // resource ID 4 will have a count of 1.
-  ResourceId third_frame_ids[] = {10, 11, 12, 13};
-  SubmitCompositorFrameWithResources(third_frame_ids,
-                                     arraysize(third_frame_ids));
-
-  {
-    SCOPED_TRACE("third frame");
-    ResourceId expected_returned_ids[] = {2, 3, 4};
-    int expected_returned_counts[] = {2, 2, 1};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), gpu::SyncToken());
-  }
-
-  // Simulate a ResourceProvider taking a ref on all of the resources.
-  RefCurrentFrameResources();
-
-  ResourceId fourth_frame_ids[] = {12, 13};
-  SubmitCompositorFrameWithResources(fourth_frame_ids,
-                                     arraysize(fourth_frame_ids));
-
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-
-  RefCurrentFrameResources();
-
-  // All resources are still being used by the external reference, so none can
-  // be returned to the client.
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-
-  // Release resources associated with the first RefCurrentFrameResources() call
-  // first.
-  {
-    ResourceId ids_to_unref[] = {10, 11, 12, 13};
-    int counts[] = {1, 1, 1, 1};
-    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
-  }
-
-  {
-    SCOPED_TRACE("fourth frame, first unref");
-    ResourceId expected_returned_ids[] = {10, 11};
-    int expected_returned_counts[] = {1, 1};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), consumer_sync_token_);
-  }
-
-  {
-    ResourceId ids_to_unref[] = {12, 13};
-    int counts[] = {1, 1};
-    UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
-  }
-
-  // Resources 12 and 13 are still in use by the current frame, so they
-  // shouldn't be available to be returned.
-  EXPECT_EQ(0u,
-            fake_surface_resource_holder_client_.returned_resources().size());
-
-  // If we submit an empty frame, however, they should become available.
-  SubmitCompositorFrameWithResources(NULL, 0u);
-
-  {
-    SCOPED_TRACE("fourth frame, second unref");
-    ResourceId expected_returned_ids[] = {12, 13};
-    int expected_returned_counts[] = {2, 2};
-    CheckReturnedResourcesMatchExpected(
-        expected_returned_ids, expected_returned_counts,
-        arraysize(expected_returned_counts), consumer_sync_token_);
-  }
-}
-
-void CreateSurfaceDrawCallback(SurfaceFactory* factory,
-                               uint32_t* execute_count) {
-  LocalSurfaceId new_id(7, base::UnguessableToken::Create());
-  factory->SubmitCompositorFrame(new_id, test::MakeCompositorFrame(),
-                                 SurfaceFactory::DrawCallback(),
-                                 SurfaceFactory::WillDrawCallback());
-  factory->EvictSurface();
-  *execute_count += 1;
-}
-
-TEST_F(SurfaceFactoryTest, AddDuringEviction) {
-  LocalSurfaceId local_surface_id(6, kArbitraryToken);
-
-  uint32_t execute_count = 0;
-  factory_->SubmitCompositorFrame(
-      local_surface_id, test::MakeCompositorFrame(),
-      base::Bind(&CreateSurfaceDrawCallback, base::Unretained(factory_.get()),
-                 &execute_count),
-      SurfaceFactory::WillDrawCallback());
-  EXPECT_EQ(0u, execute_count);
-  factory_->EvictSurface();
-  EXPECT_EQ(1u, execute_count);
-}
-
-void DrawCallback(uint32_t* execute_count) {
-  *execute_count += 1;
-}
-
-// Tests doing an EvictSurface before shutting down the factory.
-TEST_F(SurfaceFactoryTest, EvictSurface) {
-  LocalSurfaceId local_surface_id(7, kArbitraryToken);
-  SurfaceId id(kArbitraryFrameSinkId, local_surface_id);
-
-  TransferableResource resource;
-  resource.id = 1;
-  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-  CompositorFrame frame = test::MakeCompositorFrame();
-  frame.resource_list.push_back(resource);
-  uint32_t execute_count = 0;
-  factory_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                  base::Bind(&DrawCallback, &execute_count),
-                                  SurfaceFactory::WillDrawCallback());
-  EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
-  local_surface_id_ = LocalSurfaceId();
-
-  EXPECT_TRUE(manager_.GetSurfaceForId(id));
-  EXPECT_TRUE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-  factory_->EvictSurface();
-  EXPECT_FALSE(manager_.GetSurfaceForId(id));
-  EXPECT_FALSE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-  EXPECT_EQ(1u, execute_count);
-}
-
-// Tests doing an EvictSurface which has unregistered dependency.
-TEST_F(SurfaceFactoryTest, EvictSurfaceDependencyUnRegistered) {
-  LocalSurfaceId local_surface_id(7, kArbitraryToken);
-
-  TransferableResource resource;
-  resource.id = 1;
-  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-  CompositorFrame frame = test::MakeCompositorFrame();
-  frame.resource_list.push_back(resource);
-  uint32_t execute_count = 0;
-  factory_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                  base::Bind(&DrawCallback, &execute_count),
-                                  SurfaceFactory::WillDrawCallback());
-  EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
-  local_surface_id_ = LocalSurfaceId();
-
-  SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id);
-  Surface* surface = manager_.GetSurfaceForId(surface_id);
-  surface->AddDestructionDependency(
-      SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-  factory_->EvictSurface();
-  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_FALSE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-  EXPECT_EQ(1u, execute_count);
-}
-
-// Tests doing an EvictSurface which has registered dependency.
-TEST_F(SurfaceFactoryTest, EvictSurfaceDependencyRegistered) {
-  LocalSurfaceId local_surface_id(7, kArbitraryToken);
-
-  TransferableResource resource;
-  resource.id = 1;
-  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-  CompositorFrame frame = test::MakeCompositorFrame();
-  frame.resource_list.push_back(resource);
-  uint32_t execute_count = 0;
-  factory_->SubmitCompositorFrame(local_surface_id, std::move(frame),
-                                  base::Bind(&DrawCallback, &execute_count),
-                                  SurfaceFactory::WillDrawCallback());
-  EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
-  local_surface_id_ = LocalSurfaceId();
-
-  manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
-
-  SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id);
-  Surface* surface = manager_.GetSurfaceForId(surface_id);
-  surface->AddDestructionDependency(
-      SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-  factory_->EvictSurface();
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-  EXPECT_EQ(0u, execute_count);
-
-  manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_FALSE(
-      fake_surface_resource_holder_client_.returned_resources().empty());
-}
-
-TEST_F(SurfaceFactoryTest, DestroySequence) {
-  LocalSurfaceId local_surface_id2(5, kArbitraryToken);
-  std::unique_ptr<SurfaceFactory> factory2(new SurfaceFactory(
-      kArbitraryFrameSinkId, &manager_, &stub_surface_factory_client_,
-      &fake_surface_resource_holder_client_));
-  SurfaceId id2(kArbitraryFrameSinkId, local_surface_id2);
-  factory2->SubmitCompositorFrame(
-      local_surface_id2, test::MakeCompositorFrame(),
-      SurfaceFactory::DrawCallback(), SurfaceFactory::WillDrawCallback());
-
-  manager_.RegisterFrameSinkId(kArbitraryFrameSinkId);
-
-  // Check that waiting before the sequence is satisfied works.
-  manager_.GetSurfaceForId(id2)->AddDestructionDependency(
-      SurfaceSequence(kArbitraryFrameSinkId, 4));
-  factory2->EvictSurface();
-
-  DCHECK(manager_.GetSurfaceForId(id2));
-  manager_.SatisfySequence(SurfaceSequence(kArbitraryFrameSinkId, 4));
-  manager_.SatisfySequence(SurfaceSequence(kArbitraryFrameSinkId, 6));
-  DCHECK(!manager_.GetSurfaceForId(id2));
-
-  // Check that waiting after the sequence is satisfied works.
-  factory2->SubmitCompositorFrame(
-      local_surface_id2, test::MakeCompositorFrame(),
-      SurfaceFactory::DrawCallback(), SurfaceFactory::WillDrawCallback());
-  DCHECK(manager_.GetSurfaceForId(id2));
-  manager_.GetSurfaceForId(id2)->AddDestructionDependency(
-      SurfaceSequence(kAnotherArbitraryFrameSinkId, 6));
-  factory2->EvictSurface();
-  DCHECK(!manager_.GetSurfaceForId(id2));
-}
-
-// Tests that Surface ID namespace invalidation correctly allows
-// Sequences to be ignored.
-TEST_F(SurfaceFactoryTest, InvalidFrameSinkId) {
-  FrameSinkId frame_sink_id(1234, 5678);
-
-  LocalSurfaceId local_surface_id(5, kArbitraryToken);
-  SurfaceId id(factory_->frame_sink_id(), local_surface_id);
-  factory_->SubmitCompositorFrame(local_surface_id, test::MakeCompositorFrame(),
-                                  SurfaceFactory::DrawCallback(),
-                                  SurfaceFactory::WillDrawCallback());
-
-  manager_.RegisterFrameSinkId(frame_sink_id);
-  manager_.GetSurfaceForId(id)->AddDestructionDependency(
-      SurfaceSequence(frame_sink_id, 4));
-
-  factory_->EvictSurface();
-
-  // Verify the dependency has prevented the surface from getting destroyed.
-  EXPECT_TRUE(manager_.GetSurfaceForId(id));
-
-  manager_.InvalidateFrameSinkId(frame_sink_id);
-
-  // Verify that the invalidated namespace caused the unsatisfied sequence
-  // to be ignored.
-  EXPECT_FALSE(manager_.GetSurfaceForId(id));
-}
-
-TEST_F(SurfaceFactoryTest, DestroyCycle) {
-  LocalSurfaceId local_surface_id2(5, kArbitraryToken);
-  SurfaceId id2(kArbitraryFrameSinkId, local_surface_id2);
-  std::unique_ptr<SurfaceFactory> factory2(new SurfaceFactory(
-      kArbitraryFrameSinkId, &manager_, &stub_surface_factory_client_,
-      &fake_surface_resource_holder_client_));
-  manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
-  // Give id2 a frame that references local_surface_id_.
-  {
-    std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
-    CompositorFrame frame = test::MakeCompositorFrame();
-    frame.render_pass_list.push_back(std::move(render_pass));
-    frame.metadata.referenced_surfaces.push_back(
-        SurfaceId(factory_->frame_sink_id(), local_surface_id_));
-    factory2->SubmitCompositorFrame(local_surface_id2, std::move(frame),
-                                    SurfaceFactory::DrawCallback(),
-                                    SurfaceFactory::WillDrawCallback());
-    EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id2);
-  }
-  manager_.GetSurfaceForId(id2)->AddDestructionDependency(
-      SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-  factory2->EvictSurface();
-  // Give local_surface_id_ a frame that references id2.
-  {
-    std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
-    CompositorFrame frame = test::MakeCompositorFrame();
-    frame.render_pass_list.push_back(std::move(render_pass));
-    frame.metadata.referenced_surfaces.push_back(id2);
-    factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
-                                    SurfaceFactory::DrawCallback(),
-                                    SurfaceFactory::WillDrawCallback());
-  }
-  factory_->EvictSurface();
-  EXPECT_TRUE(manager_.GetSurfaceForId(id2));
-  // local_surface_id_ should be retained by reference from id2.
-  EXPECT_TRUE(manager_.GetSurfaceForId(
-      SurfaceId(factory_->frame_sink_id(), local_surface_id_)));
-
-  // Satisfy last destruction dependency for id2.
-  manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-
-  // id2 and local_surface_id_ are in a reference cycle that has no surface
-  // sequences holding on to it, so they should be destroyed.
-  EXPECT_TRUE(!manager_.GetSurfaceForId(id2));
-  EXPECT_TRUE(!manager_.GetSurfaceForId(
-      SurfaceId(factory_->frame_sink_id(), local_surface_id_)));
-
-  local_surface_id_ = LocalSurfaceId();
-}
-
-void CopyRequestTestCallback(bool* called,
-                             std::unique_ptr<CopyOutputResult> result) {
-  *called = true;
-}
-
-TEST_F(SurfaceFactoryTest, DuplicateCopyRequest) {
-  {
-    std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
-    CompositorFrame frame = test::MakeCompositorFrame();
-    frame.render_pass_list.push_back(std::move(render_pass));
-    frame.metadata.referenced_surfaces.push_back(
-        SurfaceId(factory_->frame_sink_id(), local_surface_id_));
-    factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
-                                    SurfaceFactory::DrawCallback(),
-                                    SurfaceFactory::WillDrawCallback());
-    EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id_);
-  }
-
-  bool called1 = false;
-  std::unique_ptr<CopyOutputRequest> request;
-  request = CopyOutputRequest::CreateRequest(
-      base::Bind(&CopyRequestTestCallback, &called1));
-  request->set_source(kArbitrarySourceId1);
-
-  factory_->RequestCopyOfSurface(std::move(request));
-  EXPECT_FALSE(called1);
-
-  bool called2 = false;
-  request = CopyOutputRequest::CreateRequest(
-      base::Bind(&CopyRequestTestCallback, &called2));
-  request->set_source(kArbitrarySourceId2);
-
-  factory_->RequestCopyOfSurface(std::move(request));
-  // Callbacks have different sources so neither should be called.
-  EXPECT_FALSE(called1);
-  EXPECT_FALSE(called2);
-
-  bool called3 = false;
-  request = CopyOutputRequest::CreateRequest(
-      base::Bind(&CopyRequestTestCallback, &called3));
-  request->set_source(kArbitrarySourceId1);
-
-  factory_->RequestCopyOfSurface(std::move(request));
-  // Two callbacks are from source1, so the first should be called.
-  EXPECT_TRUE(called1);
-  EXPECT_FALSE(called2);
-  EXPECT_FALSE(called3);
-
-  factory_->EvictSurface();
-  local_surface_id_ = LocalSurfaceId();
-  EXPECT_TRUE(called1);
-  EXPECT_TRUE(called2);
-  EXPECT_TRUE(called3);
-}
-
-// Check whether the SurfaceInfo object is created and populated correctly
-// after the frame submission.
-TEST_F(SurfaceFactoryTest, SurfaceInfo) {
-  CompositorFrame frame = test::MakeEmptyCompositorFrame();
-
-  auto render_pass = RenderPass::Create();
-  render_pass->SetNew(1, gfx::Rect(5, 6), gfx::Rect(), gfx::Transform());
-  frame.render_pass_list.push_back(std::move(render_pass));
-
-  render_pass = RenderPass::Create();
-  render_pass->SetNew(2, gfx::Rect(7, 8), gfx::Rect(), gfx::Transform());
-  frame.render_pass_list.push_back(std::move(render_pass));
-
-  frame.metadata.device_scale_factor = 2.5f;
-
-  factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
-                                  SurfaceFactory::DrawCallback(),
-                                  SurfaceFactory::WillDrawCallback());
-  SurfaceId expected_surface_id(factory_->frame_sink_id(), local_surface_id_);
-  EXPECT_EQ(expected_surface_id, last_surface_info_.id());
-  EXPECT_EQ(2.5f, last_surface_info_.device_scale_factor());
-  EXPECT_EQ(gfx::Size(7, 8), last_surface_info_.size_in_pixels());
-}
-
-}  // namespace
-}  // namespace cc
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index e4267b4..19ea700 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -11,10 +11,10 @@
 #include <utility>
 
 #include "base/logging.h"
+#include "cc/surfaces/compositor_frame_sink_support.h"
 #include "cc/surfaces/direct_surface_reference_factory.h"
 #include "cc/surfaces/local_surface_id_allocator.h"
 #include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surface_info.h"
 
 #if DCHECK_IS_ON()
@@ -75,18 +75,20 @@
 }
 
 std::unique_ptr<Surface> SurfaceManager::CreateSurface(
-    base::WeakPtr<SurfaceFactory> surface_factory,
+    base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support,
     const LocalSurfaceId& local_surface_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(local_surface_id.is_valid() && surface_factory);
+  DCHECK(local_surface_id.is_valid() && compositor_frame_sink_support);
 
-  SurfaceId surface_id(surface_factory->frame_sink_id(), local_surface_id);
+  SurfaceId surface_id(compositor_frame_sink_support->frame_sink_id(),
+                       local_surface_id);
 
   // If no surface with this SurfaceId exists, simply create the surface and
   // return.
   auto surface_iter = surface_map_.find(surface_id);
   if (surface_iter == surface_map_.end()) {
-    auto surface = base::MakeUnique<Surface>(surface_id, surface_factory);
+    auto surface =
+        base::MakeUnique<Surface>(surface_id, compositor_frame_sink_support);
     surface_map_[surface->surface_id()] = surface.get();
     return surface;
   }
@@ -108,7 +110,8 @@
   std::unique_ptr<Surface> surface = std::move(*it);
   surfaces_to_destroy_.erase(it);
   surface->set_destroyed(false);
-  DCHECK_EQ(surface_factory.get(), surface->factory().get());
+  DCHECK_EQ(compositor_frame_sink_support.get(),
+            surface->compositor_frame_sink_support().get());
   return surface;
 }
 
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h
index 91d9d9f..db716bd 100644
--- a/cc/surfaces/surface_manager.h
+++ b/cc/surfaces/surface_manager.h
@@ -38,9 +38,10 @@
 class CompositorFrame;
 class FrameSinkManagerClient;
 class Surface;
-class SurfaceFactory;
-class SurfaceFactoryClient;
-class CompositorFrameSinkSupportTest;
+
+namespace test {
+class SurfaceSynchronizationTest;
+}
 
 class CC_SURFACES_EXPORT SurfaceManager {
  public:
@@ -66,7 +67,7 @@
   void RequestSurfaceResolution(Surface* pending_surface);
 
   std::unique_ptr<Surface> CreateSurface(
-      base::WeakPtr<SurfaceFactory> surface_factory,
+      base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support,
       const LocalSurfaceId& local_surface_id);
 
   // Destroy the Surface once a set of sequence numbers has been satisfied.
@@ -82,8 +83,8 @@
 
   bool SurfaceModified(const SurfaceId& surface_id);
 
-  // Called when a CompositorFrame is submitted to a SurfaceFactory for a given
-  // |surface_id| for the first time.
+  // Called when a CompositorFrame is submitted to a CompositorFrameSinkSupport
+  // for a given |surface_id| for the first time.
   void SurfaceCreated(const SurfaceInfo& surface_info);
 
   // Require that the given sequence number must be satisfied (using
@@ -101,8 +102,8 @@
   // possibly because a renderer process has crashed.
   void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id);
 
-  // SurfaceFactoryClient, hierarchy, and BeginFrameSource can be registered
-  // and unregistered in any order with respect to each other.
+  // CompositorFrameSinkSupport, hierarchy, and BeginFrameSource can be
+  // registered and unregistered in any order with respect to each other.
   //
   // This happens in practice, e.g. the relationship to between ui::Compositor /
   // DelegatedFrameHost is known before ui::Compositor has a surface/client).
@@ -169,7 +170,7 @@
   }
 
  private:
-  friend class CompositorFrameSinkSupportTest;
+  friend class test::SurfaceSynchronizationTest;
   friend class SurfaceManagerRefTest;
 
   using SurfaceIdSet = std::unordered_set<SurfaceId, SurfaceIdHash>;
diff --git a/cc/surfaces/surface_manager_unittest.cc b/cc/surfaces/surface_manager_unittest.cc
index 53fe6ed9..07047fd 100644
--- a/cc/surfaces/surface_manager_unittest.cc
+++ b/cc/surfaces/surface_manager_unittest.cc
@@ -6,9 +6,7 @@
 
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/surfaces/frame_sink_manager_client.h"
-#include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surface_manager.h"
-#include "cc/surfaces/surface_resource_holder_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -184,7 +182,7 @@
 
 // This test verifies that a BeginFrameSource path to the root from a
 // FrameSinkId is preserved even if that FrameSinkId has no children
-// and does not have a corresponding SurfaceFactoryClient.
+// and does not have a corresponding FrameSinkManagerClient.
 TEST_F(SurfaceManagerTest, ParentWithoutClientRetained) {
   StubBeginFrameSource root_source;
 
@@ -201,7 +199,7 @@
   EXPECT_EQ(&root_source, root.source());
 
   // Set up initial hierarchy: root -> A -> B.
-  // Note that A does not have a SurfaceFactoryClient.
+  // Note that A does not have a FrameSinkManagerClient.
   manager_.RegisterFrameSinkHierarchy(kFrameSinkIdRoot, kFrameSinkIdA);
   manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB);
   // The root's BeginFrameSource should propagate to B.
@@ -237,7 +235,7 @@
   FakeFrameSinkManagerClient client_c(kFrameSinkIdC, &manager_);
 
   // Set up initial hierarchy: root -> A -> B.
-  // Note that A does not have a SurfaceFactoryClient.
+  // Note that A does not have a FrameSinkManagerClient.
   manager_.RegisterFrameSinkHierarchy(kFrameSinkIdRoot, kFrameSinkIdA);
   manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB);
   // The root does not yet have a BeginFrameSource so client B should not have
@@ -260,7 +258,7 @@
 }
 
 // In practice, registering and unregistering both parent/child relationships
-// and SurfaceFactoryClients can happen in any ordering with respect to
+// and FrameSinkManagerClients can happen in any ordering with respect to
 // each other.  These following tests verify that all the data structures
 // are properly set up and cleaned up under the four permutations of orderings
 // of this nesting.
diff --git a/cc/surfaces/surface_resource_holder.cc b/cc/surfaces/surface_resource_holder.cc
index dff955c..8d46b25 100644
--- a/cc/surfaces/surface_resource_holder.cc
+++ b/cc/surfaces/surface_resource_holder.cc
@@ -11,12 +11,10 @@
     SurfaceResourceHolderClient* client)
     : client_(client) {}
 
-SurfaceResourceHolder::~SurfaceResourceHolder() {
-}
+SurfaceResourceHolder::~SurfaceResourceHolder() = default;
 
 SurfaceResourceHolder::ResourceRefs::ResourceRefs()
-    : refs_received_from_child(0), refs_holding_resource_alive(0) {
-}
+    : refs_received_from_child(0), refs_holding_resource_alive(0) {}
 
 void SurfaceResourceHolder::Reset() {
   resource_id_info_map_.clear();
@@ -24,10 +22,8 @@
 
 void SurfaceResourceHolder::ReceiveFromChild(
     const TransferableResourceArray& resources) {
-  for (TransferableResourceArray::const_iterator it = resources.begin();
-       it != resources.end();
-       ++it) {
-    ResourceRefs& ref = resource_id_info_map_[it->id];
+  for (const auto& resource : resources) {
+    ResourceRefs& ref = resource_id_info_map_[resource.id];
     ref.refs_holding_resource_alive++;
     ref.refs_received_from_child++;
   }
diff --git a/cc/surfaces/surface_synchronization_unittest.cc b/cc/surfaces/surface_synchronization_unittest.cc
new file mode 100644
index 0000000..8c21486
--- /dev/null
+++ b/cc/surfaces/surface_synchronization_unittest.cc
@@ -0,0 +1,1389 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/surfaces/compositor_frame_sink_support.h"
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_manager.h"
+#include "cc/surfaces/surface_observer.h"
+#include "cc/test/begin_frame_args_test.h"
+#include "cc/test/compositor_frame_helpers.h"
+#include "cc/test/fake_external_begin_frame_source.h"
+#include "cc/test/mock_compositor_frame_sink_support_client.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Eq;
+using testing::IsEmpty;
+using testing::UnorderedElementsAre;
+
+namespace cc {
+namespace test {
+namespace {
+
+constexpr bool kIsRoot = true;
+constexpr bool kIsChildRoot = false;
+constexpr bool kHandlesFrameSinkIdInvalidation = true;
+constexpr bool kNeedsSyncPoints = true;
+constexpr FrameSinkId kDisplayFrameSink(2, 0);
+constexpr FrameSinkId kParentFrameSink(3, 0);
+constexpr FrameSinkId kChildFrameSink1(65563, 0);
+constexpr FrameSinkId kChildFrameSink2(65564, 0);
+constexpr FrameSinkId kArbitraryFrameSink(1337, 7331);
+
+std::vector<SurfaceId> empty_surface_ids() {
+  return std::vector<SurfaceId>();
+}
+
+SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) {
+  return SurfaceId(
+      frame_sink_id,
+      LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
+}
+
+}  // namespace
+
+class SurfaceSynchronizationTest : public testing::Test,
+                                   public SurfaceObserver {
+ public:
+  SurfaceSynchronizationTest()
+      : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {}
+  ~SurfaceSynchronizationTest() override {}
+
+  CompositorFrameSinkSupport& display_support() { return *supports_[0]; }
+  Surface* display_surface() {
+    return display_support().current_surface_for_testing();
+  }
+
+  CompositorFrameSinkSupport& parent_support() { return *supports_[1]; }
+  Surface* parent_surface() {
+    return parent_support().current_surface_for_testing();
+  }
+  const ReferencedSurfaceTracker& parent_reference_tracker() {
+    return parent_support().ReferenceTrackerForTesting();
+  }
+
+  CompositorFrameSinkSupport& child_support1() { return *supports_[2]; }
+  Surface* child_surface1() {
+    return child_support1().current_surface_for_testing();
+  }
+
+  CompositorFrameSinkSupport& child_support2() { return *supports_[3]; }
+  Surface* child_surface2() {
+    return child_support2().current_surface_for_testing();
+  }
+
+  CompositorFrameSinkSupport& support(int index) { return *supports_[index]; }
+  Surface* surface(int index) {
+    return support(index).current_surface_for_testing();
+  }
+
+  SurfaceManager& surface_manager() { return surface_manager_; }
+
+  // Returns all the references where |surface_id| is the parent.
+  const SurfaceManager::SurfaceIdSet& GetChildReferences(
+      const SurfaceId& surface_id) {
+    return surface_manager().parent_to_child_refs_[surface_id];
+  }
+
+  // Returns true if there is a temporary reference for |surface_id|.
+  bool HasTemporaryReference(const SurfaceId& surface_id) {
+    return surface_manager().HasTemporaryReference(surface_id);
+  }
+
+  SurfaceDependencyTracker& dependency_tracker() {
+    return *surface_manager_.dependency_tracker();
+  }
+
+  FakeExternalBeginFrameSource* begin_frame_source() {
+    return begin_frame_source_.get();
+  }
+
+  // testing::Test:
+  void SetUp() override {
+    testing::Test::SetUp();
+
+    begin_frame_source_ =
+        base::MakeUnique<FakeExternalBeginFrameSource>(0.f, false);
+    surface_manager_.SetDependencyTracker(
+        base::MakeUnique<SurfaceDependencyTracker>(&surface_manager_,
+                                                   begin_frame_source_.get()));
+    surface_manager_.AddObserver(this);
+    supports_.push_back(CompositorFrameSinkSupport::Create(
+        &support_client_, &surface_manager_, kDisplayFrameSink, kIsRoot,
+        kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints));
+    supports_.push_back(CompositorFrameSinkSupport::Create(
+        &support_client_, &surface_manager_, kParentFrameSink, kIsChildRoot,
+        kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints));
+    supports_.push_back(CompositorFrameSinkSupport::Create(
+        &support_client_, &surface_manager_, kChildFrameSink1, kIsChildRoot,
+        kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints));
+    supports_.push_back(CompositorFrameSinkSupport::Create(
+        &support_client_, &surface_manager_, kChildFrameSink2, kIsChildRoot,
+        kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints));
+
+    // Normally, the BeginFrameSource would be registered by the Display. We
+    // register it here so that BeginFrames are received by the display support,
+    // for use in the PassesOnBeginFrameAcks test. Other supports do not receive
+    // BeginFrames, since the frame sink hierarchy is not set up in this test.
+    surface_manager_.RegisterBeginFrameSource(begin_frame_source_.get(),
+                                              kDisplayFrameSink);
+  }
+
+  void TearDown() override {
+    surface_manager_.RemoveObserver(this);
+    surface_manager_.SetDependencyTracker(nullptr);
+    surface_manager_.UnregisterBeginFrameSource(begin_frame_source_.get());
+
+    // SurfaceDependencyTracker depends on this BeginFrameSource and so it must
+    // be destroyed AFTER the dependency tracker is destroyed.
+    begin_frame_source_.reset();
+
+    supports_.clear();
+
+    damaged_surfaces_.clear();
+  }
+
+  bool IsSurfaceDamaged(const SurfaceId& surface_id) const {
+    return damaged_surfaces_.count(surface_id) > 0;
+  }
+
+  // SurfaceObserver implementation:
+  void OnSurfaceCreated(const SurfaceInfo& surface_info) override {}
+  void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) override {
+    damaged_surfaces_.insert(surface_id);
+  }
+
+ protected:
+  testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_;
+
+ private:
+  base::flat_set<SurfaceId> damaged_surfaces_;
+  SurfaceManager surface_manager_;
+  std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_;
+  std::vector<std::unique_ptr<CompositorFrameSinkSupport>> supports_;
+
+  DISALLOW_COPY_AND_ASSIGN(SurfaceSynchronizationTest);
+};
+
+// The display root surface should have a surface reference from the top-level
+// root added/removed when a CompositorFrame is submitted with a new SurfaceId.
+TEST_F(SurfaceSynchronizationTest, RootSurfaceReceivesReferences) {
+  const SurfaceId display_id_first = MakeSurfaceId(kDisplayFrameSink, 1);
+  const SurfaceId display_id_second = MakeSurfaceId(kDisplayFrameSink, 2);
+
+  // Submit a CompositorFrame for the first display root surface.
+  display_support().SubmitCompositorFrame(display_id_first.local_surface_id(),
+                                          MakeCompositorFrame());
+
+  // A surface reference from the top-level root is added and there shouldn't be
+  // a temporary reference.
+  EXPECT_FALSE(HasTemporaryReference(display_id_first));
+  EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()),
+              UnorderedElementsAre(display_id_first));
+
+  // Submit a CompositorFrame for the second display root surface.
+  display_support().SubmitCompositorFrame(display_id_second.local_surface_id(),
+                                          MakeCompositorFrame());
+
+  // A surface reference from the top-level root to |display_id_second| should
+  // be added and the reference to |display_root_first| removed.
+  EXPECT_FALSE(HasTemporaryReference(display_id_second));
+  EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()),
+              UnorderedElementsAre(display_id_second));
+
+  // Surface |display_id_first| is unreachable and should get deleted.
+  EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(display_id_first));
+}
+
+// The parent Surface is blocked on |child_id1| and |child_id2|.
+TEST_F(SurfaceSynchronizationTest, BlockedOnTwo) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id1, child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // parent_support is blocked on |child_id1| and |child_id2|.
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1, child_id2));
+
+  // Submit a CompositorFrame without any dependencies to |child_id1|.
+  // parent_support should now only be blocked on |child_id2|.
+  child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+
+  // Submit a CompositorFrame without any dependencies to |child_id2|.
+  // parent_support should be activated.
+  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+}
+
+// The parent Surface is blocked on |child_id2| which is blocked on |child_id3|.
+TEST_F(SurfaceSynchronizationTest, BlockedChain) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // parent_support is blocked on |child_id1|.
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1));
+  // The parent should not report damage until it activates.
+  EXPECT_FALSE(IsSurfaceDamaged(parent_id));
+
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame({child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // child_support1 should now be blocked on |child_id2|.
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(child_surface1()->HasActiveFrame());
+  EXPECT_TRUE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+  // The parent and child should not report damage until they activate.
+  EXPECT_FALSE(IsSurfaceDamaged(parent_id));
+  EXPECT_FALSE(IsSurfaceDamaged(child_id1));
+
+  // The parent should still be blocked on |child_id1| because it's pending.
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1));
+
+  // Submit a CompositorFrame without any dependencies to |child_id2|.
+  // parent_support should be activated.
+  child_support2().SubmitCompositorFrame(
+      child_id2.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+
+  // child_surface1 should now be active.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+
+  // parent_surface should now be active.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+
+  // All three surfaces |parent_id|, |child_id1|, and |child_id2| should
+  // now report damage. This would trigger a new display frame.
+  EXPECT_TRUE(IsSurfaceDamaged(parent_id));
+  EXPECT_TRUE(IsSurfaceDamaged(child_id1));
+  EXPECT_TRUE(IsSurfaceDamaged(child_id2));
+}
+
+// parent_surface and child_surface1 are blocked on |child_id2|.
+TEST_F(SurfaceSynchronizationTest, TwoBlockedOnOne) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // parent_support is blocked on |child_id2|.
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+
+  // child_support1 should now be blocked on |child_id2|.
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame({child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(child_surface1()->HasActiveFrame());
+  EXPECT_TRUE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+
+  // The parent should still be blocked on |child_id2|.
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+
+  // Submit a CompositorFrame without any dependencies to |child_id2|.
+  // parent_support should be activated.
+  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+
+  // child_surface1 should now be active.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+
+  // parent_surface should now be active.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+}
+
+// parent_surface is blocked on |child_id1|, and child_surface2 is blocked on
+// |child_id2| until the deadline hits.
+TEST_F(SurfaceSynchronizationTest, DeadlineHits) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // parent_support is blocked on |child_id1|.
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1));
+
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame({child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // child_support1 should now be blocked on |child_id2|.
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(child_surface1()->HasActiveFrame());
+  EXPECT_TRUE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+
+  // The parent should still be blocked on |child_id1| because it's pending.
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1));
+
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source()->TestOnBeginFrame(args);
+    // There is still a looming deadline! Eeek!
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+
+    // parent_support is still blocked on |child_id1|.
+    EXPECT_FALSE(parent_surface()->HasActiveFrame());
+    EXPECT_TRUE(parent_surface()->HasPendingFrame());
+    EXPECT_THAT(parent_surface()->blocking_surfaces(),
+                UnorderedElementsAre(child_id1));
+
+    // child_support1 is still blocked on |child_id2|.
+    EXPECT_FALSE(child_surface1()->HasActiveFrame());
+    EXPECT_TRUE(child_surface1()->HasPendingFrame());
+    EXPECT_THAT(child_surface1()->blocking_surfaces(),
+                UnorderedElementsAre(child_id2));
+  }
+
+  begin_frame_source()->TestOnBeginFrame(args);
+
+  // The deadline has passed.
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+
+  // parent_surface has been activated.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+
+  // child_surface1 has been activated.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+}
+
+// Verifies that the deadline does not reset if we submit CompositorFrames
+// to new Surfaces with unresolved dependencies.
+TEST_F(SurfaceSynchronizationTest, FramesSubmittedAfterDeadlineSet) {
+  const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  for (int i = 0; i < 3; ++i) {
+    LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create());
+    support(i).SubmitCompositorFrame(
+        local_surface_id,
+        MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
+                            TransferableResourceArray()));
+    // The deadline has been set.
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+
+    // support(i) should be blocked on arbitrary_id.
+    EXPECT_FALSE(surface(i)->HasActiveFrame());
+    EXPECT_TRUE(surface(i)->HasPendingFrame());
+    EXPECT_THAT(surface(i)->blocking_surfaces(),
+                UnorderedElementsAre(arbitrary_id));
+
+    // Issue a BeginFrame to get closer to the deadline.
+    begin_frame_source()->TestOnBeginFrame(args);
+  }
+
+  // The deadline hits and all the Surfaces should activate.
+  begin_frame_source()->TestOnBeginFrame(args);
+  for (int i = 0; i < 3; ++i) {
+    EXPECT_TRUE(surface(i)->HasActiveFrame());
+    EXPECT_FALSE(surface(i)->HasPendingFrame());
+    EXPECT_THAT(surface(i)->blocking_surfaces(), IsEmpty());
+  }
+}
+
+// This test verifies at the Surface activates once a CompositorFrame is
+// submitted that has no unresolved dependencies.
+TEST_F(SurfaceSynchronizationTest, NewFrameOverridesOldDependencies) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
+
+  // Submit a CompositorFrame that depends on |arbitrary_id|.
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // Verify that the CompositorFrame is blocked on |arbitrary_id|.
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(arbitrary_id));
+
+  // Submit a CompositorFrame that has no dependencies.
+  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  // Verify that the CompositorFrame has been activated.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+}
+
+// This test verifies that a pending CompositorFrame does not affect surface
+// references. A new surface from a child will continue to exist as a temporary
+// reference until the parent's frame activates.
+TEST_F(SurfaceSynchronizationTest, OnlyActiveFramesAffectSurfaceReferences) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  // child_support1 submits a CompositorFrame without any dependencies.
+  // DidReceiveCompositorFrameAck should call on immediate activation.
+  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(1);
+  child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+                                         MakeCompositorFrame());
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // Verify that the child surface is not blocked.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+
+  // Verify that there's a temporary reference for |child_id1|.
+  EXPECT_TRUE(HasTemporaryReference(child_id1));
+
+  // parent_support submits a CompositorFrame that depends on |child_id1|
+  // (which is already active) and |child_id2|. Thus, the parent should not
+  // activate immediately. DidReceiveCompositorFrameAck should not be called
+  // immediately because the parent CompositorFrame is also blocked on
+  // |child_id2|.
+  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id2}, {child_id1},
+                          TransferableResourceArray()));
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+  EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // Verify that there's a temporary reference for |child_id1| that still
+  // exists.
+  EXPECT_TRUE(HasTemporaryReference(child_id1));
+
+  // child_support2 submits a CompositorFrame without any dependencies.
+  // Both the child and the parent should immediately ACK CompositorFrames
+  // on activation.
+  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2);
+  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
+                                         MakeCompositorFrame());
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // Verify that the child surface is not blocked.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+
+  // Verify that the parent surface's CompositorFrame has activated and that the
+  // temporary reference has been replaced by a permanent one.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+  EXPECT_FALSE(HasTemporaryReference(child_id1));
+  EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
+}
+
+// This test verifies that we do not double count returned resources when a
+// CompositorFrame starts out as pending, then becomes active, and then is
+// replaced with another active CompositorFrame.
+TEST_F(SurfaceSynchronizationTest, ResourcesOnlyReturnedOnce) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
+
+  // The parent submits a CompositorFrame that depends on |child_id| before the
+  // child submits a CompositorFrame. The CompositorFrame also has resources in
+  // its resource list.
+  TransferableResource resource;
+  resource.id = 1337;
+  resource.format = ALPHA_8;
+  resource.filter = 1234;
+  resource.size = gfx::Size(1234, 5678);
+  TransferableResourceArray resource_list = {resource};
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id}, empty_surface_ids(), resource_list));
+
+  // Verify that the CompositorFrame is blocked on |child_id|.
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id));
+
+  child_support1().SubmitCompositorFrame(
+      child_id.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // Verify that the child CompositorFrame activates immediately.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+
+  // Verify that the parent has activated.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+
+  ReturnedResourceArray returned_resources = {resource.ToReturnedResource()};
+  EXPECT_CALL(support_client_,
+              DidReceiveCompositorFrameAck(returned_resources));
+
+  // The parent submits a CompositorFrame without any dependencies. That frame
+  // should activate immediately, replacing the earlier frame. The resource from
+  // the earlier frame should be returned to the client.
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({empty_surface_ids()}, {empty_surface_ids()},
+                          TransferableResourceArray()));
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+}
+
+// The parent Surface is blocked on |child_id2| which is blocked on |child_id3|.
+// child_support1 evicts its blocked Surface. The parent surface should
+// activate.
+TEST_F(SurfaceSynchronizationTest, EvictSurfaceWithPendingFrame) {
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  // Submit a CompositorFrame that depends on |child_id1|.
+  parent_support().SubmitCompositorFrame(
+      parent_id1.local_surface_id(),
+      MakeCompositorFrame({child_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // Verify that the CompositorFrame is blocked on |child_id1|.
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1));
+
+  // Submit a CompositorFrame that depends on |child_id2|.
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame({child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // Verify that the CompositorFrame is blocked on |child_id2|.
+  EXPECT_FALSE(child_surface1()->HasActiveFrame());
+  EXPECT_TRUE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+
+  // Evict child_support1's current Surface.
+  // TODO(fsamuel): EvictFrame => EvictCurrentSurface.
+  child_support1().EvictFrame();
+
+  // The parent Surface should immediately activate.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+}
+
+// This test verifies that if a surface has both a pending and active
+// CompositorFrame and the pending CompositorFrame activates, replacing the
+// existing active CompositorFrame, then the surface reference hierarchy will be
+// updated allowing garbage collection of surfaces that are no longer
+// referenced.
+TEST_F(SurfaceSynchronizationTest, DropStaleReferencesAfterActivation) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
+
+  // The parent submits a CompositorFrame that depends on |child_id1| before the
+  // child submits a CompositorFrame.
+  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // Verify that the CompositorFrame is blocked on |child_id|.
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id1));
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // Verify that no references are added while the CompositorFrame is pending.
+  EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
+
+  // DidReceiveCompositorFrameAck should get called twice: once for the child
+  // and once for the now active parent CompositorFrame.
+  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2);
+  child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+                                         MakeCompositorFrame());
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // Verify that the child CompositorFrame activates immediately.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
+
+  // Verify that the parent Surface has activated.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+
+  // Submit a new parent CompositorFrame to add a reference.
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), {child_id1},
+                          TransferableResourceArray()));
+
+  // Verify that the parent Surface has activated.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+
+  // Verify that there is no temporary reference for the child and that
+  // the reference from the parent to the child still exists.
+  EXPECT_FALSE(HasTemporaryReference(child_id1));
+  EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
+
+  // The parent submits another CompositorFrame that depends on |child_id2|.
+  // Submitting a pending CompositorFrame will not trigger a CompositorFrameAck.
+  EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // The parent surface should now have both a pending and activate
+  // CompositorFrame. Verify that the set of child references from
+  // |parent_id| are only from the active CompositorFrame.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(),
+              UnorderedElementsAre(child_id2));
+  EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
+
+  child_support2().SubmitCompositorFrame(child_id2.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  // Verify that the parent Surface has activated and no longer has a pending
+  // CompositorFrame. Also verify that |child_id1| is no longer a child
+  // reference of |parent_id|.
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
+  // The parent will not immediately refer to the child until it submits a new
+  // CompositorFrame with the reference.
+  EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
+}
+
+// Checks whether the latency info are moved to the new surface from the old
+// one when LocalSurfaceId changes. No frame has unresolved dependencies.
+TEST_F(SurfaceSynchronizationTest,
+       LatencyInfoCarriedOverOnResize_NoUnresolvedDependencies) {
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+  const ui::LatencyComponentType latency_type1 =
+      ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+  const int64_t latency_id1 = 234;
+  const int64_t latency_sequence_number1 = 5645432;
+  const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
+  const int64_t latency_id2 = 31434351;
+  const int64_t latency_sequence_number2 = 663788;
+
+  // Submit a frame with latency info
+  ui::LatencyInfo info;
+  info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.metadata.latency_info.push_back(info);
+
+  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
+                                         std::move(frame));
+
+  // Verify that the old surface has an active frame and no pending frame.
+  Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1);
+  ASSERT_NE(nullptr, old_surface);
+  EXPECT_TRUE(old_surface->HasActiveFrame());
+  EXPECT_FALSE(old_surface->HasPendingFrame());
+
+  // Submit another frame with some other latency info and a different
+  // LocalSurfaceId.
+  ui::LatencyInfo info2;
+  info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+
+  CompositorFrame frame2 = MakeCompositorFrame();
+  frame2.metadata.latency_info.push_back(info2);
+
+  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
+                                         std::move(frame2));
+
+  // Verify that the new surface has an active frame and no pending frames.
+  Surface* surface = surface_manager().GetSurfaceForId(parent_id2);
+  ASSERT_NE(nullptr, surface);
+  EXPECT_TRUE(surface->HasActiveFrame());
+  EXPECT_FALSE(surface->HasPendingFrame());
+
+  // Verify that the new surface has both latency info elements.
+  std::vector<ui::LatencyInfo> info_list;
+  surface->TakeLatencyInfo(&info_list);
+  EXPECT_EQ(2u, info_list.size());
+
+  ui::LatencyInfo aggregated_latency_info = info_list[0];
+  aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
+
+  // Two components are the original ones, and the third one is
+  // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
+  // submit.
+  EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
+
+  ui::LatencyInfo::LatencyComponent comp1;
+  EXPECT_TRUE(
+      aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
+  EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
+  EXPECT_TRUE(
+      aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
+  EXPECT_TRUE(aggregated_latency_info.FindLatency(
+      ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
+}
+
+// Checks whether the latency info are moved to the new surface from the old
+// one when LocalSurfaceId changes. Old surface has unresolved dependencies.
+TEST_F(SurfaceSynchronizationTest,
+       LatencyInfoCarriedOverOnResize_OldSurfaceHasPendingAndActiveFrame) {
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
+
+  const ui::LatencyComponentType latency_type1 =
+      ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+  const int64_t latency_id1 = 234;
+  const int64_t latency_sequence_number1 = 5645432;
+  const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
+  const int64_t latency_id2 = 31434351;
+  const int64_t latency_sequence_number2 = 663788;
+
+  // Submit a frame with no unresolved dependecy.
+  ui::LatencyInfo info;
+  info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.metadata.latency_info.push_back(info);
+
+  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
+                                         std::move(frame));
+
+  // Submit a frame with unresolved dependencies.
+  ui::LatencyInfo info2;
+  info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+
+  CompositorFrame frame2 = MakeCompositorFrame({child_id}, empty_surface_ids(),
+                                               TransferableResourceArray());
+  frame2.metadata.latency_info.push_back(info2);
+
+  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
+                                         std::move(frame2));
+
+  // Verify that the old surface has both an active and a pending frame.
+  Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1);
+  ASSERT_NE(nullptr, old_surface);
+  EXPECT_TRUE(old_surface->HasActiveFrame());
+  EXPECT_TRUE(old_surface->HasPendingFrame());
+
+  // Submit a frame with a new local surface id.
+  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  // Verify that the new surface has an active frame only.
+  Surface* surface = surface_manager().GetSurfaceForId(parent_id2);
+  ASSERT_NE(nullptr, surface);
+  EXPECT_TRUE(surface->HasActiveFrame());
+  EXPECT_FALSE(surface->HasPendingFrame());
+
+  // Verify that the new surface has latency info from both active and pending
+  // frame of the old surface.
+  std::vector<ui::LatencyInfo> info_list;
+  surface->TakeLatencyInfo(&info_list);
+  EXPECT_EQ(2u, info_list.size());
+
+  ui::LatencyInfo aggregated_latency_info = info_list[0];
+  aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
+
+  // Two components are the original ones, and the third one is
+  // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
+  // submit.
+  EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
+
+  ui::LatencyInfo::LatencyComponent comp1;
+  EXPECT_TRUE(
+      aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
+  EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
+  EXPECT_TRUE(
+      aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
+  EXPECT_TRUE(aggregated_latency_info.FindLatency(
+      ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
+}
+
+// Checks whether the latency info are moved to the new surface from the old
+// one when LocalSurfaceId changes. The new surface has unresolved dependencies.
+TEST_F(SurfaceSynchronizationTest,
+       LatencyInfoCarriedOverOnResize_NewSurfaceHasPendingFrame) {
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
+
+  const ui::LatencyComponentType latency_type1 =
+      ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+  const int64_t latency_id1 = 234;
+  const int64_t latency_sequence_number1 = 5645432;
+  const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
+  const int64_t latency_id2 = 31434351;
+  const int64_t latency_sequence_number2 = 663788;
+
+  // Submit a frame with no unresolved dependencies.
+  ui::LatencyInfo info;
+  info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.metadata.latency_info.push_back(info);
+
+  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
+                                         std::move(frame));
+
+  // Verify that the old surface has an active frame only.
+  Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1);
+  ASSERT_NE(nullptr, old_surface);
+  EXPECT_TRUE(old_surface->HasActiveFrame());
+  EXPECT_FALSE(old_surface->HasPendingFrame());
+
+  // Submit a frame with a new local surface id and with unresolved
+  // dependencies.
+  ui::LatencyInfo info2;
+  info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+
+  CompositorFrame frame2 = MakeCompositorFrame({child_id}, empty_surface_ids(),
+                                               TransferableResourceArray());
+  frame2.metadata.latency_info.push_back(info2);
+
+  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
+                                         std::move(frame2));
+
+  // Verify that the new surface has a pending frame and no active frame.
+  Surface* surface = surface_manager().GetSurfaceForId(parent_id2);
+  ASSERT_NE(nullptr, surface);
+  EXPECT_TRUE(surface->HasPendingFrame());
+  EXPECT_FALSE(surface->HasActiveFrame());
+
+  // Resolve the dependencies. The frame in parent's surface must become active.
+  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
+                                         MakeCompositorFrame());
+  EXPECT_FALSE(surface->HasPendingFrame());
+  EXPECT_TRUE(surface->HasActiveFrame());
+
+  // Both latency info elements must exist in the now-activated frame of the
+  // new surface.
+  std::vector<ui::LatencyInfo> info_list;
+  surface->TakeLatencyInfo(&info_list);
+  EXPECT_EQ(2u, info_list.size());
+
+  ui::LatencyInfo aggregated_latency_info = info_list[0];
+  aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
+
+  // Two components are the original ones, and the third one is
+  // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
+  // submit.
+  EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
+
+  ui::LatencyInfo::LatencyComponent comp1;
+  EXPECT_TRUE(
+      aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
+  EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
+  EXPECT_TRUE(
+      aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
+  EXPECT_TRUE(aggregated_latency_info.FindLatency(
+      ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
+}
+
+TEST_F(SurfaceSynchronizationTest, PassesOnBeginFrameAcks) {
+  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
+
+  // Request BeginFrames.
+  display_support().SetNeedsBeginFrame(true);
+
+  // Issue a BeginFrame.
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  begin_frame_source()->TestOnBeginFrame(args);
+
+  // Check that the support forwards a BeginFrameDidNotSwap ack to the
+  // BeginFrameSource.
+  BeginFrameAck ack(0, 1, 1, false);
+  display_support().BeginFrameDidNotSwap(ack);
+  EXPECT_EQ(ack, begin_frame_source()->LastAckForObserver(&display_support()));
+
+  // Issue another BeginFrame.
+  args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2);
+  begin_frame_source()->TestOnBeginFrame(args);
+
+  // Check that the support forwards the BeginFrameAck attached
+  // to a CompositorFrame to the BeginFrameSource.
+  BeginFrameAck ack2(0, 2, 2, true);
+  CompositorFrame frame = MakeCompositorFrame();
+  frame.metadata.begin_frame_ack = ack2;
+  display_support().SubmitCompositorFrame(display_id.local_surface_id(),
+                                          std::move(frame));
+  EXPECT_EQ(ack2, begin_frame_source()->LastAckForObserver(&display_support()));
+}
+
+// Checks that resources and ack are sent together if possible.
+TEST_F(SurfaceSynchronizationTest, ReturnResourcesWithAck) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  TransferableResource resource;
+  resource.id = 1234;
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
+                          {resource}));
+  ReturnedResourceArray returned_resources;
+  TransferableResource::ReturnResources({resource}, &returned_resources);
+  EXPECT_CALL(support_client_, ReclaimResources(_)).Times(0);
+  EXPECT_CALL(support_client_,
+              DidReceiveCompositorFrameAck(Eq(returned_resources)));
+  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
+                                         MakeCompositorFrame());
+}
+
+// Verifies that if a surface is marked destroyed and a new frame arrives for
+// it, it will be recovered.
+TEST_F(SurfaceSynchronizationTest, SurfaceResurrection) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3);
+
+  // Create the child surface by submitting a frame to it.
+  EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id));
+  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  // Verify that the child surface is created.
+  Surface* surface = surface_manager().GetSurfaceForId(child_id);
+  EXPECT_NE(nullptr, surface);
+
+  // Add a reference from the parent to the child.
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id}, {child_id}, TransferableResourceArray()));
+
+  // Attempt to destroy the child surface. The surface must still exist since
+  // the parent needs it but it will be marked as destroyed.
+  child_support1().EvictFrame();
+  surface = surface_manager().GetSurfaceForId(child_id);
+  EXPECT_NE(nullptr, surface);
+  EXPECT_TRUE(surface->destroyed());
+
+  // Child submits another frame to the same local surface id that is marked
+  // destroyed.
+  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  // Verify that the surface that was marked destroyed is recovered and is being
+  // used again.
+  Surface* surface2 = surface_manager().GetSurfaceForId(child_id);
+  EXPECT_EQ(surface, surface2);
+  EXPECT_FALSE(surface2->destroyed());
+}
+
+// Verifies that if a LocalSurfaceId belonged to a surface that doesn't exist
+// anymore, it can still be reused for new surfaces.
+TEST_F(SurfaceSynchronizationTest, LocalSurfaceIdIsReusable) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3);
+
+  // Submit the first frame. Creates the surface.
+  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
+                                         MakeCompositorFrame());
+  EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id));
+
+  // Add a reference from parent.
+  parent_support().SubmitCompositorFrame(
+      parent_id.local_surface_id(),
+      MakeCompositorFrame({child_id}, {child_id}, TransferableResourceArray()));
+
+  // Remove the reference from parant. This allows us to destroy the surface.
+  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  // Destroy the surface.
+  child_support1().EvictFrame();
+  EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id));
+
+  // Submit another frame with the same local surface id. This should work fine
+  // and a new surface must be created.
+  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
+                                         MakeCompositorFrame());
+  EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id));
+}
+
+// This test verifies that a crash does not occur if garbage collection is
+// triggered during surface dependency resolution. This test triggers garbage
+// collection during surface resolution, by causing an activation to remove
+// a surface subtree from the root. Both the old subtree and the new
+// activated subtree refer to the same dependency. The old subtree was activated
+// by deadline, and the new subtree was activated by a dependency finally
+// resolving.
+TEST_F(SurfaceSynchronizationTest, DependencyTrackingGarbageCollection) {
+  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
+
+  parent_support().SubmitCompositorFrame(
+      parent_id1.local_surface_id(),
+      MakeCompositorFrame({child_id}, empty_surface_ids(),
+                          TransferableResourceArray()));
+  display_support().SubmitCompositorFrame(
+      display_id.local_surface_id(),
+      MakeCompositorFrame({parent_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+
+  // Advance BeginFrames to trigger a deadline.
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source()->TestOnBeginFrame(args);
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+  }
+  begin_frame_source()->TestOnBeginFrame(args);
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+
+  EXPECT_TRUE(display_surface()->HasActiveFrame());
+  EXPECT_FALSE(display_surface()->HasPendingFrame());
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+
+  parent_support().SubmitCompositorFrame(
+      parent_id2.local_surface_id(),
+      MakeCompositorFrame({child_id}, empty_surface_ids(),
+                          TransferableResourceArray()));
+  display_support().SubmitCompositorFrame(
+      display_id.local_surface_id(),
+      MakeCompositorFrame({parent_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // The display surface now has two CompositorFrames. One that is pending,
+  // indirectly blocked on child_id and one that is active, also indirectly
+  // referring to child_id, but activated due to the deadline above.
+  EXPECT_TRUE(display_surface()->HasActiveFrame());
+  EXPECT_TRUE(display_surface()->HasPendingFrame());
+
+  // Submitting a CompositorFrame will trigger garbage collection of the
+  // |parent_id1| subtree. This should not crash.
+  child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
+                                         MakeCompositorFrame());
+}
+
+// This test verifies that a crash does not occur if garbage collection is
+// triggered when a deadline forces frame activation. This test triggers garbage
+// collection during deadline activation by causing the activation of a display
+// frame to replace a previously activated display frame that was referring to
+// a now-unreachable surface subtree. That subtree gets garbage collected during
+// deadline activation. SurfaceDependencyTracker is also tracking a surface
+// from that subtree due to an unresolved dependency. This test verifies that
+// this dependency resolution does not crash.
+TEST_F(SurfaceSynchronizationTest, GarbageCollectionOnDeadline) {
+  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
+
+  // |parent_id1| is blocked on |child_id|.
+  parent_support().SubmitCompositorFrame(
+      parent_id1.local_surface_id(),
+      MakeCompositorFrame({child_id}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  display_support().SubmitCompositorFrame(
+      display_id.local_surface_id(),
+      MakeCompositorFrame({parent_id1}, {parent_id1},
+                          TransferableResourceArray()));
+
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_TRUE(display_surface()->HasPendingFrame());
+  EXPECT_FALSE(display_surface()->HasActiveFrame());
+
+  // Advance BeginFrames to trigger a deadline. This activates the
+  // CompositorFrame submitted above.
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source()->TestOnBeginFrame(args);
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+  }
+  begin_frame_source()->TestOnBeginFrame(args);
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(display_surface()->HasPendingFrame());
+  EXPECT_TRUE(display_surface()->HasActiveFrame());
+
+  // By submitting a display CompositorFrame, and replacing the parent's
+  // CompositorFrame with another surface ID, parent_id1 becomes unreachable and
+  // a candidate for garbage collection.
+  display_support().SubmitCompositorFrame(
+      display_id.local_surface_id(),
+      MakeCompositorFrame({parent_id2}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // Now |parent_id1| is only kept alive by the active |display_id| frame.
+  parent_support().SubmitCompositorFrame(
+      parent_id2.local_surface_id(),
+      MakeCompositorFrame({child_id}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  // SurfaceDependencyTracker should now be tracking |display_id|, |parent_id1|
+  // and |parent_id2|. By activating the pending |display_id| frame by deadline,
+  // |parent_id1| becomes unreachable and is garbage collected while
+  // SurfaceDependencyTracker is in the process of activating surfaces. This
+  // should not cause a crash or use-after-free.
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source()->TestOnBeginFrame(args);
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+  }
+  begin_frame_source()->TestOnBeginFrame(args);
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+}
+
+// This test verifies that a CompositorFrame will only blocked on embedded
+// surfaces but not on other retained surface IDs in the CompositorFrame.
+TEST_F(SurfaceSynchronizationTest, OnlyBlockOnEmbeddedSurfaces) {
+  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+
+  // Submitting a CompositorFrame with |parent_id2| so that the display
+  // CompositorFrame can hold a reference to it.
+  parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  display_support().SubmitCompositorFrame(
+      display_id.local_surface_id(),
+      MakeCompositorFrame({parent_id1}, {parent_id2},
+                          TransferableResourceArray()));
+
+  EXPECT_TRUE(display_surface()->HasPendingFrame());
+  EXPECT_FALSE(display_surface()->HasActiveFrame());
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+
+  // Verify that the display CompositorFrame will only block on |parent_id1| but
+  // not |parent_id2|.
+  EXPECT_THAT(display_surface()->blocking_surfaces(),
+              UnorderedElementsAre(parent_id1));
+  // Verify that the display surface holds no references while its
+  // CompositorFrame is pending.
+  EXPECT_THAT(GetChildReferences(display_id), IsEmpty());
+
+  // Submitting a CompositorFrame with |parent_id1| should unblock the display
+  // CompositorFrame.
+  parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
+                                         MakeCompositorFrame());
+
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(display_surface()->HasPendingFrame());
+  EXPECT_TRUE(display_surface()->HasActiveFrame());
+  EXPECT_THAT(display_surface()->blocking_surfaces(), IsEmpty());
+}
+
+// This test verifies that a late arriving CompositorFrame activates immediately
+// and does not trigger a new deadline.
+TEST_F(SurfaceSynchronizationTest, LateArrivingDependency) {
+  const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+
+  display_support().SubmitCompositorFrame(
+      display_id.local_surface_id(),
+      MakeCompositorFrame({parent_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+
+  EXPECT_TRUE(display_surface()->HasPendingFrame());
+  EXPECT_FALSE(display_surface()->HasActiveFrame());
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+
+  // Advance BeginFrames to trigger a deadline. This activates the
+  // CompositorFrame submitted above.
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source()->TestOnBeginFrame(args);
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+  }
+  begin_frame_source()->TestOnBeginFrame(args);
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(display_surface()->HasPendingFrame());
+  EXPECT_TRUE(display_surface()->HasActiveFrame());
+
+  // A late arriving CompositorFrame should activate immediately without
+  // scheduling a deadline and without waiting for dependencies to resolve.
+  parent_support().SubmitCompositorFrame(
+      parent_id1.local_surface_id(),
+      MakeCompositorFrame({child_id1}, empty_surface_ids(),
+                          TransferableResourceArray()));
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+}
+
+// This test verifies that CompositorFrames submitted to a surface referenced
+// by a parent CompositorFrame as a fallback will be rejected and ACK'ed
+// immediately.
+TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
+  const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+  // This is the fallback child surface that the parent holds a reference to.
+  const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+  // This is the primary child surface that the parent wants to block on.
+  const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 2);
+
+  // child_support1 submits a CompositorFrame without any dependencies.
+  // DidReceiveCompositorFrameAck should call on immediate activation.
+  // However, resources will not be returned because this frame is a candidate
+  // for display.
+  TransferableResource resource;
+  resource.id = 1337;
+  resource.format = ALPHA_8;
+  resource.filter = 1234;
+  resource.size = gfx::Size(1234, 5678);
+  ReturnedResourceArray returned_resources;
+  TransferableResource::ReturnResources({resource}, &returned_resources);
+
+  EXPECT_CALL(support_client_,
+              DidReceiveCompositorFrameAck(Eq(ReturnedResourceArray())));
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
+                          {resource}));
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // The parent is blocked on |child_id2| and references |child_id1|. The
+  // surface corresponding to |child_id1| will not accept new CompositorFrames
+  // while the parent CompositorFrame is blocked.
+  parent_support().SubmitCompositorFrame(
+      parent_id1.local_surface_id(),
+      MakeCompositorFrame({child_id2}, {child_id1},
+                          TransferableResourceArray()));
+  EXPECT_TRUE(dependency_tracker().has_deadline());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_FALSE(parent_surface()->HasActiveFrame());
+
+  // Resources will be returned immediately because |child_id1|'s surface is
+  // closed.
+  TransferableResource resource2;
+  resource2.id = 1246;
+  resource2.format = ALPHA_8;
+  resource2.filter = 1357;
+  resource2.size = gfx::Size(8765, 4321);
+  ReturnedResourceArray returned_resources2;
+  TransferableResource::ReturnResources({resource2}, &returned_resources2);
+  EXPECT_CALL(support_client_,
+              DidReceiveCompositorFrameAck(Eq(returned_resources2)));
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
+                          {resource2}));
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+
+  // Advance BeginFrames to trigger a deadline. This activates the
+  // CompositorFrame submitted to the parent.
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  for (int i = 0; i < 3; ++i) {
+    begin_frame_source()->TestOnBeginFrame(args);
+    EXPECT_TRUE(dependency_tracker().has_deadline());
+  }
+  begin_frame_source()->TestOnBeginFrame(args);
+  EXPECT_FALSE(dependency_tracker().has_deadline());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+
+  // Resources will be returned immediately because |child_id1|'s surface is
+  // closed forever.
+  EXPECT_CALL(support_client_,
+              DidReceiveCompositorFrameAck(Eq(returned_resources2)));
+  child_support1().SubmitCompositorFrame(
+      child_id1.local_surface_id(),
+      MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
+                          {resource2}));
+  testing::Mock::VerifyAndClearExpectations(&support_client_);
+}
+
+}  // namespace test
+}  // namespace cc
diff --git a/cc/test/compositor_frame_helpers.cc b/cc/test/compositor_frame_helpers.cc
index 23cc993..33e0ed63 100644
--- a/cc/test/compositor_frame_helpers.cc
+++ b/cc/test/compositor_frame_helpers.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "cc/test/compositor_frame_helpers.h"
+
 #include "cc/output/compositor_frame.h"
 
 namespace cc {
@@ -25,5 +26,19 @@
   return frame;
 }
 
+CompositorFrame MakeCompositorFrame(
+    std::vector<SurfaceId> activation_dependencies,
+    std::vector<SurfaceId> referenced_surfaces,
+    TransferableResourceArray resource_list) {
+  CompositorFrame compositor_frame = test::MakeCompositorFrame();
+  compositor_frame.metadata.begin_frame_ack = BeginFrameAck(0, 1, 1, true);
+  compositor_frame.metadata.activation_dependencies =
+      std::move(activation_dependencies);
+  compositor_frame.metadata.referenced_surfaces =
+      std::move(referenced_surfaces);
+  compositor_frame.resource_list = std::move(resource_list);
+  return compositor_frame;
+}
+
 }  // namespace test
 }  // namespace cc
diff --git a/cc/test/compositor_frame_helpers.h b/cc/test/compositor_frame_helpers.h
index c60de21..32356e6 100644
--- a/cc/test/compositor_frame_helpers.h
+++ b/cc/test/compositor_frame_helpers.h
@@ -5,6 +5,11 @@
 #ifndef CC_TEST_COMPOSITOR_FRAME_HELPERS_H_
 #define CC_TEST_COMPOSITOR_FRAME_HELPERS_H_
 
+#include <vector>
+
+#include "cc/resources/transferable_resource.h"
+#include "cc/surfaces/surface_id.h"
+
 namespace cc {
 
 class CompositorFrame;
@@ -18,6 +23,11 @@
 // initialized.
 CompositorFrame MakeEmptyCompositorFrame();
 
+CompositorFrame MakeCompositorFrame(
+    std::vector<SurfaceId> activation_dependencies,
+    std::vector<SurfaceId> referenced_surfaces,
+    TransferableResourceArray resource_list);
+
 }  // namespace test
 }  // namespace cc
 
diff --git a/cc/test/mock_compositor_frame_sink_support_client.cc b/cc/test/mock_compositor_frame_sink_support_client.cc
new file mode 100644
index 0000000..758c87d8
--- /dev/null
+++ b/cc/test/mock_compositor_frame_sink_support_client.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/mock_compositor_frame_sink_support_client.h"
+
+#include "cc/output/begin_frame_args.h"
+#include "cc/surfaces/local_surface_id.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace cc {
+namespace test {
+
+MockCompositorFrameSinkSupportClient::MockCompositorFrameSinkSupportClient() =
+    default;
+
+MockCompositorFrameSinkSupportClient::~MockCompositorFrameSinkSupportClient() =
+    default;
+
+}  // namespace test
+
+}  // namespace cc
diff --git a/cc/test/mock_compositor_frame_sink_support_client.h b/cc/test/mock_compositor_frame_sink_support_client.h
new file mode 100644
index 0000000..792bb9d
--- /dev/null
+++ b/cc/test/mock_compositor_frame_sink_support_client.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_MOCK_COMPOSITOR_FRAME_SINK_SUPPORT_CLIENT_H_
+#define CC_TEST_MOCK_COMPOSITOR_FRAME_SINK_SUPPORT_CLIENT_H_
+
+#include "cc/surfaces/compositor_frame_sink_support_client.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace cc {
+namespace test {
+
+class MockCompositorFrameSinkSupportClient
+    : public CompositorFrameSinkSupportClient {
+ public:
+  MockCompositorFrameSinkSupportClient();
+  ~MockCompositorFrameSinkSupportClient() override;
+
+  // CompositorFrameSinkSupportClient implementation.
+  MOCK_METHOD1(DidReceiveCompositorFrameAck,
+               void(const ReturnedResourceArray&));
+  MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&));
+  MOCK_METHOD1(ReclaimResources, void(const ReturnedResourceArray&));
+  MOCK_METHOD2(WillDrawSurface, void(const LocalSurfaceId&, const gfx::Rect&));
+};
+
+}  // namespace test
+}  // namespace cc
+
+#endif  // CC_TEST_MOCK_COMPOSITOR_FRAME_SINK_SUPPORT_CLIENT_H_
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 493eb02..7e193ca 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -167,6 +167,7 @@
     ":chrome_public_android_manifest",
     ":chrome_public_apk_template_resources",
     ":document_tab_model_info_proto_java",
+    ":partner_location_descriptor_proto_java",
     "//base:base_java",
     "//chrome/android/webapk/libs/client:client_java",
     "//chrome/android/webapk/libs/common:common_java",
@@ -321,6 +322,13 @@
   ]
 }
 
+proto_java_library("partner_location_descriptor_proto_java") {
+  proto_path = "java/src/org/chromium/chrome/browser/omnibox/geo"
+  sources = [
+    "$proto_path/partner_location_descriptor.proto",
+  ]
+}
+
 java_cpp_template("resource_id_javagen") {
   sources = [
     "java/ResourceId.template",
@@ -423,6 +431,7 @@
   }
 
   deps = [
+    ":partner_location_descriptor_proto_java",
     "//base:base_java",
     "//base:base_java_test_support",
     "//chrome/android:app_hooks_java",
@@ -474,6 +483,7 @@
     "//third_party/WebKit/public:android_mojo_bindings_java",
     "//third_party/WebKit/public:blink_headers_java",
     "//third_party/WebKit/public:mojo_bindings_java",
+    "//third_party/android_protobuf:protobuf_nano_javalib",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/android_tools:android_support_design_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index ffaaa4d..6afd8e2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -192,6 +192,7 @@
     public static final String WEB_PAYMENTS_MODIFIERS = "WebPaymentsModifiers";
     public static final String WEB_PAYMENTS_SINGLE_APP_UI_SKIP = "WebPaymentsSingleAppUiSkip";
     public static final String WEBVR_CARDBOARD_SUPPORT = "WebVRCardboardSupport";
+    public static final String XGEO_VISIBLE_NETWORKS = "XGEOVisibleNetworks";
 
     private static native boolean nativeIsInitialized();
     private static native boolean nativeIsEnabled(String featureName);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
index d403e34..aca80473 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
@@ -16,6 +16,8 @@
 import android.support.annotation.IntDef;
 import android.util.Base64;
 
+import com.google.protobuf.nano.MessageNano;
+
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -183,6 +185,15 @@
     /** The maximum age in milliseconds of a location before we'll request a refresh. */
     private static final int REFRESH_LOCATION_AGE = 5 * 60 * 1000;  // 5 minutes
 
+    /** The X-Geo header prefix, preceding any location descriptors */
+    private static final String XGEO_HEADER_PREFIX = "X-Geo: ";
+
+    /** The location descriptor prefix used in the X-Geo header to specify a proto wire encoding */
+    private static final String LOCATION_PROTO_PREFIX = "w ";
+
+    /** The location descriptor prefix used in the X-Geo header to specify an ASCII encoding */
+    private static final String LOCATION_ASCII_PREFIX = "a ";
+
     /** The time of the first location refresh. Contains Long.MAX_VALUE if not set. */
     private static long sFirstLocationTime = Long.MAX_VALUE;
 
@@ -301,9 +312,9 @@
         // Timestamp in microseconds since the UNIX epoch.
         long timestamp = location.getTime() * 1000;
         // Latitude times 1e7.
-        int latitude = (int) (location.getLatitude() * 10000000);
+        int latitudeE7 = (int) (location.getLatitude() * 10000000);
         // Longitude times 1e7.
-        int longitude = (int) (location.getLongitude() * 10000000);
+        int longitudeE7 = (int) (location.getLongitude() * 10000000);
         // Radius of 68% accuracy in mm.
         int radius = (int) (location.getAccuracy() * 1000);
 
@@ -311,10 +322,35 @@
         // https://goto.google.com/partner_location_proto
         String locationAscii = String.format(Locale.US,
                 "role:1 producer:12 timestamp:%d latlng{latitude_e7:%d longitude_e7:%d} radius:%d",
-                timestamp, latitude, longitude, radius);
-        String locationBase64 = new String(Base64.encode(locationAscii.getBytes(), Base64.NO_WRAP));
+                timestamp, latitudeE7, longitudeE7, radius);
+        String locationAsciiEncoding =
+                new String(Base64.encode(locationAscii.getBytes(), Base64.NO_WRAP));
 
-        return "X-Geo: a " + locationBase64;
+        boolean isXGeoVisibleNetworksEnabled =
+                ChromeFeatureList.isEnabled(ChromeFeatureList.XGEO_VISIBLE_NETWORKS);
+        if (!isXGeoVisibleNetworksEnabled) {
+            return XGEO_HEADER_PREFIX + LOCATION_ASCII_PREFIX + locationAsciiEncoding;
+        }
+
+        // Create a LatLng for the coordinates.
+        PartnerLocationDescriptor.LatLng latlng = new PartnerLocationDescriptor.LatLng();
+        latlng.latitudeE7 = latitudeE7;
+        latlng.longitudeE7 = longitudeE7;
+
+        // Populate a LocationDescriptor with the LatLng.
+        PartnerLocationDescriptor.LocationDescriptor locationDescriptor =
+                new PartnerLocationDescriptor.LocationDescriptor();
+        locationDescriptor.latlng = latlng;
+        // Include role, producer, timestamp and radius.
+        locationDescriptor.role = PartnerLocationDescriptor.CURRENT_LOCATION;
+        locationDescriptor.producer = PartnerLocationDescriptor.DEVICE_LOCATION;
+        locationDescriptor.timestamp = timestamp;
+        locationDescriptor.radius = (float) radius;
+
+        String locationProtoEncoding = Base64.encodeToString(
+                MessageNano.toByteArray(locationDescriptor), Base64.NO_WRAP | Base64.URL_SAFE);
+
+        return XGEO_HEADER_PREFIX + LOCATION_PROTO_PREFIX + locationProtoEncoding;
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto
new file mode 100644
index 0000000..e1b36c4e
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto
@@ -0,0 +1,81 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Protocol buffer definition for a location descriptor, used for sending
+// geographical information to the Default Search Engine in omnibox queries
+// when location permissions are granted.
+//
+// TODO(lbargu): Move over to standard Geo header once it is defined, and remove
+// this proto structure from chromium code base.
+//
+// NOTE: This is currently using a Google-defined structure. This explains the
+// jumps in values. New fields cannot be added to this proto directly. See
+// https://goto.google.com/partner_location_proto
+
+syntax = "proto2";
+
+package org.chromium.chrome.browser.omnibox.geo;
+
+option java_outer_classname = "PartnerLocationDescriptor";
+option java_package = "org.chromium.chrome.browser.omnibox.geo";
+
+enum LocationRole {
+  UNKNOWN_ROLE = 0;
+  CURRENT_LOCATION = 1;
+}
+
+enum LocationProducer {
+  UNKNOWN_PRODUCER = 0;
+  DEVICE_LOCATION = 12;
+}
+
+message LatLng {
+  optional sfixed32 latitude_e7 = 1;
+  optional sfixed32 longitude_e7 = 2;
+}
+
+message VisibleNetwork {
+
+  message WiFi {
+    optional string bssid = 1;
+    optional int32 level_dbm = 2;
+  }
+
+  message Cell {
+
+    enum Type {
+      UNKNOWN = 0;
+      GSM = 1;
+      LTE = 2;
+      CDMA = 3;
+      WCDMA = 4;
+    }
+
+    optional Type type = 1;
+    optional int32 cell_id = 2;
+    optional int32 location_area_code = 3;
+    optional int32 mobile_country_code = 4;
+    optional int32 mobile_network_code = 5;
+    optional int32 primary_scrambling_code = 6;
+    optional int32 physical_cell_id = 7;
+    optional int32 tracking_area_code = 8;
+  }
+
+  oneof type {
+    WiFi wifi = 1;
+    Cell cell = 2;
+  }
+
+  optional bool connected = 3;
+  optional int64 timestamp_ms = 4;
+}
+
+message LocationDescriptor {
+  optional LocationRole role = 1 [default = UNKNOWN_ROLE];
+  optional LocationProducer producer = 2 [default = UNKNOWN_PRODUCER];
+  optional int64 timestamp = 3;
+  optional LatLng latlng = 5;
+  optional float radius = 7;
+  repeated VisibleNetwork visible_network = 23;
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
index a0ed7d3..090267f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
@@ -9,6 +9,9 @@
 import android.os.Build;
 import android.os.SystemClock;
 import android.support.test.filters.SmallTest;
+import android.util.Base64;
+
+import com.google.protobuf.nano.MessageNano;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.library_loader.ProcessInitException;
@@ -22,6 +25,8 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
 
+import java.util.Locale;
+
 /**
  * Tests for GeolocationHeader and GeolocationTracker.
  */
@@ -32,7 +37,16 @@
             "enable-features=ConsistentOmniboxGeolocation";
     private static final String DISABLE_CONSISTENT_GEOLOCATION_FEATURE =
             "disable-features=ConsistentOmniboxGeolocation";
+    private static final String ENABLE_XGEO_VISIBLE_NETWORKS =
+            "enable-features=XGEOVisibleNetworks";
+    private static final String DISABLE_XGEO_VISIBLE_NETWORKS =
+            "disable-features=XGEOVisibleNetworks";
     private static final String GOOGLE_BASE_URL_SWITCH = "google-base-url=https://www.google.com";
+    private static final double LOCATION_LAT = 20.3;
+    private static final double LOCATION_LONG = 155.8;
+    private static final float LOCATION_ACCURACY = 20f;
+    private static final boolean ENCODING_PROTO = true;
+    private static final boolean ENCODING_ASCII = false;
 
     public GeolocationHeaderTest() {
         super(ChromeActivity.class);
@@ -51,13 +65,13 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add(DISABLE_CONSISTENT_GEOLOCATION_FEATURE)
+    @CommandLineFlags.Add({DISABLE_CONSISTENT_GEOLOCATION_FEATURE, DISABLE_XGEO_VISIBLE_NETWORKS})
     public void testGeolocationHeader() throws ProcessInitException {
-        setMockLocation(20.3, 155.8, System.currentTimeMillis());
+        long now = setMockLocationNow();
 
         // X-Geo should be sent for Google search results page URLs.
-        assertNonNullHeader(SEARCH_URL_1, false);
-        assertNonNullHeader(SEARCH_URL_2, false);
+        assertNonNullHeader(SEARCH_URL_1, false, now, ENCODING_ASCII);
+        assertNonNullHeader(SEARCH_URL_2, false, now, ENCODING_ASCII);
 
         // X-Geo shouldn't be sent in incognito mode.
         assertNullHeader(SEARCH_URL_1, true);
@@ -75,12 +89,13 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH})
+    @CommandLineFlags.Add({ENABLE_CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH,
+            DISABLE_XGEO_VISIBLE_NETWORKS})
     public void testConsistentHeader() throws ProcessInitException {
-        setMockLocation(20.3, 155.8, System.currentTimeMillis());
+        long now = setMockLocationNow();
 
         // X-Geo should be sent for Google search results page URLs.
-        assertNonNullHeader(SEARCH_URL_1, false);
+        assertNonNullHeader(SEARCH_URL_1, false, now, ENCODING_ASCII);
 
         // But only the current CCTLD.
         assertNullHeader(SEARCH_URL_2, false);
@@ -103,47 +118,68 @@
     @Feature({"Location"})
     @CommandLineFlags.Add(DISABLE_CONSISTENT_GEOLOCATION_FEATURE)
     public void testPermissions() throws ProcessInitException {
-        setMockLocation(20.3, 155.8, System.currentTimeMillis());
+        long now = setMockLocationNow();
 
         // X-Geo shouldn't be sent when location is disallowed for https origin.
-        checkHeaderWithPermissions(ContentSetting.ALLOW, false);
-        checkHeaderWithPermissions(ContentSetting.DEFAULT, false);
-        checkHeaderWithPermissions(ContentSetting.BLOCK, true);
+        checkHeaderWithPermissions(ContentSetting.ALLOW, now, false);
+        checkHeaderWithPermissions(ContentSetting.DEFAULT, now, false);
+        checkHeaderWithPermissions(ContentSetting.BLOCK, now, true);
     }
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH})
+    @CommandLineFlags.Add({ENABLE_CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH,
+            DISABLE_XGEO_VISIBLE_NETWORKS})
     public void testPermissionAndSetting() throws ProcessInitException {
-        setMockLocation(20.3, 155.8, System.currentTimeMillis());
+        long now = setMockLocationNow();
 
         // X-Geo shouldn't be sent when location is disallowed for the origin, or when the DSE
         // geolocation setting is off.
-        checkHeaderWithPermissionAndSetting(ContentSetting.ALLOW, true, false);
-        checkHeaderWithPermissionAndSetting(ContentSetting.DEFAULT, true, false);
-        checkHeaderWithPermissionAndSetting(ContentSetting.DEFAULT, false, true);
-        checkHeaderWithPermissionAndSetting(ContentSetting.BLOCK, false, true);
+        checkHeaderWithPermissionAndSetting(ContentSetting.ALLOW, true, now, false);
+        checkHeaderWithPermissionAndSetting(ContentSetting.DEFAULT, true, now, false);
+        checkHeaderWithPermissionAndSetting(ContentSetting.DEFAULT, false, now, true);
+        checkHeaderWithPermissionAndSetting(ContentSetting.BLOCK, false, now, true);
     }
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add(DISABLE_CONSISTENT_GEOLOCATION_FEATURE)
+    @CommandLineFlags.Add({DISABLE_CONSISTENT_GEOLOCATION_FEATURE, DISABLE_XGEO_VISIBLE_NETWORKS})
     public void testOnlyNonStale() throws ProcessInitException {
-        setMockLocation(20.3, 155.8, System.currentTimeMillis());
-
         // X-Geo should be sent only with non-stale locations.
         long now = System.currentTimeMillis();
         long oneHour = 60 * 60 * 1000;
         long oneWeek = 7 * 24 * 60 * 60 * 1000;
-        checkHeaderWithLocation(20.3, 155.8, now, false);
-        checkHeaderWithLocation(20.3, 155.8, now - oneHour, false);
-        checkHeaderWithLocation(20.3, 155.8, now - oneWeek, true);
+        setMockLocation(now);
+
+        checkHeaderWithLocation(now, false);
+        checkHeaderWithLocation(now - oneHour, false);
+        checkHeaderWithLocation(now - oneWeek, true);
         GeolocationTracker.setLocationForTesting(null);
         assertNullHeader(SEARCH_URL_1, false);
     }
 
-    private void checkHeaderWithPermissions(
-            final ContentSetting httpsPermission, final boolean shouldBeNull) {
+    @SmallTest
+    @Feature({"Location"})
+    @CommandLineFlags.Add({DISABLE_XGEO_VISIBLE_NETWORKS})
+    public void testAsciiEncoding() throws ProcessInitException {
+        long now = setMockLocationNow();
+
+        // X-Geo should be sent for Google search results page URLs using ascii encoding.
+        assertNonNullHeader(SEARCH_URL_1, false, now, ENCODING_ASCII);
+    }
+
+    @SmallTest
+    @Feature({"Location"})
+    @CommandLineFlags.Add({ENABLE_XGEO_VISIBLE_NETWORKS})
+    public void testProtoEncoding() throws ProcessInitException {
+        long now = setMockLocationNow();
+
+        // X-Geo should be sent for Google search results page URLs using proto encoding.
+        assertNonNullHeader(SEARCH_URL_1, false, now, ENCODING_PROTO);
+    }
+
+    private void checkHeaderWithPermissions(final ContentSetting httpsPermission,
+            final long locationTime, final boolean shouldBeNull) {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -153,13 +189,13 @@
                 String header = GeolocationHeader.getGeoHeader(
                         "https://www.google.de/search?q=kartoffelsalat",
                         getActivity().getActivityTab());
-                assertHeaderState(header, shouldBeNull);
+                assertHeaderState(header, locationTime, shouldBeNull);
             }
         });
     }
 
     private void checkHeaderWithPermissionAndSetting(final ContentSetting httpsPermission,
-            final boolean settingValue, final boolean shouldBeNull) {
+            final boolean settingValue, final long locationTime, final boolean shouldBeNull) {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -169,37 +205,42 @@
                 WebsitePreferenceBridge.setDSEGeolocationSetting(settingValue);
                 String header = GeolocationHeader.getGeoHeader(
                         SEARCH_URL_1, getActivity().getActivityTab());
-                assertHeaderState(header, shouldBeNull);
+                assertHeaderState(header, locationTime, shouldBeNull);
             }
         });
     }
 
-    private void checkHeaderWithLocation(final double latitute, final double longitude,
-            final long time, final boolean shouldBeNull) {
+    private void checkHeaderWithLocation(final long locationTime, final boolean shouldBeNull) {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                setMockLocation(latitute, longitude, time);
+                setMockLocation(locationTime);
                 String header = GeolocationHeader.getGeoHeader(SEARCH_URL_1,
                         getActivity().getActivityTab());
-                assertHeaderState(header, shouldBeNull);
+                assertHeaderState(header, locationTime, shouldBeNull);
             }
         });
     }
 
-    private void assertHeaderState(String header, boolean shouldBeNull) {
+    private void assertHeaderState(String header, long locationTime, boolean shouldBeNull) {
         if (shouldBeNull) {
             assertNull(header);
         } else {
-            assertNotNull(header);
+            assertHeaderEquals(locationTime, ENCODING_ASCII, header);
         }
     }
 
-    private void setMockLocation(double latitute, double longitude, long time) {
+    private long setMockLocationNow() {
+        long now = System.currentTimeMillis();
+        setMockLocation(now);
+        return now;
+    }
+
+    private void setMockLocation(long time) {
         final Location location = new Location(LocationManager.NETWORK_PROVIDER);
-        location.setLatitude(latitute);
-        location.setLongitude(longitude);
-        location.setAccuracy(20f);
+        location.setLatitude(LOCATION_LAT);
+        location.setLongitude(LOCATION_LONG);
+        location.setAccuracy(LOCATION_ACCURACY);
         location.setTime(time);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
             location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()
@@ -222,13 +263,15 @@
         }
     }
 
-    private void assertNonNullHeader(final String url, final boolean isIncognito) {
+    private void assertNonNullHeader(final String url, final boolean isIncognito,
+            final long locationTime, final boolean encodingType) {
         try {
             final Tab tab = loadUrlInNewTab("about:blank", isIncognito);
             ThreadUtils.runOnUiThreadBlocking(new Runnable() {
                 @Override
                 public void run() {
-                    assertNotNull(GeolocationHeader.getGeoHeader(url, tab));
+                    assertHeaderEquals(
+                            locationTime, encodingType, GeolocationHeader.getGeoHeader(url, tab));
                 }
             });
         } catch (InterruptedException e) {
@@ -236,6 +279,47 @@
         }
     }
 
+    private void assertHeaderEquals(long locationTime, boolean encodingType, String header) {
+        long timestamp = locationTime * 1000;
+        // Latitude times 1e7.
+        int latitudeE7 = (int) (LOCATION_LAT * 10000000);
+        // Longitude times 1e7.
+        int longitudeE7 = (int) (LOCATION_LONG * 10000000);
+        // Radius of 68% accuracy in mm.
+        int radius = (int) (LOCATION_ACCURACY * 1000);
+
+        String expectedHeader;
+        if (encodingType == ENCODING_PROTO) {
+            // Create a LatLng for the coordinates.
+            PartnerLocationDescriptor.LatLng latlng = new PartnerLocationDescriptor.LatLng();
+            latlng.latitudeE7 = latitudeE7;
+            latlng.longitudeE7 = longitudeE7;
+
+            // Populate a LocationDescriptor with the LatLng.
+            PartnerLocationDescriptor.LocationDescriptor locationDescriptor =
+                    new PartnerLocationDescriptor.LocationDescriptor();
+            locationDescriptor.latlng = latlng;
+            // Include role, producer, timestamp and radius.
+            locationDescriptor.role = PartnerLocationDescriptor.CURRENT_LOCATION;
+            locationDescriptor.producer = PartnerLocationDescriptor.DEVICE_LOCATION;
+            locationDescriptor.timestamp = timestamp;
+            locationDescriptor.radius = (float) radius;
+
+            String locationProto = Base64.encodeToString(
+                    MessageNano.toByteArray(locationDescriptor), Base64.NO_WRAP | Base64.URL_SAFE);
+            expectedHeader = "X-Geo: w " + locationProto;
+        } else {
+            assertEquals(ENCODING_ASCII, encodingType);
+            String locationAscii = String.format(Locale.US,
+                    "role:1 producer:12 timestamp:%d latlng{latitude_e7:%d longitude_e7:%d} "
+                            + "radius:%d",
+                    timestamp, latitudeE7, longitudeE7, radius);
+            expectedHeader = "X-Geo: a "
+                    + new String(Base64.encode(locationAscii.getBytes(), Base64.NO_WRAP));
+        }
+        assertEquals(expectedHeader, header);
+    }
+
     @Override
     public void startMainActivity() throws InterruptedException {
         startMainActivityOnBlankPage();
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 16a1c17..cdaea04b 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2847,6 +2847,11 @@
      flag_descriptions::kLocationHardReloadDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kLocationHardReload)},
 
+    {"capture-thumbnail-on-load-finished",
+     flag_descriptions::kCaptureThumbnailOnLoadFinishedName,
+     flag_descriptions::kCaptureThumbnailOnLoadFinishedDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kCaptureThumbnailOnLoadFinished)},
+
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms/enums.xml. See note in
     // enums.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 64abee2d..582f824 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -80,6 +80,7 @@
     &kWebPaymentsModifiers,
     &kWebPaymentsSingleAppUiSkip,
     &kWebVRCardboardSupport,
+    &kXGEOVisibleNetworks,
     &ntp_snippets::kIncreasedVisibility,
     &ntp_snippets::kForeignSessionsSuggestionsFeature,
     &ntp_snippets::kNotificationsFeature,
@@ -217,6 +218,9 @@
 const base::Feature kWebVRCardboardSupport{
     "WebVRCardboardSupport", base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kXGEOVisibleNetworks{"XGEOVisibleNetworks",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
+
 static jboolean IsInitialized(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
   return !!base::FeatureList::GetInstance();
 }
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index f6e35071..68359b9 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -50,6 +50,7 @@
 extern const base::Feature kWebPaymentsModifiers;
 extern const base::Feature kWebPaymentsSingleAppUiSkip;
 extern const base::Feature kWebVRCardboardSupport;
+extern const base::Feature kXGEOVisibleNetworks;
 
 bool RegisterChromeFeatureListJni(JNIEnv* env);
 
diff --git a/chrome/browser/browsing_data/cache_counter.cc b/chrome/browser/browsing_data/cache_counter.cc
index 557be8a3..d131033 100644
--- a/chrome/browser/browsing_data/cache_counter.cc
+++ b/chrome/browser/browsing_data/cache_counter.cc
@@ -32,6 +32,8 @@
 }
 
 void CacheCounter::Count() {
+  // Cancel existing requests.
+  weak_ptr_factory_.InvalidateWeakPtrs();
   base::WeakPtr<browsing_data::ConditionalCacheCountingHelper> counter =
       browsing_data::ConditionalCacheCountingHelper::CreateForRange(
           content::BrowserContext::GetDefaultStoragePartition(profile_),
diff --git a/chrome/browser/browsing_data/media_licenses_counter.cc b/chrome/browser/browsing_data/media_licenses_counter.cc
index cd248ad46..9f19f2766 100644
--- a/chrome/browser/browsing_data/media_licenses_counter.cc
+++ b/chrome/browser/browsing_data/media_licenses_counter.cc
@@ -63,6 +63,8 @@
 
 void MediaLicensesCounter::Count() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // Cancel existing requests.
+  weak_ptr_factory_.InvalidateWeakPtrs();
   scoped_refptr<storage::FileSystemContext> filesystem_context =
       make_scoped_refptr(
           content::BrowserContext::GetDefaultStoragePartition(profile_)
diff --git a/chrome/browser/browsing_data/site_data_counter.cc b/chrome/browser/browsing_data/site_data_counter.cc
index 36397fd..8106d3ea 100644
--- a/chrome/browser/browsing_data/site_data_counter.cc
+++ b/chrome/browser/browsing_data/site_data_counter.cc
@@ -20,6 +20,8 @@
 }
 
 void SiteDataCounter::Count() {
+  // Cancel existing requests.
+  weak_ptr_factory_.InvalidateWeakPtrs();
   base::Time begin = GetPeriodStart();
   auto done_callback =
       base::Bind(&SiteDataCounter::Done, weak_ptr_factory_.GetWeakPtr());
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 71c0017a..3004ed2 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3127,4 +3127,11 @@
     "Enable an experimental change for Location.reload() to trigger a "
     "hard-reload.";
 
+const char kCaptureThumbnailOnLoadFinishedName[] =
+    "Capture page thumbnail on load finished";
+
+const char kCaptureThumbnailOnLoadFinishedDescription[] =
+    "Capture a page thumbnail (for use on the New Tab page) when the page load "
+    "finishes, in addition to other times a thumbnail may be captured.";
+
 }  // namespace flag_descriptions
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 437edc3..3074292 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -3398,6 +3398,10 @@
 // a hard-reload.
 extern const char kLocationHardReloadDescription[];
 
+// Name and description for the capture-thumbnail-on-load-finished flag.
+extern const char kCaptureThumbnailOnLoadFinishedName[];
+extern const char kCaptureThumbnailOnLoadFinishedDescription[];
+
 }  // namespace flag_descriptions
 
 #endif  // CHROME_BROWSER_FLAG_DESCRIPTIONS_H_
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm
index 83d4bad..841897d 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac.mm
+++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm
@@ -128,24 +128,53 @@
   return title;
 }
 
+bool IsPersistentNotification(const Notification& notification) {
+  return notification.never_timeout() ||
+         notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS;
+}
+
 base::string16 CreateNotificationContext(const Notification& notification,
                                          bool requires_attribution) {
   if (!requires_attribution)
     return notification.context_message();
 
-  base::string16 context =
+  // Mac OS notifications don't provide a good way to elide the domain (or tell
+  // you the maximum width of the subtitle field). We have experimentally
+  // determined the maximum number of characters that fit using the widest
+  // possible character (m). If the domain fits in those character we show it
+  // completely. Otherwise we use eTLD + 1.
+
+  // These numbers have been obtained through experimentation on various
+  // Mac OS platforms.
+
+  // Corresponds to the string "mmmmmmmmmmmmmm"
+  constexpr size_t kMaxDomainLenghtAlert = 14;
+
+  // Corresponds to the string "mmmmmmmmmmmmmmmmmmmmm"
+  constexpr size_t kMaxDomainLenghtBanner = 21;
+
+  size_t max_characters = IsPersistentNotification(notification)
+                              ? kMaxDomainLenghtAlert
+                              : kMaxDomainLenghtBanner;
+
+  base::string16 origin = url_formatter::FormatOriginForSecurityDisplay(
+      url::Origin(notification.origin_url()),
+      url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
+
+  if (origin.size() <= max_characters)
+    return origin;
+
+  // Too long, use etld+1
+  base::string16 etldplusone =
       base::UTF8ToUTF16(net::registry_controlled_domains::GetDomainAndRegistry(
           notification.origin_url(),
           net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
 
   // localhost, raw IPs etc. are not handled by GetDomainAndRegistry.
-  if (context.empty()) {
-    context = url_formatter::FormatOriginForSecurityDisplay(
-        url::Origin(notification.origin_url()),
-        url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
-  }
+  if (etldplusone.empty())
+    return origin;
 
-  return context;
+  return etldplusone;
 }
 }  // namespace
 
@@ -268,9 +297,7 @@
   // Send persistent notifications to the XPC service so they
   // can be displayed as alerts. Chrome itself can only display
   // banners.
-  // Progress Notifications are always considered persistent.
-  if (notification.never_timeout() ||
-      notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS) {
+  if (IsPersistentNotification(notification)) {
     NSDictionary* dict = [builder buildDictionary];
     [alert_dispatcher_ dispatchNotification:dict];
   } else {
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm b/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm
index 81eb7cd..06c4419 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm
+++ b/chrome/browser/notifications/notification_platform_bridge_mac_unittest.mm
@@ -434,37 +434,43 @@
 
   notification = CreateBanner("Title", "Context", "https://mail.appspot.com",
                               "Button 1", nullptr);
-
   bridge->Display(NotificationCommon::PERSISTENT, "notification_id2",
                   "profile_id", false, *notification);
+
   notification = CreateBanner("Title", "Context", "https://tests.peter.sh",
                               "Button 1", nullptr);
-
   bridge->Display(NotificationCommon::PERSISTENT, "notification_id3",
                   "profile_id", false, *notification);
 
+  notification = CreateBanner(
+      "Title", "Context",
+      "https://somereallylongsubdomainthatactuallyisanaliasfortests.peter.sh/",
+      "Button 1", nullptr);
+  bridge->Display(NotificationCommon::PERSISTENT, "notification_id4",
+                  "profile_id", false, *notification);
+
   notification = CreateBanner("Title", "Context", "http://localhost:8080",
                               "Button 1", nullptr);
-
-  bridge->Display(NotificationCommon::PERSISTENT, "notification_id4",
+  bridge->Display(NotificationCommon::PERSISTENT, "notification_id5",
                   "profile_id", false, *notification);
 
   notification = CreateBanner("Title", "Context", "https://93.186.186.172",
                               "Button 1", nullptr);
-
-  bridge->Display(NotificationCommon::PERSISTENT, "notification_id5",
+  bridge->Display(NotificationCommon::PERSISTENT, "notification_id6",
                   "profile_id", false, *notification);
 
   NSArray* notifications = [notification_center() deliveredNotifications];
-  EXPECT_EQ(5u, [notifications count]);
+  EXPECT_EQ(6u, [notifications count]);
   NSUserNotification* delivered_notification = [notifications objectAtIndex:0];
   EXPECT_NSEQ(@"test.co.uk", [delivered_notification subtitle]);
   delivered_notification = [notifications objectAtIndex:1];
   EXPECT_NSEQ(@"mail.appspot.com", [delivered_notification subtitle]);
   delivered_notification = [notifications objectAtIndex:2];
-  EXPECT_NSEQ(@"peter.sh", [delivered_notification subtitle]);
+  EXPECT_NSEQ(@"tests.peter.sh", [delivered_notification subtitle]);
   delivered_notification = [notifications objectAtIndex:3];
-  EXPECT_NSEQ(@"localhost:8080", [delivered_notification subtitle]);
+  EXPECT_NSEQ(@"peter.sh", [delivered_notification subtitle]);
   delivered_notification = [notifications objectAtIndex:4];
+  EXPECT_NSEQ(@"localhost:8080", [delivered_notification subtitle]);
+  delivered_notification = [notifications objectAtIndex:5];
   EXPECT_NSEQ(@"93.186.186.172", [delivered_notification subtitle]);
 }
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
index dbe29ea07..cfdd6ff 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/test/thread_test_helper.h"
 #include "base/time/clock.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h"
@@ -384,9 +385,15 @@
       ReportExpectation::Successful({{"report1", RetryStatus::RETRIED}}));
 }
 
+// Failing on some Win and Mac buildbots.  See crbug.com/719138.
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#define MAYBE_DontSendOldReports DISABLED_DontSendOldReports
+#else
+#define MAYBE_DontSendOldReports DontSendOldReports
+#endif
 // CertificateReportingService should ignore reports older than the report TTL.
 IN_PROC_BROWSER_TEST_F(CertificateReportingServiceBrowserTest,
-                       DontSendOldReports) {
+                       MAYBE_DontSendOldReports) {
   SetExpectedHistogramCountOnTeardown(5);
 
   base::SimpleTestClock* clock = new base::SimpleTestClock();
diff --git a/chrome/browser/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/thumbnails/thumbnail_tab_helper.cc
index b710d4cc..a60fd560 100644
--- a/chrome/browser/thumbnails/thumbnail_tab_helper.cc
+++ b/chrome/browser/thumbnails/thumbnail_tab_helper.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/thumbnails/thumbnail_tab_helper.h"
 
+#include "base/feature_list.h"
 #include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/thumbnails/thumbnail_service.h"
 #include "chrome/browser/thumbnails/thumbnail_service_factory.h"
 #include "chrome/browser/thumbnails/thumbnailing_algorithm.h"
-#include "chrome/browser/thumbnails/thumbnailing_context.h"
+#include "chrome/common/chrome_features.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
@@ -18,14 +18,8 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
-#include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/scrollbar_size.h"
-#include "ui/gfx/skbitmap_operations.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ThumbnailTabHelper);
 
@@ -35,7 +29,7 @@
 // --------
 // This class provides a service for updating thumbnails to be used in
 // "Most visited" section of the new tab page. The service can be started
-// by StartThumbnailing(). The current algorithm of the service is as
+// by UpdateThumbnailIfNecessary(). The current algorithm of the service is as
 // simple as follows:
 //
 //    When a renderer is about to be hidden (this usually occurs when the
@@ -43,17 +37,21 @@
 //    thumbnail for the tab rendered by the renderer, if needed. The
 //    heuristics to judge whether or not to update the thumbnail is
 //    implemented in ShouldUpdateThumbnail().
+//    If features::kCaptureThumbnailOnLoadFinished is enabled, then a thumbnail
+//    may also be captured when a page load finishes (subject to the same
+//    heuristics).
 
 using content::RenderViewHost;
 using content::RenderWidgetHost;
 using content::WebContents;
 
-using thumbnails::ClipResult;
 using thumbnails::ThumbnailingContext;
 using thumbnails::ThumbnailingAlgorithm;
 
 ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents)
     : content::WebContentsObserver(contents),
+      capture_on_load_finished_(base::FeatureList::IsEnabled(
+          features::kCaptureThumbnailOnLoadFinished)),
       load_interrupted_(false),
       weak_factory_(this) {
   // Even though we deal in RenderWidgetHosts, we only care about its
@@ -86,8 +84,7 @@
   }
 }
 
-void ThumbnailTabHelper::RenderViewDeleted(
-    content::RenderViewHost* render_view_host) {
+void ThumbnailTabHelper::RenderViewDeleted(RenderViewHost* render_view_host) {
   bool registered = registrar_.IsRegistered(
       this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
       content::Source<RenderWidgetHost>(render_view_host->GetWidget()));
@@ -102,6 +99,12 @@
   load_interrupted_ = false;
 }
 
+void ThumbnailTabHelper::DidStopLoading() {
+  if (capture_on_load_finished_) {
+    UpdateThumbnailIfNecessary();
+  }
+}
+
 void ThumbnailTabHelper::NavigationStopped() {
   // This function gets called when the page loading is interrupted by the
   // stop button.
@@ -163,7 +166,7 @@
     return;
   }
 
-  scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm(
+  scoped_refptr<ThumbnailingAlgorithm> algorithm(
       thumbnail_service->GetThumbnailingAlgorithm());
 
   thumbnailing_context_ = new ThumbnailingContext(web_contents(),
@@ -185,7 +188,7 @@
 }
 
 void ThumbnailTabHelper::ProcessCapturedBitmap(
-    scoped_refptr<thumbnails::ThumbnailingAlgorithm> algorithm,
+    scoped_refptr<ThumbnailingAlgorithm> algorithm,
     const SkBitmap& bitmap,
     content::ReadbackResponse response) {
   if (response == content::READBACK_SUCCESS) {
@@ -211,9 +214,8 @@
   thumbnailing_context_ = nullptr;
 }
 
-void ThumbnailTabHelper::UpdateThumbnail(
-    const thumbnails::ThumbnailingContext& context,
-    const SkBitmap& thumbnail) {
+void ThumbnailTabHelper::UpdateThumbnail(const ThumbnailingContext& context,
+                                         const SkBitmap& thumbnail) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // Feed the constructed thumbnail to the thumbnail service.
   gfx::Image image = gfx::Image::CreateFrom1xBitmap(thumbnail);
@@ -224,8 +226,7 @@
   CleanUpFromThumbnailGeneration();
 }
 
-void ThumbnailTabHelper::RenderViewHostCreated(
-    content::RenderViewHost* renderer) {
+void ThumbnailTabHelper::RenderViewHostCreated(RenderViewHost* renderer) {
   // NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED is really a new
   // RenderView, not RenderViewHost, and there is no good way to get
   // notifications of RenderViewHosts. So just be tolerant of re-registrations.
diff --git a/chrome/browser/thumbnails/thumbnail_tab_helper.h b/chrome/browser/thumbnails/thumbnail_tab_helper.h
index aae839e..b91b05a 100644
--- a/chrome/browser/thumbnails/thumbnail_tab_helper.h
+++ b/chrome/browser/thumbnails/thumbnail_tab_helper.h
@@ -38,6 +38,7 @@
   // content::WebContentsObserver overrides.
   void RenderViewDeleted(content::RenderViewHost* render_view_host) override;
   void DidStartLoading() override;
+  void DidStopLoading() override;
   void NavigationStopped() override;
 
   // Update the thumbnail of the given tab contents if necessary.
@@ -67,6 +68,8 @@
   // Indicates that the given widget has changed is visibility.
   void WidgetHidden(content::RenderWidgetHost* widget);
 
+  const bool capture_on_load_finished_;
+
   content::NotificationRegistrar registrar_;
   scoped_refptr<thumbnails::ThumbnailingContext> thumbnailing_context_;
 
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 7cd2d31c..521c2036 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -99,6 +99,11 @@
 
 const base::Feature kTabsInCbd{"TabsInCBD", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Whether to capture page thumbnails when the page load finishes (in addition
+// to any other times this might happen).
+const base::Feature kCaptureThumbnailOnLoadFinished{
+    "CaptureThumbnailOnLoadFinished", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Whether to trigger app banner installability checks on page load.
 const base::Feature kCheckInstallabilityForBannerOnLoad{
     "CheckInstallabilityForBannerOnLoad", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 4aae3c88..306e4f7 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -62,6 +62,8 @@
 extern const base::Feature kTabStripKeyboardFocus;
 #endif  // defined(OS_MACOSX)
 
+extern const base::Feature kCaptureThumbnailOnLoadFinished;
+
 extern const base::Feature kCheckInstallabilityForBannerOnLoad;
 
 #if defined(OS_WIN)
diff --git a/components/browsing_data/core/counters/browsing_data_counter.h b/components/browsing_data/core/counters/browsing_data_counter.h
index d7fbb95..d7d532a 100644
--- a/components/browsing_data/core/counters/browsing_data_counter.h
+++ b/components/browsing_data/core/counters/browsing_data_counter.h
@@ -128,7 +128,8 @@
   // Called after the class is initialized by calling |Init|.
   virtual void OnInitialized();
 
-  // Count the data.
+  // Count the data. Call ReportResult() when finished. Tasks that are still
+  // running should be cancelled to avoid reporting old results.
   virtual void Count() = 0;
 
   // State transition methods.
diff --git a/components/browsing_data/core/counters/history_counter.cc b/components/browsing_data/core/counters/history_counter.cc
index 6fcb1c1..0061bb1 100644
--- a/components/browsing_data/core/counters/history_counter.cc
+++ b/components/browsing_data/core/counters/history_counter.cc
@@ -55,6 +55,8 @@
   // Reset the state.
   cancelable_task_tracker_.TryCancelAll();
   web_history_request_.reset();
+  weak_ptr_factory_.InvalidateWeakPtrs();
+
   has_synced_visits_ = false;
 
   // Count the locally stored items.
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc
index 6f3f041e..584484a6 100644
--- a/components/favicon/core/favicon_handler_unittest.cc
+++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_task_environment.h"
+#include "base/test/test_simple_task_runner.h"
 #include "components/favicon/core/favicon_driver.h"
 #include "components/favicon/core/test/mock_favicon_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -229,7 +230,8 @@
 // particular URL, the callback is called with empty database results.
 class FakeFaviconService {
  public:
-  FakeFaviconService() = default;
+  FakeFaviconService()
+      : manual_callback_task_runner_(new base::TestSimpleTaskRunner()) {}
 
   // Stores favicon with bitmap data in |results| at |page_url| and |icon_url|.
   void Store(const GURL& page_url,
@@ -272,6 +274,28 @@
     return GetFaviconForPageOrIconURL(icon_url, callback, tracker);
   }
 
+  // Disables automatic callback for |url|. This is useful for emulating a
+  // DB lookup taking a long time. The callback for
+  // GetFaviconForPageOrIconURL() will be stored in |manual_callback_|.
+  void SetRunCallbackManuallyForUrl(const GURL& url) {
+    manual_callback_url_ = url;
+  }
+
+  // Returns whether an ongoing lookup exists for a url previously selected
+  // via SetRunCallbackManuallyForUrl().
+  bool HasPendingManualCallback() {
+    return manual_callback_task_runner_->HasPendingTask();
+  }
+
+  // Triggers the response for a lookup previously selected for manual
+  // triggering via SetRunCallbackManuallyForUrl().
+  bool RunCallbackManually() {
+    if (!HasPendingManualCallback())
+      return false;
+    manual_callback_task_runner_->RunPendingTasks();
+    return true;
+  }
+
  private:
   base::CancelableTaskTracker::TaskId GetFaviconForPageOrIconURL(
       const GURL& page_or_icon_url,
@@ -279,14 +303,31 @@
       base::CancelableTaskTracker* tracker) {
     db_requests_.push_back(page_or_icon_url);
 
-    return tracker->PostTask(base::ThreadTaskRunnerHandle::Get().get(),
-                             FROM_HERE,
-                             base::Bind(callback, results_[page_or_icon_url]));
+    base::Closure bound_callback =
+        base::Bind(callback, results_[page_or_icon_url]);
+
+    if (page_or_icon_url != manual_callback_url_) {
+      return tracker->PostTask(base::ThreadTaskRunnerHandle::Get().get(),
+                               FROM_HERE, bound_callback);
+    }
+
+    // We use PostTaskAndReply() to cause |callback| being run in the current
+    // TaskRunner.
+    return tracker->PostTaskAndReply(manual_callback_task_runner_.get(),
+                                     FROM_HERE, base::Bind(&base::DoNothing),
+                                     bound_callback);
   }
 
   std::map<GURL, std::vector<favicon_base::FaviconRawBitmapResult>> results_;
   URLVector db_requests_;
 
+  // URL to disable automatic callbacks for.
+  GURL manual_callback_url_;
+
+  // Callback for GetFaviconForPageOrIconURL() request for
+  // |manual_callback_url_|.
+  scoped_refptr<base::TestSimpleTaskRunner> manual_callback_task_runner_;
+
   DISALLOW_COPY_AND_ASSIGN(FakeFaviconService);
 };
 
@@ -422,24 +463,35 @@
 // - FaviconService::GetFaviconForPageURL() callback returns before
 //   FaviconHandler::OnUpdateFaviconURL() is called.
 TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesSlower) {
+  // Defer the database lookup completion to control the exact timing.
+  favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
+
+  EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
+  EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
+
+  FaviconHandler handler(&favicon_service_, &delegate_,
+                         FaviconDriverObserver::NON_TOUCH_16_DIP);
+  handler.FetchFavicon(kPageURL);
+  base::RunLoop().RunUntilIdle();
+  // Database lookup for |kPageURL| is ongoing.
+  ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
+  // Causes FaviconService lookups be faster than OnUpdateFaviconURL().
+  ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
+  ASSERT_TRUE(VerifyAndClearExpectations());
+
   EXPECT_CALL(favicon_service_, SetFavicons(kPageURL, kIconURL16x16, FAVICON,
                                             ImageSizeIs(16, 16)));
   EXPECT_CALL(delegate_, OnFaviconUpdated(
                              kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP,
                              kIconURL16x16, /*icon_url_changed=*/true, _));
-
-  FaviconHandler handler(&favicon_service_, &delegate_,
-                         FaviconDriverObserver::NON_TOUCH_16_DIP);
-  handler.FetchFavicon(kPageURL);
-  // Causes FaviconService lookups be faster than OnUpdateFaviconURL().
-  base::RunLoop().RunUntilIdle();
+  // Feed in favicons now that the database lookup is completed.
   handler.OnUpdateFaviconURL(kPageURL,
                              {FaviconURL(kIconURL16x16, FAVICON, kEmptySizes)});
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
   EXPECT_THAT(favicon_service_.fake()->db_requests(),
-              ElementsAre(kPageURL, kIconURL16x16));
+              ElementsAre(kIconURL16x16));
+  EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
 }
 
 // Test that the FaviconHandler process finishes when:
@@ -448,20 +500,34 @@
 // - FaviconService::GetFaviconForPageURL() callback returns after
 //   FaviconHandler::OnUpdateFaviconURL() is called.
 TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesFaster) {
-  EXPECT_CALL(favicon_service_, SetFavicons(kPageURL, kIconURL16x16, FAVICON,
-                                            ImageSizeIs(16, 16)));
-  EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
+  // Defer the database lookup completion to control the exact timing.
+  favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
+
+  EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
+  EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
 
   FaviconHandler handler(&favicon_service_, &delegate_,
                          FaviconDriverObserver::NON_TOUCH_16_DIP);
   handler.FetchFavicon(kPageURL);
-  ASSERT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL));
-
-  // Feed in favicons without processing posted tasks (RunUntilIdle()).
+  base::RunLoop().RunUntilIdle();
+  // Feed in favicons before completing the database lookup.
   handler.OnUpdateFaviconURL(kPageURL,
                              {FaviconURL(kIconURL16x16, FAVICON, kEmptySizes)});
+
+  ASSERT_TRUE(VerifyAndClearExpectations());
+  // Database lookup for |kPageURL| is ongoing.
+  ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
+
+  EXPECT_CALL(favicon_service_, SetFavicons(kPageURL, kIconURL16x16, FAVICON,
+                                            ImageSizeIs(16, 16)));
+  EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
+
+  // Complete the lookup for |kPageURL|.
+  ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
   base::RunLoop().RunUntilIdle();
 
+  EXPECT_THAT(favicon_service_.fake()->db_requests(),
+              ElementsAre(kIconURL16x16));
   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
 }
 
@@ -656,8 +722,8 @@
 }
 
 // Test that sending an icon URL update identical to the previous icon URL
-// update is a no-op.
-TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileProcessingShouldBeNoop) {
+// update during image download is a no-op.
+TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileDownloadingShouldBeNoop) {
   const GURL kSlowLoadingIconURL("http://www.google.com/slow_favicon");
 
   const std::vector<FaviconURL> favicon_urls = {
@@ -682,6 +748,8 @@
   // despite the ongoing download.
   handler->OnUpdateFaviconURL(kPageURL, favicon_urls);
   base::RunLoop().RunUntilIdle();
+  EXPECT_THAT(favicon_service_.fake()->db_requests(), IsEmpty());
+  EXPECT_THAT(delegate_.downloads(), IsEmpty());
 
   // Complete the download.
   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _));
@@ -691,6 +759,40 @@
   EXPECT_THAT(delegate_.downloads(), IsEmpty());
 }
 
+// Test that sending an icon URL update identical to the previous icon URL
+// update during a database lookup is a no-op.
+TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileDatabaseLookupShouldBeNoop) {
+  const std::vector<FaviconURL> favicon_urls = {
+      FaviconURL(kIconURL64x64, FAVICON, kEmptySizes),
+  };
+
+  favicon_service_.fake()->SetRunCallbackManuallyForUrl(kIconURL64x64);
+
+  std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
+      FaviconDriverObserver::NON_TOUCH_16_DIP, favicon_urls);
+
+  // Ongoing database lookup.
+  ASSERT_THAT(favicon_service_.fake()->db_requests(),
+              ElementsAre(kPageURL, kIconURL64x64));
+  ASSERT_THAT(delegate_.downloads(), IsEmpty());
+  ASSERT_TRUE(VerifyAndClearExpectations());
+  ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
+
+  // Calling OnUpdateFaviconURL() with the same icon URLs should have no effect,
+  // despite the ongoing DB lookup.
+  handler->OnUpdateFaviconURL(kPageURL, favicon_urls);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_THAT(favicon_service_.fake()->db_requests(), IsEmpty());
+  EXPECT_THAT(delegate_.downloads(), IsEmpty());
+
+  // Complete the lookup.
+  EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _));
+  EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _));
+  EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL64x64));
+}
+
 // Test that calling OnUpdateFaviconUrl() with the same icon URLs as before is a
 // no-op. This is important because OnUpdateFaviconUrl() is called when the page
 // finishes loading. This can occur several times for pages with iframes.
diff --git a/components/metrics/execution_phase.cc b/components/metrics/execution_phase.cc
index 98f9aee..992ef82 100644
--- a/components/metrics/execution_phase.cc
+++ b/components/metrics/execution_phase.cc
@@ -5,12 +5,15 @@
 #include "components/metrics/execution_phase.h"
 
 #include "build/build_config.h"
-#include "components/browser_watcher/stability_data_names.h"
-#include "components/browser_watcher/stability_debugging.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 
+#if defined(OS_WIN)
+#include "components/browser_watcher/stability_data_names.h"
+#include "components/browser_watcher/stability_debugging.h"
+#endif  // defined(OS_WIN)
+
 namespace metrics {
 
 ExecutionPhaseManager::ExecutionPhaseManager(PrefService* local_state)
diff --git a/components/suggestions/suggestions_service_impl.h b/components/suggestions/suggestions_service_impl.h
index ee0b2fd..b2ce162 100644
--- a/components/suggestions/suggestions_service_impl.h
+++ b/components/suggestions/suggestions_service_impl.h
@@ -105,6 +105,10 @@
   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, ClearBlacklist);
   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, UndoBlacklistURL);
   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest,
+                           UndoBlacklistURLFailsIfNotInBlacklist);
+  FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest,
+                           UndoBlacklistURLFailsIfAlreadyCandidate);
+  FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest,
                            GetBlacklistedUrlBlacklistRequest);
   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, UpdateBlacklistDelay);
   FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, CheckDefaultTimeStamps);
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc
index 2a9ab77..ef75e2e 100644
--- a/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -186,7 +186,6 @@
         signin_client_(&pref_service_),
         signin_manager_(&signin_client_, &account_tracker_),
         factory_(nullptr, base::Bind(&CreateURLFetcher)),
-        mock_sync_service_(nullptr),
         mock_thumbnail_manager_(nullptr),
         mock_blacklist_store_(nullptr),
         test_suggestions_store_(nullptr) {
@@ -203,86 +202,35 @@
   void SetUp() override {
     request_context_ =
         new net::TestURLRequestContextGetter(io_message_loop_.task_runner());
-  }
 
-  std::unique_ptr<SuggestionsServiceImpl> CreateSuggestionsServiceWithMocks() {
-    mock_sync_service_ = base::MakeUnique<MockSyncService>();
-    EXPECT_CALL(*mock_sync_service_, CanSyncStart())
+    EXPECT_CALL(mock_sync_service_, CanSyncStart())
         .Times(AnyNumber())
         .WillRepeatedly(Return(true));
-    EXPECT_CALL(*mock_sync_service_, IsSyncActive())
+    EXPECT_CALL(mock_sync_service_, IsSyncActive())
         .Times(AnyNumber())
         .WillRepeatedly(Return(true));
-    EXPECT_CALL(*mock_sync_service_, ConfigurationDone())
+    EXPECT_CALL(mock_sync_service_, ConfigurationDone())
         .Times(AnyNumber())
         .WillRepeatedly(Return(true));
-    EXPECT_CALL(*mock_sync_service_, GetActiveDataTypes())
+    EXPECT_CALL(mock_sync_service_, GetActiveDataTypes())
         .Times(AnyNumber())
         .WillRepeatedly(
             Return(syncer::ModelTypeSet(syncer::HISTORY_DELETE_DIRECTIVES)));
 
-    // These objects are owned by the returned SuggestionsService, but we keep
-    // the pointer around for testing.
-    // TODO(treib): This is broken - if the test destroys the SuggestionsService
-    // (which it can easily do, since it has an owning pointer), we'll be left
-    // with dangling pointers here.
+    // These objects are owned by the SuggestionsService, but we keep the
+    // pointers around for testing.
     test_suggestions_store_ = new TestSuggestionsStore();
     mock_thumbnail_manager_ = new StrictMock<MockImageManager>();
     mock_blacklist_store_ = new StrictMock<MockBlacklistStore>();
-    return base::MakeUnique<SuggestionsServiceImpl>(
-        &signin_manager_, &token_service_, mock_sync_service_.get(),
+    suggestions_service_ = base::MakeUnique<SuggestionsServiceImpl>(
+        &signin_manager_, &token_service_, &mock_sync_service_,
         request_context_.get(), base::WrapUnique(test_suggestions_store_),
         base::WrapUnique(mock_thumbnail_manager_),
         base::WrapUnique(mock_blacklist_store_));
   }
 
-  // Helper for Undo failure tests. Depending on |is_uploaded|, tests either
-  // the case where the URL is no longer in the local blacklist or the case
-  // in which it's not yet candidate for upload.
-  void UndoBlacklistURLFailsHelper(bool is_uploaded) {
-    std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-        CreateSuggestionsServiceWithMocks());
-    // Ensure scheduling the request doesn't happen before undo.
-    base::TimeDelta delay = base::TimeDelta::FromHours(1);
-    suggestions_service->set_blacklist_delay(delay);
-
-    auto subscription = suggestions_service->AddCallback(base::Bind(
-        &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
-
-    SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
-    GURL blacklisted_url(kBlacklistedUrl);
-
-    // Blacklist expectations.
-    EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
-        .WillOnce(Return(true));
-    EXPECT_CALL(*mock_thumbnail_manager_,
-                Initialize(EqualsProto(suggestions_profile)));
-    EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_));
-    EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
-        .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
-    // Undo expectations.
-    if (is_uploaded) {
-      // URL is not in local blacklist.
-      EXPECT_CALL(*mock_blacklist_store_,
-                  GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
-          .WillOnce(Return(false));
-    } else {
-      // URL is not yet candidate for upload.
-      base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1);
-      EXPECT_CALL(*mock_blacklist_store_,
-                  GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
-          .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true)));
-    }
-
-    EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url));
-    EXPECT_FALSE(suggestions_service->UndoBlacklistURL(blacklisted_url));
-
-    EXPECT_EQ(1, suggestions_data_callback_count_);
-  }
-
-  bool HasPendingSuggestionsRequest(
-      SuggestionsServiceImpl* suggestions_service) {
-    return !!suggestions_service->pending_request_.get();
+  bool HasPendingSuggestionsRequest() const {
+    return !!suggestions_service_->pending_request_.get();
   }
 
  protected:
@@ -293,21 +241,21 @@
   FakeSigninManagerBase signin_manager_;
   net::FakeURLFetcherFactory factory_;
   FakeProfileOAuth2TokenService token_service_;
-  std::unique_ptr<MockSyncService> mock_sync_service_;
-  // Only used if the SuggestionsService is built with mocks. Not owned.
+  MockSyncService mock_sync_service_;
+  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+  // Owned by the SuggestionsService.
   MockImageManager* mock_thumbnail_manager_;
   MockBlacklistStore* mock_blacklist_store_;
   TestSuggestionsStore* test_suggestions_store_;
-  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+
+  std::unique_ptr<SuggestionsServiceImpl> suggestions_service_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest);
 };
 
 TEST_F(SuggestionsServiceTest, FetchSuggestionsData) {
-  std::unique_ptr<SuggestionsService> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
@@ -324,7 +272,7 @@
       .WillOnce(Return(false));
 
   // Send the request. The data should be returned to the callback.
-  suggestions_service->FetchSuggestionsData();
+  suggestions_service_->FetchSuggestionsData();
 
   // Let the network request run.
   base::RunLoop().RunUntilIdle();
@@ -340,9 +288,7 @@
 }
 
 TEST_F(SuggestionsServiceTest, IgnoresNoopSyncChange) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
@@ -351,7 +297,7 @@
                            net::HTTP_OK, net::URLRequestStatus::SUCCESS);
 
   // An no-op change should not result in a suggestions refresh.
-  suggestions_service->OnStateChanged(mock_sync_service_.get());
+  suggestions_service_->OnStateChanged(&mock_sync_service_);
 
   // Let any network request run (there shouldn't be one).
   base::RunLoop().RunUntilIdle();
@@ -361,9 +307,7 @@
 }
 
 TEST_F(SuggestionsServiceTest, IgnoresUninterestingSyncChange) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
@@ -373,11 +317,11 @@
 
   // An uninteresting change should not result in a network request (the
   // SyncState is INITIALIZED_ENABLED_HISTORY before and after).
-  EXPECT_CALL(*mock_sync_service_, GetActiveDataTypes())
+  EXPECT_CALL(mock_sync_service_, GetActiveDataTypes())
       .Times(AnyNumber())
       .WillRepeatedly(Return(syncer::ModelTypeSet(
           syncer::HISTORY_DELETE_DIRECTIVES, syncer::BOOKMARKS)));
-  suggestions_service->OnStateChanged(mock_sync_service_.get());
+  suggestions_service_->OnStateChanged(&mock_sync_service_);
 
   // Let any network request run (there shouldn't be one).
   base::RunLoop().RunUntilIdle();
@@ -387,18 +331,15 @@
 }
 
 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-  EXPECT_CALL(*mock_sync_service_, IsSyncActive())
-      .WillRepeatedly(Return(false));
-  suggestions_service->OnStateChanged(mock_sync_service_.get());
+  EXPECT_CALL(mock_sync_service_, IsSyncActive()).WillRepeatedly(Return(false));
+  suggestions_service_->OnStateChanged(&mock_sync_service_);
 
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   // Try to fetch suggestions. Since sync is not active, no network request
   // should be sent.
-  suggestions_service->FetchSuggestionsData();
+  suggestions_service_->FetchSuggestionsData();
 
   // Let any network request run.
   base::RunLoop().RunUntilIdle();
@@ -414,17 +355,14 @@
 }
 
 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-  EXPECT_CALL(*mock_sync_service_, CanSyncStart())
-      .WillRepeatedly(Return(false));
+  EXPECT_CALL(mock_sync_service_, CanSyncStart()).WillRepeatedly(Return(false));
 
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   // Tell SuggestionsService that the sync state changed. The cache should be
   // cleared and empty data returned to the callback.
-  suggestions_service->OnStateChanged(mock_sync_service_.get());
+  suggestions_service_->OnStateChanged(&mock_sync_service_);
 
   // Ensure that CheckCallback ran once with empty data.
   EXPECT_EQ(1, suggestions_data_callback_count_);
@@ -432,7 +370,7 @@
 
   // Try to fetch suggestions. Since sync is not active, no network request
   // should be sent.
-  suggestions_service->FetchSuggestionsData();
+  suggestions_service_->FetchSuggestionsData();
 
   // Let any network request run.
   base::RunLoop().RunUntilIdle();
@@ -444,30 +382,24 @@
 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) {
   token_service_.set_auto_post_fetch_response_on_message_loop(false);
 
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
       .WillOnce(Return(false));
 
-  suggestions_service->FetchSuggestionsData();
+  suggestions_service_->FetchSuggestionsData();
 
   token_service_.IssueErrorForAllPendingRequests(GoogleServiceAuthError(
       GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
 
   // No network request should be sent.
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(HasPendingSuggestionsRequest(suggestions_service.get()));
+  EXPECT_FALSE(HasPendingSuggestionsRequest());
   EXPECT_EQ(0, suggestions_data_callback_count_);
 }
 
 TEST_F(SuggestionsServiceTest, IssueRequestIfNoneOngoingError) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-
   // Fake a request error.
   factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(),
                            "irrelevant", net::HTTP_OK,
@@ -477,7 +409,7 @@
       .WillOnce(Return(false));
 
   // Send the request. Empty data will be returned to the callback.
-  suggestions_service->IssueRequestIfNoneOngoing(
+  suggestions_service_->IssueRequestIfNoneOngoing(
       SuggestionsServiceImpl::BuildSuggestionsURL());
 
   // (Testing only) wait until suggestion fetch is complete.
@@ -485,9 +417,6 @@
 }
 
 TEST_F(SuggestionsServiceTest, IssueRequestIfNoneOngoingResponseNotOK) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-
   // Fake a non-200 response code.
   factory_.SetFakeResponse(SuggestionsServiceImpl::BuildSuggestionsURL(),
                            "irrelevant", net::HTTP_BAD_REQUEST,
@@ -498,7 +427,7 @@
       .WillOnce(Return(false));
 
   // Send the request. Empty data will be returned to the callback.
-  suggestions_service->IssueRequestIfNoneOngoing(
+  suggestions_service_->IssueRequestIfNoneOngoing(
       SuggestionsServiceImpl::BuildSuggestionsURL());
 
   // (Testing only) wait until suggestion fetch is complete.
@@ -510,12 +439,10 @@
 }
 
 TEST_F(SuggestionsServiceTest, BlacklistURL) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
   base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0);
-  suggestions_service->set_blacklist_delay(no_delay);
+  suggestions_service_->set_blacklist_delay(no_delay);
 
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   GURL blacklisted_url(kBlacklistedUrl);
@@ -538,7 +465,7 @@
   EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url)))
       .WillOnce(Return(true));
 
-  EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url));
+  EXPECT_TRUE(suggestions_service_->BlacklistURL(blacklisted_url));
   EXPECT_EQ(1, suggestions_data_callback_count_);
 
   // Wait on the upload task, the blacklist request and the next blacklist
@@ -557,29 +484,24 @@
 }
 
 TEST_F(SuggestionsServiceTest, BlacklistURLFails) {
-  std::unique_ptr<SuggestionsService> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   GURL blacklisted_url(kBlacklistedUrl);
   EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
       .WillOnce(Return(false));
 
-  EXPECT_FALSE(suggestions_service->BlacklistURL(blacklisted_url));
+  EXPECT_FALSE(suggestions_service_->BlacklistURL(blacklisted_url));
 
   EXPECT_EQ(0, suggestions_data_callback_count_);
 }
 
 // Initial blacklist request fails, triggering a second which succeeds.
 TEST_F(SuggestionsServiceTest, BlacklistURLRequestFails) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
   base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0);
-  suggestions_service->set_blacklist_delay(no_delay);
+  suggestions_service_->set_blacklist_delay(no_delay);
 
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   GURL blacklisted_url(kBlacklistedUrl);
@@ -616,7 +538,7 @@
       .WillOnce(Return(true));
 
   // Blacklist call, first request attempt.
-  EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url));
+  EXPECT_TRUE(suggestions_service_->BlacklistURL(blacklisted_url));
   EXPECT_EQ(1, suggestions_data_callback_count_);
 
   // Wait for the first scheduling, the first request, the second scheduling,
@@ -633,13 +555,11 @@
 }
 
 TEST_F(SuggestionsServiceTest, UndoBlacklistURL) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
   // Ensure scheduling the request doesn't happen before undo.
   base::TimeDelta delay = base::TimeDelta::FromHours(1);
-  suggestions_service->set_blacklist_delay(delay);
+  suggestions_service_->set_blacklist_delay(delay);
 
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
@@ -661,20 +581,18 @@
   EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url)))
       .WillOnce(Return(true));
 
-  EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url));
-  EXPECT_TRUE(suggestions_service->UndoBlacklistURL(blacklisted_url));
+  EXPECT_TRUE(suggestions_service_->BlacklistURL(blacklisted_url));
+  EXPECT_TRUE(suggestions_service_->UndoBlacklistURL(blacklisted_url));
 
   EXPECT_EQ(2, suggestions_data_callback_count_);
 }
 
 TEST_F(SuggestionsServiceTest, ClearBlacklist) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
   // Ensure scheduling the request doesn't happen before undo.
   base::TimeDelta delay = base::TimeDelta::FromHours(1);
-  suggestions_service->set_blacklist_delay(delay);
+  suggestions_service_->set_blacklist_delay(delay);
 
-  auto subscription = suggestions_service->AddCallback(base::Bind(
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
       &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
 
   SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
@@ -696,18 +614,73 @@
       .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
   EXPECT_CALL(*mock_blacklist_store_, ClearBlacklist());
 
-  EXPECT_TRUE(suggestions_service->BlacklistURL(blacklisted_url));
-  suggestions_service->ClearBlacklist();
+  EXPECT_TRUE(suggestions_service_->BlacklistURL(blacklisted_url));
+  suggestions_service_->ClearBlacklist();
 
   EXPECT_EQ(2, suggestions_data_callback_count_);
 }
 
 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfNotInBlacklist) {
-  UndoBlacklistURLFailsHelper(true);
+  // Ensure scheduling the request doesn't happen before undo.
+  base::TimeDelta delay = base::TimeDelta::FromHours(1);
+  suggestions_service_->set_blacklist_delay(delay);
+
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
+      &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
+
+  SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
+  GURL blacklisted_url(kBlacklistedUrl);
+
+  // Blacklist expectations.
+  EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_thumbnail_manager_,
+              Initialize(EqualsProto(suggestions_profile)));
+  EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_));
+  EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
+      .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
+
+  // URL is not in local blacklist.
+  EXPECT_CALL(*mock_blacklist_store_,
+              GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
+      .WillOnce(Return(false));
+
+  EXPECT_TRUE(suggestions_service_->BlacklistURL(blacklisted_url));
+  EXPECT_FALSE(suggestions_service_->UndoBlacklistURL(blacklisted_url));
+
+  EXPECT_EQ(1, suggestions_data_callback_count_);
 }
 
 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfAlreadyCandidate) {
-  UndoBlacklistURLFailsHelper(false);
+  // Ensure scheduling the request doesn't happen before undo.
+  base::TimeDelta delay = base::TimeDelta::FromHours(1);
+  suggestions_service_->set_blacklist_delay(delay);
+
+  auto subscription = suggestions_service_->AddCallback(base::Bind(
+      &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
+
+  SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
+  GURL blacklisted_url(kBlacklistedUrl);
+
+  // Blacklist expectations.
+  EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_thumbnail_manager_,
+              Initialize(EqualsProto(suggestions_profile)));
+  EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_));
+  EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
+      .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
+
+  // URL is not yet candidate for upload.
+  base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1);
+  EXPECT_CALL(*mock_blacklist_store_,
+              GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
+      .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true)));
+
+  EXPECT_TRUE(suggestions_service_->BlacklistURL(blacklisted_url));
+  EXPECT_FALSE(suggestions_service_->UndoBlacklistURL(blacklisted_url));
+
+  EXPECT_EQ(1, suggestions_data_callback_count_);
 }
 
 TEST_F(SuggestionsServiceTest, GetBlacklistedUrlNotBlacklistRequest) {
@@ -737,49 +710,42 @@
 }
 
 TEST_F(SuggestionsServiceTest, UpdateBlacklistDelay) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-  base::TimeDelta initial_delay = suggestions_service->blacklist_delay();
+  base::TimeDelta initial_delay = suggestions_service_->blacklist_delay();
 
   // Delay unchanged on success.
-  suggestions_service->UpdateBlacklistDelay(true);
-  EXPECT_EQ(initial_delay, suggestions_service->blacklist_delay());
+  suggestions_service_->UpdateBlacklistDelay(true);
+  EXPECT_EQ(initial_delay, suggestions_service_->blacklist_delay());
 
   // Delay increases on failure.
-  suggestions_service->UpdateBlacklistDelay(false);
-  EXPECT_GT(suggestions_service->blacklist_delay(), initial_delay);
+  suggestions_service_->UpdateBlacklistDelay(false);
+  EXPECT_GT(suggestions_service_->blacklist_delay(), initial_delay);
 
   // Delay resets on success.
-  suggestions_service->UpdateBlacklistDelay(true);
-  EXPECT_EQ(initial_delay, suggestions_service->blacklist_delay());
+  suggestions_service_->UpdateBlacklistDelay(true);
+  EXPECT_EQ(initial_delay, suggestions_service_->blacklist_delay());
 }
 
 TEST_F(SuggestionsServiceTest, CheckDefaultTimeStamps) {
-  std::unique_ptr<SuggestionsServiceImpl> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
   SuggestionsProfile suggestions =
       CreateSuggestionsProfileWithExpiryTimestamps();
-  suggestions_service->SetDefaultExpiryTimestamp(&suggestions,
-                                                 kTestDefaultExpiry);
+  suggestions_service_->SetDefaultExpiryTimestamp(&suggestions,
+                                                  kTestDefaultExpiry);
   EXPECT_EQ(kTestSetExpiry, suggestions.suggestions(0).expiry_ts());
   EXPECT_EQ(kTestDefaultExpiry, suggestions.suggestions(1).expiry_ts());
 }
 
 TEST_F(SuggestionsServiceTest, GetPageThumbnail) {
-  std::unique_ptr<SuggestionsService> suggestions_service(
-      CreateSuggestionsServiceWithMocks());
-
   GURL test_url(kTestUrl);
   GURL thumbnail_url("https://www.thumbnails.com/thumb.jpg");
   base::Callback<void(const GURL&, const gfx::Image&)> dummy_callback;
 
   EXPECT_CALL(*mock_thumbnail_manager_, GetImageForURL(test_url, _));
-  suggestions_service->GetPageThumbnail(test_url, dummy_callback);
+  suggestions_service_->GetPageThumbnail(test_url, dummy_callback);
 
   EXPECT_CALL(*mock_thumbnail_manager_, AddImageURL(test_url, thumbnail_url));
   EXPECT_CALL(*mock_thumbnail_manager_, GetImageForURL(test_url, _));
-  suggestions_service->GetPageThumbnailWithURL(test_url, thumbnail_url,
-                                               dummy_callback);
+  suggestions_service_->GetPageThumbnailWithURL(test_url, thumbnail_url,
+                                                dummy_callback);
 }
 
 }  // namespace suggestions
diff --git a/components/tracing/common/process_metrics_memory_dump_provider.cc b/components/tracing/common/process_metrics_memory_dump_provider.cc
index 3f2abde..7db23920 100644
--- a/components/tracing/common/process_metrics_memory_dump_provider.cc
+++ b/components/tracing/common/process_metrics_memory_dump_provider.cc
@@ -180,15 +180,18 @@
   return num_valid_regions;
 }
 
-bool GetResidentSizeFromStatmFile(int fd, uint64_t* resident_pages) {
+bool GetResidentAndSharedPagesFromStatmFile(int fd,
+                                            uint64_t* resident_pages,
+                                            uint64_t* shared_pages) {
   lseek(fd, 0, SEEK_SET);
   char line[kMaxLineSize];
   int res = read(fd, line, kMaxLineSize - 1);
   if (res <= 0)
     return false;
   line[res] = '\0';
-  int num_scanned = sscanf(line, "%*s %" SCNu64, resident_pages);
-  return num_scanned == 1;
+  int num_scanned =
+      sscanf(line, "%*s %" SCNu64 " %" SCNu64, resident_pages, shared_pages);
+  return num_scanned == 2;
 }
 
 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
@@ -633,6 +636,29 @@
 
   uint64_t peak_rss_bytes = 0;
 
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  auto& footprint = pmd->process_totals()->GetPlatformPrivateFootprint();
+
+  base::ScopedFD autoclose;
+  int statm_fd = fast_polling_statm_fd_.get();
+  if (statm_fd == -1) {
+    autoclose = OpenStatm();
+    statm_fd = autoclose.get();
+  }
+  if (statm_fd == -1)
+    return false;
+  const static size_t page_size = base::GetPageSize();
+  uint64_t resident_pages;
+  uint64_t shared_pages;
+  bool success = GetResidentAndSharedPagesFromStatmFile(
+      statm_fd, &resident_pages, &shared_pages);
+  if (!success)
+    return false;
+
+  // TODO(hjd): Implement swap in the next CL.
+  footprint.rss_anon_bytes = (resident_pages - shared_pages) * page_size;
+#endif  // defined(OS_LINUX) || defined(OS_ANDROID)
+
 #if !defined(OS_IOS)
   peak_rss_bytes = process_metrics_->GetPeakWorkingSetSize();
 #if defined(OS_LINUX) || defined(OS_ANDROID)
@@ -676,31 +702,41 @@
   return true;
 }
 
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+base::ScopedFD ProcessMetricsMemoryDumpProvider::OpenStatm() {
+  std::string name =
+      "/proc/" +
+      (process_ == base::kNullProcessId ? "self"
+                                        : base::IntToString(process_)) +
+      "/statm";
+  base::ScopedFD fd = base::ScopedFD(open(name.c_str(), O_RDONLY));
+  DCHECK(fd.is_valid());
+  return fd;
+}
+#endif  // defined(OS_LINUX) || defined(OS_ANDROID)
+
 void ProcessMetricsMemoryDumpProvider::PollFastMemoryTotal(
     uint64_t* memory_total) {
   *memory_total = 0;
 #if defined(OS_LINUX) || defined(OS_ANDROID)
+
   int statm_fd = fast_polling_statm_fd_for_testing;
   if (statm_fd == -1) {
-    if (!fast_polling_statm_fd_.is_valid()) {
-      std::string name = "/proc/" + (process_ == base::kNullProcessId
-                                         ? "self"
-                                         : base::IntToString(process_)) +
-                         "/statm";
-      fast_polling_statm_fd_.reset(open(name.c_str(), O_RDONLY));
-      DCHECK(fast_polling_statm_fd_.is_valid());
-    }
+    if (!fast_polling_statm_fd_.is_valid())
+      fast_polling_statm_fd_ = OpenStatm();
     statm_fd = fast_polling_statm_fd_.get();
+    if (statm_fd == -1)
+      return;
   }
-  if (statm_fd == -1)
-    return;
 
-  uint64_t rss_pages = 0;
-  if (!GetResidentSizeFromStatmFile(statm_fd, &rss_pages))
+  uint64_t resident_pages = 0;
+  uint64_t ignored_shared_pages = 0;
+  if (!GetResidentAndSharedPagesFromStatmFile(statm_fd, &resident_pages,
+                                              &ignored_shared_pages))
     return;
 
   static size_t page_size = base::GetPageSize();
-  *memory_total = rss_pages * page_size;
+  *memory_total = resident_pages * page_size;
 #else
   *memory_total = process_metrics_->GetWorkingSetSize();
 #endif
diff --git a/components/tracing/common/process_metrics_memory_dump_provider.h b/components/tracing/common/process_metrics_memory_dump_provider.h
index 730a9be..d3c5334 100644
--- a/components/tracing/common/process_metrics_memory_dump_provider.h
+++ b/components/tracing/common/process_metrics_memory_dump_provider.h
@@ -75,6 +75,8 @@
   static int fast_polling_statm_fd_for_testing;
 
   base::ScopedFD fast_polling_statm_fd_;
+
+  base::ScopedFD OpenStatm();
 #endif
 
   base::ProcessId process_;
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index fc720a7..ed78781 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -13,7 +13,6 @@
 #include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 #include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_factory.h"
 #include "cc/surfaces/surface_manager.h"
 #include "cc/surfaces/surface_sequence.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
diff --git a/content/public/renderer/resource_fetcher.h b/content/public/renderer/resource_fetcher.h
index ba75a4e..6f6c21e 100644
--- a/content/public/renderer/resource_fetcher.h
+++ b/content/public/renderer/resource_fetcher.h
@@ -18,7 +18,7 @@
 }
 
 namespace blink {
-class WebFrame;
+class WebLocalFrame;
 class WebURLResponse;
 }
 
@@ -51,7 +51,7 @@
 
   // Starts the request using the specified frame.  Calls |callback| when
   // done.
-  virtual void Start(blink::WebFrame* frame,
+  virtual void Start(blink::WebLocalFrame* frame,
                      blink::WebURLRequest::RequestContext request_context,
                      const Callback& callback) = 0;
 
diff --git a/content/renderer/fetchers/resource_fetcher_impl.cc b/content/renderer/fetchers/resource_fetcher_impl.cc
index 037e0ec..7b6a0e8 100644
--- a/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -20,8 +20,8 @@
 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
 #include "third_party/WebKit/public/platform/WebURLResponse.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebKit.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
 
 namespace content {
@@ -171,12 +171,14 @@
 }
 
 void ResourceFetcherImpl::Start(
-    blink::WebFrame* frame,
+    blink::WebLocalFrame* frame,
     blink::WebURLRequest::RequestContext request_context,
     const Callback& callback) {
   DCHECK(!loader_);
   DCHECK(!client_);
   DCHECK(!request_.IsNull());
+  DCHECK(frame);
+  DCHECK(!frame->GetDocument().IsNull());
   if (!request_.HttpBody().IsNull())
     DCHECK_NE("GET", request_.HttpMethod().Utf8()) << "GETs can't have bodies.";
 
diff --git a/content/renderer/fetchers/resource_fetcher_impl.h b/content/renderer/fetchers/resource_fetcher_impl.h
index fb13047..af0be03e 100644
--- a/content/renderer/fetchers/resource_fetcher_impl.h
+++ b/content/renderer/fetchers/resource_fetcher_impl.h
@@ -18,7 +18,7 @@
 class GURL;
 
 namespace blink {
-class WebFrame;
+class WebLocalFrame;
 class WebURLLoader;
 }
 
@@ -30,7 +30,7 @@
   void SetMethod(const std::string& method) override;
   void SetBody(const std::string& body) override;
   void SetHeader(const std::string& header, const std::string& value) override;
-  void Start(blink::WebFrame* frame,
+  void Start(blink::WebLocalFrame* frame,
              blink::WebURLRequest::RequestContext request_context,
              const Callback& callback) override;
   void SetTimeout(const base::TimeDelta& timeout) override;
diff --git a/content/renderer/mojo_context_state.cc b/content/renderer/mojo_context_state.cc
index 8296cd4..1263c49 100644
--- a/content/renderer/mojo_context_state.cc
+++ b/content/renderer/mojo_context_state.cc
@@ -29,7 +29,7 @@
 #include "mojo/public/js/constants.h"
 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebScriptSource.h"
 
 using v8::Context;
@@ -109,7 +109,7 @@
 }
 
 std::string GetModulePrefixForBindingsType(MojoBindingsType bindings_type,
-                                           blink::WebFrame* frame) {
+                                           blink::WebLocalFrame* frame) {
   switch (bindings_type) {
     case MojoBindingsType::FOR_WEB_UI:
       return frame->GetSecurityOrigin().ToString().Utf8() + "/";
@@ -124,7 +124,7 @@
 
 }  // namespace
 
-MojoContextState::MojoContextState(blink::WebFrame* frame,
+MojoContextState::MojoContextState(blink::WebLocalFrame* frame,
                                    v8::Local<v8::Context> context,
                                    MojoBindingsType bindings_type)
     : frame_(frame),
diff --git a/content/renderer/mojo_context_state.h b/content/renderer/mojo_context_state.h
index 1af69b7..7b67ee3f 100644
--- a/content/renderer/mojo_context_state.h
+++ b/content/renderer/mojo_context_state.h
@@ -15,7 +15,7 @@
 #include "v8/include/v8.h"
 
 namespace blink {
-class WebFrame;
+class WebLocalFrame;
 class WebURLResponse;
 }
 
@@ -29,7 +29,7 @@
 // by way of gin. Non-builtin modules are downloaded by way of ResourceFetchers.
 class MojoContextState : public gin::ModuleRegistryObserver {
  public:
-  MojoContextState(blink::WebFrame* frame,
+  MojoContextState(blink::WebLocalFrame* frame,
                    v8::Local<v8::Context> context,
                    MojoBindingsType bindings_type);
   ~MojoContextState() override;
@@ -61,7 +61,7 @@
       const std::vector<std::string>& dependencies) override;
 
   // Frame script is executed in. Also used to download resources.
-  blink::WebFrame* frame_;
+  blink::WebLocalFrame* frame_;
 
   // See description above getter.
   bool module_added_;
diff --git a/content/renderer/resource_fetcher_browsertest.cc b/content/renderer/resource_fetcher_browsertest.cc
index c1d6016..832e6017f 100644
--- a/content/renderer/resource_fetcher_browsertest.cc
+++ b/content/renderer/resource_fetcher_browsertest.cc
@@ -26,7 +26,6 @@
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
 
-using blink::WebFrame;
 using blink::WebURLRequest;
 using blink::WebURLResponse;
 
@@ -149,7 +148,8 @@
   }
 
   void ResourceFetcherDownloadOnRenderer(const GURL& url) {
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
     std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
@@ -165,7 +165,8 @@
   }
 
   void ResourceFetcher404OnRenderer(const GURL& url) {
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
     std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
@@ -179,7 +180,8 @@
   }
 
   void ResourceFetcherDidFailOnRenderer() {
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     // Try to fetch a page on a site that doesn't exist.
     GURL url("http://localhost:1339/doesnotexist");
@@ -199,7 +201,8 @@
   }
 
   void ResourceFetcherTimeoutOnRenderer(const GURL& url) {
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
     std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
@@ -218,7 +221,8 @@
   }
 
   void ResourceFetcherDeletedInCallbackOnRenderer(const GURL& url) {
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     std::unique_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
     std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
@@ -234,7 +238,8 @@
   void ResourceFetcherPost(const GURL& url) {
     const char* kBody = "Really nifty POST body!";
 
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
     std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
@@ -252,7 +257,8 @@
   void ResourceFetcherSetHeader(const GURL& url) {
     const char* kHeader = "Rather boring header.";
 
-    WebFrame* frame = GetRenderView()->GetWebView()->MainFrame();
+    blink::WebLocalFrame* frame =
+        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
 
     std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
     std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index a6b5739a..91b5d08 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -67,3 +67,6 @@
               ['mac', ('intel', 0x0a2e)], bug=718183)
     self.Fail('Pixel_WebGLGreenTriangle_NonChromiumImage_NoAA_NoAlpha',
               ['mac', ('intel', 0x0a2e)], bug=718183)
+
+    self.Flaky('Pixel_OffscreenCanvasTransferBeforeStyleResize',
+              ['mac', 'linux'], bug=719186)
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 6d08ac4..1f2ef7c1 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -198,10 +198,6 @@
 #   define SK_SUPPORT_LEGACY_ANISOTROPIC_MIPMAP_SCALE
 #endif
 
-#ifndef    SK_IGNORE_ETC1_SUPPORT
-#   define SK_IGNORE_ETC1_SUPPORT
-#endif
-
 #ifndef    SK_IGNORE_GPU_DITHER
 #   define SK_IGNORE_GPU_DITHER
 #endif
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index 6b001ef..cb4bdcb2 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -285,7 +285,7 @@
     "//v8:wasm_fuzzer",
   ]
   dict = "dicts/v8_wasm.dict"
-  seed_corpus = "//v8/test/fuzzer/wasm/"
+  seed_corpus = "//v8/test/fuzzer/wasm_corpus/"
   libfuzzer_options = [ "max_len=500" ]
 }
 
@@ -295,7 +295,7 @@
     "//v8:wasm_asmjs_fuzzer",
   ]
   dict = "dicts/v8_wasm.dict"
-  seed_corpus = "//v8/test/fuzzer/wasm_asmjs/"
+  seed_corpus = "//v8/test/fuzzer/wasm_asmjs_corpus/"
   libfuzzer_options = [ "max_len=500" ]
 }
 
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index 8207eb6..930cd6f9 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -186,7 +186,7 @@
 // |SelectionInDOMTree| instead of |VisibleSelection|.
 VisibleSelection Editor::SelectionForCommand(Event* event) {
   VisibleSelection selection =
-      GetFrame().Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
+      GetFrame().Selection().ComputeVisibleSelectionInDOMTree();
   if (!event)
     return selection;
   // If the target is a text control, and the current selection is outside of
@@ -228,12 +228,12 @@
 }
 
 static bool IsCaretAtStartOfWrappedLine(const FrameSelection& selection) {
-  if (!selection.ComputeVisibleSelectionInDOMTreeDeprecated().IsCaret())
+  if (!selection.ComputeVisibleSelectionInDOMTree().IsCaret())
     return false;
   if (selection.GetSelectionInDOMTree().Affinity() != TextAffinity::kDownstream)
     return false;
   const Position& position =
-      selection.ComputeVisibleSelectionInDOMTreeDeprecated().Start();
+      selection.ComputeVisibleSelectionInDOMTree().Start();
   return !InSameLine(PositionWithAffinity(position, TextAffinity::kUpstream),
                      PositionWithAffinity(position, TextAffinity::kDownstream));
 }
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index 3ee3ee0..498a59b 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -632,17 +632,16 @@
 
   Node* root = nullptr;
   Node* select_start_target = nullptr;
-  if (ComputeVisibleSelectionInDOMTreeDeprecated().IsContentEditable()) {
-    root = HighestEditableRoot(
-        ComputeVisibleSelectionInDOMTreeDeprecated().Start());
+  if (ComputeVisibleSelectionInDOMTree().IsContentEditable()) {
+    root = HighestEditableRoot(ComputeVisibleSelectionInDOMTree().Start());
     if (Node* shadow_root = NonBoundaryShadowTreeRootNode(
-            ComputeVisibleSelectionInDOMTreeDeprecated().Start()))
+            ComputeVisibleSelectionInDOMTree().Start()))
       select_start_target = shadow_root->OwnerShadowHost();
     else
       select_start_target = root;
   } else {
     root = NonBoundaryShadowTreeRootNode(
-        ComputeVisibleSelectionInDOMTreeDeprecated().Start());
+        ComputeVisibleSelectionInDOMTree().Start());
     if (root) {
       select_start_target = root->OwnerShadowHost();
     } else {
@@ -1107,7 +1106,7 @@
 }
 
 void FrameSelection::MoveRangeSelectionExtent(const IntPoint& contents_point) {
-  if (ComputeVisibleSelectionInDOMTreeDeprecated().IsNone())
+  if (ComputeVisibleSelectionInDOMTree().IsNone())
     return;
 
   const SetSelectionOptions kOptions =
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index 67b5b56b..31e6977 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -261,6 +261,7 @@
 TEST_F(FrameSelectionTest, SelectAllWithUnselectableRoot) {
   Element* select = GetDocument().createElement("select");
   GetDocument().ReplaceChild(select, GetDocument().documentElement());
+  GetDocument().UpdateStyleAndLayout();
   Selection().SelectAll();
   EXPECT_TRUE(Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsNone())
       << "Nothing should be selected if the "
diff --git a/third_party/WebKit/Source/core/editing/GranularityStrategy.cpp b/third_party/WebKit/Source/core/editing/GranularityStrategy.cpp
index e8bced1a..cb515b81 100644
--- a/third_party/WebKit/Source/core/editing/GranularityStrategy.cpp
+++ b/third_party/WebKit/Source/core/editing/GranularityStrategy.cpp
@@ -69,7 +69,7 @@
   const VisiblePosition& extent_position =
       VisiblePositionForContentsPoint(extent_point, frame);
   const VisibleSelection& selection =
-      frame->Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
+      frame->Selection().ComputeVisibleSelectionInDOMTree();
   if (extent_position.IsNull() || selection.VisibleBase().DeepEquivalent() ==
                                       extent_position.DeepEquivalent())
     return selection.AsSelection();
@@ -102,7 +102,7 @@
     const IntPoint& extent_point,
     LocalFrame* frame) {
   const VisibleSelection& selection =
-      frame->Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
+      frame->Selection().ComputeVisibleSelectionInDOMTree();
 
   if (state_ == StrategyState::kCleared)
     state_ = StrategyState::kExpanding;
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h
index 3e05917..96792811 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h
@@ -11,6 +11,10 @@
 namespace blink {
 
 class LocalFrame;
+class Node;
+class WebFrameClient;
+class WebTextCheckClient;
+class WebViewBase;
 
 // WebLocalFrameBase is a temporary class the provides a layer of abstraction
 // for WebLocalFrameImpl. Mehtods that are declared public in WebLocalFrameImpl
@@ -25,6 +29,12 @@
   CORE_EXPORT static WebLocalFrameBase* FromFrame(LocalFrame*);
   CORE_EXPORT static WebLocalFrameBase* FromFrame(LocalFrame&);
 
+  virtual WebViewBase* ViewImpl() const = 0;
+  virtual WebFrameClient* Client() const = 0;
+  virtual WebTextCheckClient* TextCheckClient() const = 0;
+  virtual void SetContextMenuNode(Node*) = 0;
+  virtual void ClearContextMenuNode() = 0;
+
  protected:
   explicit WebLocalFrameBase(WebTreeScopeType scope) : WebLocalFrame(scope) {}
 };
diff --git a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
index e0edd169..beb514f 100644
--- a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
@@ -213,8 +213,9 @@
   HTMLElement::AttributeChanged(params);
 }
 
-static bool WasInShadowTreeBeforeInserted(HTMLSlotElement& slot,
-                                          ContainerNode& insertion_point) {
+static bool WasInDifferentShadowTreeBeforeInserted(
+    HTMLSlotElement& slot,
+    ContainerNode& insertion_point) {
   ShadowRoot* root1 = slot.ContainingShadowRoot();
   ShadowRoot* root2 = insertion_point.ContainingShadowRoot();
   if (root1 && root2 && root1 == root2)
@@ -232,7 +233,8 @@
     // Relevant DOM Standard: https://dom.spec.whatwg.org/#concept-node-insert
     // - 6.4:  Run assign slotables for a tree with node's tree and a set
     // containing each inclusive descendant of node that is a slot.
-    if (root->IsV1() && !WasInShadowTreeBeforeInserted(*this, *insertion_point))
+    if (root->IsV1() &&
+        !WasInDifferentShadowTreeBeforeInserted(*this, *insertion_point))
       root->DidAddSlot(*this);
   }
 
diff --git a/third_party/WebKit/Source/core/layout/BackgroundBleedAvoidance.h b/third_party/WebKit/Source/core/layout/BackgroundBleedAvoidance.h
index 8e35469..2f469081 100644
--- a/third_party/WebKit/Source/core/layout/BackgroundBleedAvoidance.h
+++ b/third_party/WebKit/Source/core/layout/BackgroundBleedAvoidance.h
@@ -14,6 +14,11 @@
   kBackgroundBleedClipLayer,
 };
 
+inline bool BleedAvoidanceIsClipping(BackgroundBleedAvoidance bleed_avoidance) {
+  return bleed_avoidance == kBackgroundBleedClipOnly ||
+         bleed_avoidance == kBackgroundBleedClipLayer;
+}
+
 }  // namespace blink
 
 #endif  // BackgroundBleedAvoidance_h
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
index 9b70c14..9af6417e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -253,19 +253,8 @@
     // we need to clear any override size set previously, so it doesn't
     // interfere in current layout execution.
     for (auto* child = FirstInFlowChildBox(); child;
-         child = child->NextInFlowSiblingBox()) {
+         child = child->NextInFlowSiblingBox())
       child->ClearOverrideSize();
-      if (!IsOrthogonalChild(*child) ||
-          (!SizesLogicalWidthToFitContent(StyleRef().LogicalWidth()) &&
-           !StyleRef().LogicalWidth().IsIntrinsicOrAuto()))
-        continue;
-      // Additionally, we may need to clear containingBlock override sizes and
-      // force a layout of the grid items to ensure we get the same result when
-      // grid's intrinsic size is computed again in the updateLogicalWidth call
-      // bellow.
-      child->ClearContainingBlockOverrideSize();
-      child->ForceLayout();
-    }
 
     UpdateLogicalWidth();
 
diff --git a/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp b/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp
index 4e422e72..d5b98c1 100644
--- a/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp
@@ -334,11 +334,6 @@
   }
 }
 
-bool BleedAvoidanceIsClipping(BackgroundBleedAvoidance bleed_avoidance) {
-  return bleed_avoidance == kBackgroundBleedClipOnly ||
-         bleed_avoidance == kBackgroundBleedClipLayer;
-}
-
 // The LUTs below assume specific enum values.
 static_assert(kBorderStyleNone == 0, "unexpected EBorderStyle value");
 static_assert(kBorderStyleHidden == 1, "unexpected EBorderStyle value");
diff --git a/third_party/WebKit/Source/core/paint/BoxPainter.cpp b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
index 7eae8c15..07c01ce 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
@@ -100,15 +100,6 @@
   return bounds;
 }
 
-namespace {
-
-bool BleedAvoidanceIsClipping(BackgroundBleedAvoidance bleed_avoidance) {
-  return bleed_avoidance == kBackgroundBleedClipOnly ||
-         bleed_avoidance == kBackgroundBleedClipLayer;
-}
-
-}  // anonymous namespace
-
 void BoxPainter::PaintBoxDecorationBackgroundWithRect(
     const PaintInfo& paint_info,
     const LayoutPoint& paint_offset,
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
index 779c340..6bf37ce7 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -67,7 +67,6 @@
   // Emulates deprecated API use on DedicatedWorkerGlobalScope.
   void CountDeprecation(UseCounter::Feature feature) {
     EXPECT_TRUE(IsCurrentThread());
-    EXPECT_EQ(0u, GetConsoleMessageStorage()->size());
     GlobalScope()->CountDeprecation(feature);
 
     // countDeprecation() should add a warning message.
@@ -81,6 +80,38 @@
   }
 };
 
+class InProcessWorkerObjectProxyForTest final
+    : public InProcessWorkerObjectProxy {
+ public:
+  InProcessWorkerObjectProxyForTest(
+      const WeakPtr<InProcessWorkerMessagingProxy>& messaging_proxy_weak_ptr,
+      ParentFrameTaskRunners* parent_frame_task_runners)
+      : InProcessWorkerObjectProxy(messaging_proxy_weak_ptr,
+                                   parent_frame_task_runners),
+        reported_features_(UseCounter::kNumberOfFeatures) {
+    default_interval_in_sec_ = kDefaultIntervalInSec;
+    next_interval_in_sec_ = kNextIntervalInSec;
+    max_interval_in_sec_ = kMaxIntervalInSec;
+  }
+
+  void CountFeature(UseCounter::Feature feature) override {
+    // Any feature should be reported only one time.
+    EXPECT_FALSE(reported_features_.QuickGet(feature));
+    reported_features_.QuickSet(feature);
+    InProcessWorkerObjectProxy::CountFeature(feature);
+  }
+
+  void CountDeprecation(UseCounter::Feature feature) override {
+    // Any feature should be reported only one time.
+    EXPECT_FALSE(reported_features_.QuickGet(feature));
+    reported_features_.QuickSet(feature);
+    InProcessWorkerObjectProxy::CountDeprecation(feature);
+  }
+
+ private:
+  BitVector reported_features_;
+};
+
 class InProcessWorkerMessagingProxyForTest
     : public InProcessWorkerMessagingProxy {
  public:
@@ -88,10 +119,8 @@
       : InProcessWorkerMessagingProxy(execution_context,
                                       nullptr /* workerObject */,
                                       nullptr /* workerClients */) {
-    WorkerObjectProxy().default_interval_in_sec_ = kDefaultIntervalInSec;
-    WorkerObjectProxy().next_interval_in_sec_ = kNextIntervalInSec;
-    WorkerObjectProxy().max_interval_in_sec_ = kMaxIntervalInSec;
-
+    worker_object_proxy_ = WTF::MakeUnique<InProcessWorkerObjectProxyForTest>(
+        weak_ptr_factory_.CreateWeakPtr(), GetParentFrameTaskRunners());
     worker_loader_proxy_provider_ =
         WTF::MakeUnique<WorkerLoaderProxyProvider>();
     worker_thread_ = WTF::WrapUnique(new DedicatedWorkerThreadForTest(
@@ -399,6 +428,15 @@
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature1));
 
+  // API use should be reported to the Document only one time. See comments in
+  // InProcessWorkerObjectProxyForTest::CountFeature.
+  TaskRunnerHelper::Get(TaskType::kUnspecedTimer, GetWorkerThread())
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&DedicatedWorkerThreadForTest::CountFeature,
+                          CrossThreadUnretained(GetWorkerThread()), kFeature1));
+  testing::EnterRunLoop();
+
   // This feature is randomly selected from Deprecation::deprecationMessage().
   const UseCounter::Feature kFeature2 =
       UseCounter::Feature::kPrefixedStorageInfo;
@@ -413,6 +451,15 @@
                           CrossThreadUnretained(GetWorkerThread()), kFeature2));
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature2));
+
+  // API use should be reported to the Document only one time. See comments in
+  // InProcessWorkerObjectProxyForTest::CountDeprecation.
+  TaskRunnerHelper::Get(TaskType::kUnspecedTimer, GetWorkerThread())
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&DedicatedWorkerThreadForTest::CountDeprecation,
+                          CrossThreadUnretained(GetWorkerThread()), kFeature2));
+  testing::EnterRunLoop();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
index 3dd4b62..60baf1ce 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
@@ -87,7 +87,7 @@
   WeakPtr<ThreadedMessagingProxyBase> MessagingProxyWeakPtr() final;
 
  private:
-  friend class InProcessWorkerMessagingProxyForTest;
+  friend class InProcessWorkerObjectProxyForTest;
 
   void StartPendingActivityTimer();
   void CheckPendingActivity(TimerBase*);
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
index 0e6ea30e..daaefd8 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
@@ -26,19 +26,18 @@
 
 MainThreadWorkletGlobalScope::~MainThreadWorkletGlobalScope() {}
 
-void MainThreadWorkletGlobalScope::CountFeature(UseCounter::Feature feature) {
+void MainThreadWorkletGlobalScope::ReportFeature(UseCounter::Feature feature) {
   DCHECK(IsMainThread());
   // A parent document is on the same thread, so just record API use in the
   // document's UseCounter.
   UseCounter::Count(GetFrame(), feature);
 }
 
-void MainThreadWorkletGlobalScope::CountDeprecation(
+void MainThreadWorkletGlobalScope::ReportDeprecation(
     UseCounter::Feature feature) {
   DCHECK(IsMainThread());
   // A parent document is on the same thread, so just record API use in the
   // document's UseCounter.
-  AddDeprecationMessage(feature);
   Deprecation::CountDeprecation(GetFrame(), feature);
 }
 
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
index f40405b..1fe4a060 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
@@ -34,8 +34,8 @@
   bool IsMainThreadWorkletGlobalScope() const final { return true; }
 
   // WorkerOrWorkletGlobalScope
-  void CountFeature(UseCounter::Feature) final;
-  void CountDeprecation(UseCounter::Feature) final;
+  void ReportFeature(UseCounter::Feature) override;
+  void ReportDeprecation(UseCounter::Feature) override;
   WorkerThread* GetThread() const final;
 
   void FetchAndInvokeScript(const KURL& module_url_record,
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
index 5fedf9f6..ba8f151 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
@@ -11,6 +11,39 @@
 
 namespace blink {
 
+class MainThreadWorkletGlobalScopeForTest
+    : public MainThreadWorkletGlobalScope {
+ public:
+  MainThreadWorkletGlobalScopeForTest(LocalFrame* frame,
+                                      const KURL& url,
+                                      const String& user_agent,
+                                      RefPtr<SecurityOrigin> security_origin,
+                                      v8::Isolate* isolate)
+      : MainThreadWorkletGlobalScope(frame,
+                                     url,
+                                     user_agent,
+                                     std::move(security_origin),
+                                     isolate),
+        reported_features_(UseCounter::kNumberOfFeatures) {}
+
+  void ReportFeature(UseCounter::Feature feature) override {
+    // Any feature should be reported only one time.
+    EXPECT_FALSE(reported_features_.QuickGet(feature));
+    reported_features_.QuickSet(feature);
+    MainThreadWorkletGlobalScope::ReportFeature(feature);
+  }
+
+  void ReportDeprecation(UseCounter::Feature feature) final {
+    // Any feature should be reported only one time.
+    EXPECT_FALSE(reported_features_.QuickGet(feature));
+    reported_features_.QuickSet(feature);
+    MainThreadWorkletGlobalScope::ReportDeprecation(feature);
+  }
+
+ private:
+  BitVector reported_features_;
+};
+
 class MainThreadWorkletTest : public ::testing::Test {
  public:
   void SetUp() override {
@@ -42,6 +75,10 @@
   UseCounter::Count(global_scope_, kFeature1);
   EXPECT_TRUE(UseCounter::IsCounted(document, kFeature1));
 
+  // API use should be reported to the Document only one time. See comments in
+  // MainThreadGlobalScopeForTest::ReportFeature.
+  UseCounter::Count(global_scope_, kFeature1);
+
   // This feature is randomly selected from Deprecation::deprecationMessage().
   const UseCounter::Feature kFeature2 =
       UseCounter::Feature::kPrefixedStorageInfo;
@@ -51,6 +88,10 @@
   EXPECT_FALSE(UseCounter::IsCounted(document, kFeature2));
   Deprecation::CountDeprecation(global_scope_, kFeature2);
   EXPECT_TRUE(UseCounter::IsCounted(document, kFeature2));
+
+  // API use should be reported to the Document only one time. See comments in
+  // MainThreadWorkletGlobalScopeForTest::ReportDeprecation.
+  Deprecation::CountDeprecation(global_scope_, kFeature2);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.cpp
index acd9721..f3a1a74 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.cpp
@@ -30,16 +30,16 @@
   DCHECK(!thread_);
 }
 
-void ThreadedWorkletGlobalScope::CountFeature(UseCounter::Feature feature) {
+void ThreadedWorkletGlobalScope::ReportFeature(UseCounter::Feature feature) {
   DCHECK(IsContextThread());
   DCHECK(thread_);
   thread_->GetWorkerReportingProxy().CountFeature(feature);
 }
 
-void ThreadedWorkletGlobalScope::CountDeprecation(UseCounter::Feature feature) {
+void ThreadedWorkletGlobalScope::ReportDeprecation(
+    UseCounter::Feature feature) {
   DCHECK(IsContextThread());
   DCHECK(thread_);
-  AddDeprecationMessage(feature);
   thread_->GetWorkerReportingProxy().CountDeprecation(feature);
 }
 
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.h
index 5b8795c..81ae12b 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletGlobalScope.h
@@ -16,8 +16,8 @@
  public:
   ~ThreadedWorkletGlobalScope() override;
   void Dispose() override;
-  void CountFeature(UseCounter::Feature) final;
-  void CountDeprecation(UseCounter::Feature) final;
+  void ReportFeature(UseCounter::Feature) override;
+  void ReportDeprecation(UseCounter::Feature) override;
 
   // ExecutionContext
   bool IsThreadedWorkletGlobalScope() const final { return true; }
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.h b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.h
index 7e057206..3e288c7 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.h
@@ -32,6 +32,8 @@
   }
 
  private:
+  friend class ThreadedWorkletMessagingProxyForTest;
+
   std::unique_ptr<ThreadedWorkletObjectProxy> worklet_object_proxy_;
 
   WeakPtrFactory<ThreadedWorkletMessagingProxy> weak_ptr_factory_;
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
index b979310f..e9a2c962 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -20,6 +20,35 @@
 
 namespace blink {
 
+class ThreadedWorkletObjectProxyForTest final
+    : public ThreadedWorkletObjectProxy {
+ public:
+  ThreadedWorkletObjectProxyForTest(
+      const WeakPtr<ThreadedWorkletMessagingProxy>& messaging_proxy_weak_ptr,
+      ParentFrameTaskRunners* parent_frame_task_runners)
+      : ThreadedWorkletObjectProxy(messaging_proxy_weak_ptr,
+                                   parent_frame_task_runners),
+        reported_features_(UseCounter::kNumberOfFeatures) {}
+
+ protected:
+  void CountFeature(UseCounter::Feature feature) override {
+    // Any feature should be reported only one time.
+    EXPECT_FALSE(reported_features_.QuickGet(feature));
+    reported_features_.QuickSet(feature);
+    ThreadedWorkletObjectProxy::CountFeature(feature);
+  }
+
+  void CountDeprecation(UseCounter::Feature feature) final {
+    // Any feature should be reported only one time.
+    EXPECT_FALSE(reported_features_.QuickGet(feature));
+    reported_features_.QuickSet(feature);
+    ThreadedWorkletObjectProxy::CountDeprecation(feature);
+  }
+
+ private:
+  BitVector reported_features_;
+};
+
 class ThreadedWorkletThreadForTest : public WorkerThread {
  public:
   ThreadedWorkletThreadForTest(
@@ -27,7 +56,7 @@
       WorkerReportingProxy& worker_reporting_proxy)
       : WorkerThread(WorkerLoaderProxy::Create(worker_loader_proxy_provider),
                      worker_reporting_proxy) {}
-  ~ThreadedWorkletThreadForTest() override{};
+  ~ThreadedWorkletThreadForTest() override {}
 
   WorkerBackingThread& GetWorkerBackingThread() override {
     auto worklet_thread_holder =
@@ -72,7 +101,6 @@
   // Emulates deprecated API use on ThreadedWorkletGlobalScope.
   void CountDeprecation(UseCounter::Feature feature) {
     EXPECT_TRUE(IsCurrentThread());
-    EXPECT_EQ(0u, GetConsoleMessageStorage()->size());
     GlobalScope()->CountDeprecation(feature);
 
     // countDeprecation() should add a warning message.
@@ -91,6 +119,8 @@
  public:
   ThreadedWorkletMessagingProxyForTest(ExecutionContext* execution_context)
       : ThreadedWorkletMessagingProxy(execution_context) {
+    worklet_object_proxy_ = WTF::MakeUnique<ThreadedWorkletObjectProxyForTest>(
+        weak_ptr_factory_.CreateWeakPtr(), GetParentFrameTaskRunners());
     worker_loader_proxy_provider_ =
         WTF::MakeUnique<WorkerLoaderProxyProvider>();
     worker_thread_ = WTF::MakeUnique<ThreadedWorkletThreadForTest>(
@@ -170,7 +200,7 @@
   // This feature is randomly selected.
   const UseCounter::Feature kFeature1 = UseCounter::Feature::kRequestFileSystem;
 
-  // API use on the DedicatedWorkerGlobalScope should be recorded in UseCounter
+  // API use on the ThreadedWorkletGlobalScope should be recorded in UseCounter
   // on the Document.
   EXPECT_FALSE(UseCounter::IsCounted(GetDocument(), kFeature1));
   TaskRunnerHelper::Get(TaskType::kUnspecedTimer, GetWorkerThread())
@@ -181,6 +211,15 @@
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature1));
 
+  // API use should be reported to the Document only one time. See comments in
+  // ThreadedWorkletGlobalScopeForTest::CountFeature.
+  TaskRunnerHelper::Get(TaskType::kUnspecedTimer, GetWorkerThread())
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&ThreadedWorkletThreadForTest::CountFeature,
+                          CrossThreadUnretained(GetWorkerThread()), kFeature1));
+  testing::EnterRunLoop();
+
   // This feature is randomly selected from Deprecation::deprecationMessage().
   const UseCounter::Feature kFeature2 =
       UseCounter::Feature::kPrefixedStorageInfo;
@@ -195,6 +234,15 @@
                           CrossThreadUnretained(GetWorkerThread()), kFeature2));
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature2));
+
+  // API use should be reported to the Document only one time. See comments in
+  // ThreadedWorkletGlobalScopeForTest::CountDeprecation.
+  TaskRunnerHelper::Get(TaskType::kUnspecedTimer, GetWorkerThread())
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&ThreadedWorkletThreadForTest::CountDeprecation,
+                          CrossThreadUnretained(GetWorkerThread()), kFeature2));
+  testing::EnterRunLoop();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index a15ff06..a88ef27 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -112,16 +112,15 @@
   thread_ = nullptr;
 }
 
-void WorkerGlobalScope::CountFeature(UseCounter::Feature feature) {
+void WorkerGlobalScope::ReportFeature(UseCounter::Feature feature) {
   DCHECK(IsContextThread());
   DCHECK(thread_);
   thread_->GetWorkerReportingProxy().CountFeature(feature);
 }
 
-void WorkerGlobalScope::CountDeprecation(UseCounter::Feature feature) {
+void WorkerGlobalScope::ReportDeprecation(UseCounter::Feature feature) {
   DCHECK(IsContextThread());
   DCHECK(thread_);
-  AddDeprecationMessage(feature);
   thread_->GetWorkerReportingProxy().CountDeprecation(feature);
 }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
index e4a9bd8f..03e28e2d 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -84,8 +84,8 @@
   // WorkerOrWorkletGlobalScope
   bool IsClosing() const final { return closing_; }
   virtual void Dispose();
-  void CountFeature(UseCounter::Feature) final;
-  void CountDeprecation(UseCounter::Feature) final;
+  void ReportFeature(UseCounter::Feature) final;
+  void ReportDeprecation(UseCounter::Feature) final;
   WorkerThread* GetThread() const final { return thread_; }
 
   void ExceptionUnhandled(int exception_id);
diff --git a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp
index 322045ff..8743d587 100644
--- a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp
@@ -17,24 +17,33 @@
 namespace blink {
 
 WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope()
-    : deprecation_warning_bits_(UseCounter::kNumberOfFeatures) {}
+    : used_features_(UseCounter::kNumberOfFeatures) {}
 
 WorkerOrWorkletGlobalScope::~WorkerOrWorkletGlobalScope() = default;
 
-void WorkerOrWorkletGlobalScope::AddDeprecationMessage(
-    UseCounter::Feature feature) {
+void WorkerOrWorkletGlobalScope::CountFeature(UseCounter::Feature feature) {
   DCHECK_NE(UseCounter::kOBSOLETE_PageDestruction, feature);
   DCHECK_GT(UseCounter::kNumberOfFeatures, feature);
-
-  // For each deprecated feature, send console message at most once
-  // per worker lifecycle.
-  if (deprecation_warning_bits_.QuickGet(feature))
+  if (used_features_.QuickGet(feature))
     return;
-  deprecation_warning_bits_.QuickSet(feature);
+  used_features_.QuickSet(feature);
+  ReportFeature(feature);
+}
+
+void WorkerOrWorkletGlobalScope::CountDeprecation(UseCounter::Feature feature) {
+  DCHECK_NE(UseCounter::kOBSOLETE_PageDestruction, feature);
+  DCHECK_GT(UseCounter::kNumberOfFeatures, feature);
+  if (used_features_.QuickGet(feature))
+    return;
+  used_features_.QuickSet(feature);
+
+  // Adds a deprecation message to the console.
   DCHECK(!Deprecation::DeprecationMessage(feature).IsEmpty());
   AddConsoleMessage(
       ConsoleMessage::Create(kDeprecationMessageSource, kWarningMessageLevel,
                              Deprecation::DeprecationMessage(feature)));
+
+  ReportDeprecation(feature);
 }
 
 void WorkerOrWorkletGlobalScope::PostTask(
diff --git a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h
index 8eb68d9..2fd4a65 100644
--- a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h
@@ -41,24 +41,25 @@
   virtual void Dispose() = 0;
 
   // Called from UseCounter to record API use in this execution context.
-  virtual void CountFeature(UseCounter::Feature) = 0;
+  void CountFeature(UseCounter::Feature);
 
   // Called from UseCounter to record deprecated API use in this execution
-  // context. Sub-classes should call addDeprecationMessage() in this function.
-  virtual void CountDeprecation(UseCounter::Feature) = 0;
+  // context.
+  void CountDeprecation(UseCounter::Feature);
 
   // May return nullptr if this global scope is not threaded (i.e.,
   // MainThreadWorkletGlobalScope) or after dispose() is called.
   virtual WorkerThread* GetThread() const = 0;
 
  protected:
-  // Adds a deprecation message to the console.
-  void AddDeprecationMessage(UseCounter::Feature);
+  virtual void ReportFeature(UseCounter::Feature) = 0;
+  virtual void ReportDeprecation(UseCounter::Feature) = 0;
 
  private:
   void RunTask(std::unique_ptr<ExecutionContextTask>, bool is_instrumented);
 
-  BitVector deprecation_warning_bits_;
+  // This is the set of features that this worker has used.
+  BitVector used_features_;
 };
 
 DEFINE_TYPE_CASTS(
diff --git a/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp b/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp
index 7bf2ce96..0c7e7095 100644
--- a/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp
+++ b/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp
@@ -13,6 +13,7 @@
 #include "platform/blob/BlobData.h"
 #include "platform/wtf/Functional.h"
 #include "platform/wtf/RefPtr.h"
+#include "v8/include/v8.h"
 
 namespace blink {
 
@@ -114,6 +115,13 @@
     Chunk(const char* data, size_t size) {
       buffer_.ReserveInitialCapacity(size);
       buffer_.Append(data, size);
+      // Report buffer size to V8 so GC can be triggered appropriately.
+      v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+          static_cast<int64_t>(buffer_.size()));
+    }
+    ~Chunk() {
+      v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+          -static_cast<int64_t>(buffer_.size()));
     }
     const char* data() const { return buffer_.data(); }
     size_t size() const { return buffer_.size(); }
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
index 6034d49..fd9efd5 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
@@ -220,9 +220,6 @@
   // Test case 6 (User-specified buffer size): 960 Pull, 128 Push. Minimal
   // Jitter. 960 frames = 20ms at 48KHz.
   {48000, 2, 8192, 1000, 960, 1, 128, 1},
-
-  // Test case 7 (Longer test duration): 256 Pull, 128 Push. 10 seconds.
-  {48000, 2, 8192, 10000, 256, 0, 128, 1}
 };
 
 INSTANTIATE_TEST_CASE_P(PushPullFIFOSmokeTest,
diff --git a/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp b/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
index c1e00ad..f5151fa2 100644
--- a/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
@@ -44,6 +44,7 @@
 #include "core/frame/FrameView.h"
 #include "core/frame/Settings.h"
 #include "core/frame/VisualViewport.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/html/HTMLAnchorElement.h"
 #include "core/html/HTMLFormElement.h"
 #include "core/html/HTMLImageElement.h"
@@ -78,7 +79,6 @@
 #include "public/web/WebTextCheckClient.h"
 #include "public/web/WebViewClient.h"
 #include "web/ContextMenuAllowedScope.h"
-#include "web/WebLocalFrameImpl.h"
 #include "web/WebPluginContainerImpl.h"
 
 namespace blink {
@@ -189,8 +189,8 @@
   r.SetToShadowHostIfInRestrictedShadowRoot();
 
   LocalFrame* selected_frame = r.InnerNodeFrame();
-  WebLocalFrameImpl* selected_web_frame =
-      WebLocalFrameImpl::FromFrame(selected_frame);
+  WebLocalFrameBase* selected_web_frame =
+      WebLocalFrameBase::FromFrame(selected_frame);
 
   WebContextMenuData data;
   data.mouse_position = selected_frame->View()->ContentsToViewport(
@@ -420,8 +420,8 @@
   if (!selected_frame)
     return;
 
-  WebLocalFrameImpl* selected_web_frame =
-      WebLocalFrameImpl::FromFrame(selected_frame);
+  WebLocalFrameBase* selected_web_frame =
+      WebLocalFrameBase::FromFrame(selected_frame);
   selected_web_frame->ClearContextMenuNode();
 }
 
diff --git a/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp b/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp
index 8dbb41a..7ba9312 100644
--- a/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp
+++ b/third_party/WebKit/Source/web/DedicatedWorkerMessagingProxyProviderImpl.cpp
@@ -31,6 +31,7 @@
 #include "web/DedicatedWorkerMessagingProxyProviderImpl.h"
 
 #include "core/dom/Document.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/loader/WorkerFetchContext.h"
 #include "core/workers/DedicatedWorkerMessagingProxy.h"
 #include "core/workers/Worker.h"
@@ -46,7 +47,6 @@
 #include "public/web/WebWorkerContentSettingsClientProxy.h"
 #include "web/IndexedDBClientImpl.h"
 #include "web/LocalFileSystemClient.h"
-#include "web/WebLocalFrameImpl.h"
 
 namespace blink {
 
@@ -59,8 +59,8 @@
     Worker* worker) {
   if (worker->GetExecutionContext()->IsDocument()) {
     Document* document = ToDocument(worker->GetExecutionContext());
-    WebLocalFrameImpl* web_frame =
-        WebLocalFrameImpl::FromFrame(document->GetFrame());
+    WebLocalFrameBase* web_frame =
+        WebLocalFrameBase::FromFrame(document->GetFrame());
     WorkerClients* worker_clients = WorkerClients::Create();
     ProvideIndexedDBClientToWorker(
         worker_clients, IndexedDBClientImpl::Create(*worker_clients));
diff --git a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp
index 53eb4fc..a681c4a 100644
--- a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp
@@ -10,6 +10,7 @@
 #include "core/events/WheelEvent.h"
 #include "core/frame/RemoteFrame.h"
 #include "core/frame/RemoteFrameView.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/layout/api/LayoutItem.h"
 #include "core/layout/api/LayoutPartItem.h"
 #include "platform/exported/WrappedResourceRequest.h"
@@ -19,7 +20,6 @@
 #include "platform/wtf/PtrUtil.h"
 #include "public/web/WebRemoteFrameClient.h"
 #include "web/WebInputEventConversion.h"
-#include "web/WebLocalFrameImpl.h"
 #include "web/WebRemoteFrameImpl.h"
 
 namespace blink {
@@ -132,7 +132,7 @@
     LocalFrame* source_frame) const {
   if (web_frame_->Client())
     web_frame_->Client()->ForwardPostMessage(
-        WebLocalFrameImpl::FromFrame(source_frame), web_frame_,
+        WebLocalFrameBase::FromFrame(source_frame), web_frame_,
         WebSecurityOrigin(std::move(target)), WebDOMMessageEvent(event));
 }
 
@@ -148,7 +148,7 @@
 void RemoteFrameClientImpl::AdvanceFocus(WebFocusType type,
                                          LocalFrame* source) {
   web_frame_->Client()->AdvanceFocus(type,
-                                     WebLocalFrameImpl::FromFrame(source));
+                                     WebLocalFrameBase::FromFrame(source));
 }
 
 void RemoteFrameClientImpl::VisibilityChanged(bool visible) {
diff --git a/third_party/WebKit/Source/web/WebAXObject.cpp b/third_party/WebKit/Source/web/WebAXObject.cpp
index bef659e..a9efc6c 100644
--- a/third_party/WebKit/Source/web/WebAXObject.cpp
+++ b/third_party/WebKit/Source/web/WebAXObject.cpp
@@ -39,6 +39,7 @@
 #include "core/exported/WebViewBase.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/VisualViewport.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/input/KeyboardEventManager.h"
 #include "core/page/Page.h"
 #include "core/style/ComputedStyle.h"
@@ -57,7 +58,6 @@
 #include "public/web/WebDocument.h"
 #include "public/web/WebElement.h"
 #include "public/web/WebNode.h"
-#include "web/WebLocalFrameImpl.h"
 
 namespace blink {
 
@@ -944,7 +944,7 @@
   if (!frame)
     return;
 
-  WebViewBase* view = WebLocalFrameImpl::FromFrame(frame)->ViewImpl();
+  WebViewBase* view = WebLocalFrameBase::FromFrame(frame)->ViewImpl();
   if (!view)
     return;
 
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
index b7d6844..c4973398 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -360,7 +360,7 @@
   static WebPluginContainerImpl* CurrentPluginContainer(LocalFrame*,
                                                         Node* = nullptr);
 
-  WebViewBase* ViewImpl() const;
+  WebViewBase* ViewImpl() const override;
 
   FrameView* GetFrameView() const {
     return GetFrame() ? GetFrame()->View() : 0;
@@ -391,7 +391,7 @@
   // Otherwise, disallow scrolling.
   void SetCanHaveScrollbars(bool) override;
 
-  WebFrameClient* Client() const { return client_; }
+  WebFrameClient* Client() const override { return client_; }
   void SetClient(WebFrameClient* client) { client_ = client; }
 
   ContentSettingsClient& GetContentSettingsClient() {
@@ -407,7 +407,9 @@
   static void SelectWordAroundPosition(LocalFrame*, VisiblePosition);
 
   TextCheckerClient& GetTextCheckerClient() const;
-  WebTextCheckClient* TextCheckClient() const { return text_check_client_; }
+  WebTextCheckClient* TextCheckClient() const override {
+    return text_check_client_;
+  }
 
   TextFinder* GetTextFinder() const;
   // Returns the text finder object if it already exists.
@@ -428,8 +430,8 @@
   }
 
   WebNode ContextMenuNode() const { return context_menu_node_.Get(); }
-  void SetContextMenuNode(Node* node) { context_menu_node_ = node; }
-  void ClearContextMenuNode() { context_menu_node_.Clear(); }
+  void SetContextMenuNode(Node* node) override { context_menu_node_ = node; }
+  void ClearContextMenuNode() override { context_menu_node_.Clear(); }
 
   DECLARE_TRACE();
 
diff --git a/third_party/WebKit/Source/web/WebNode.cpp b/third_party/WebKit/Source/web/WebNode.cpp
index 9ea216f1..390399c 100644
--- a/third_party/WebKit/Source/web/WebNode.cpp
+++ b/third_party/WebKit/Source/web/WebNode.cpp
@@ -56,8 +56,6 @@
 #include "public/web/WebElement.h"
 #include "public/web/WebElementCollection.h"
 #include "public/web/WebPluginContainer.h"
-#include "web/LocalFrameClientImpl.h"
-#include "web/WebLocalFrameImpl.h"
 #include "web/WebPluginContainerImpl.h"
 
 namespace blink {
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index 69a0a6f8..871da5e2 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -215,6 +215,7 @@
     <classpathentry kind="src" path="out/Debug/java_mojo/mojo_public_test_interfaces_mojom/src"/>
     <classpathentry kind="src" path="out/Debug/java_proto/cacheinvalidation_proto_java/src"/>
     <classpathentry kind="src" path="out/Debug/java_proto/document_tab_model_info_proto_java/src"/>
+    <classpathentry kind="src" path="out/Debug/java_proto/partner_location_descriptor_proto_java/src"/>
     <classpathentry kind="src" path="out/Debug/java_proto/test_support_proto_java/src"/>
     <classpathentry kind="src" path="out/Debug/remoting_apk/gen"/>
     <classpathentry kind="lib" path="third_party/android_tools/sdk/extras/google/gcm/gcm-client/dist/gcm.jar" sourcepath="third_party/android_tools/sdk/extras/google/gcm/gcm-client/src"/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 6968841..7baf69d 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -21889,7 +21889,9 @@
   <int value="1108663108" label="disable-device-discovery-notifications"/>
   <int value="1113365156" label="tab-management-experiment-type-chive"/>
   <int value="1114629582" label="enable-floating-virtual-keyboard"/>
+  <int value="1116593018" label="CaptureThumbnailOnLoadFinished:disabled"/>
   <int value="1118109174" label="enable-launcher-search-provider-api"/>
+  <int value="1126061778" label="CaptureThumbnailOnLoadFinished:enabled"/>
   <int value="1127183523" label="PassiveEventListenersDueToFling:enabled"/>
   <int value="1127427821" label="OmniboxEntitySuggestions:disabled"/>
   <int value="1129888794" label="ash-touch-hud"/>
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc
index 28cb247..83c969d 100644
--- a/ui/message_center/views/message_list_view.cc
+++ b/ui/message_center/views/message_list_view.cc
@@ -560,6 +560,9 @@
   new_bounds.set_x(new_bounds.right() + kMarginBetweenItems);
   animator_.AnimateViewTo(child, new_bounds);
 
+  // Deleting the child after animation.
+  deleted_when_done_.insert(child);
+
   // Schedule to start sliding out next notification after a short delay.
   if (!clearing_all_views_.empty()) {
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
diff --git a/ui/message_center/views/message_list_view_unittest.cc b/ui/message_center/views/message_list_view_unittest.cc
index 8d139a8..3afd6e7 100644
--- a/ui/message_center/views/message_list_view_unittest.cc
+++ b/ui/message_center/views/message_list_view_unittest.cc
@@ -59,7 +59,11 @@
 MockNotificationView::MockNotificationView(MessageCenterController* controller,
                                            const Notification& notification,
                                            Test* test)
-    : NotificationView(controller, notification), test_(test) {}
+    : NotificationView(controller, notification), test_(test) {
+  // Calling SetPaintToLayer() to ensure that this view has its own layer.
+  // This layer is needed to enable adding/removal animations.
+  SetPaintToLayer();
+}
 
 MockNotificationView::~MockNotificationView() {}
 
@@ -441,15 +445,48 @@
 
   RunPendingAnimations();
 
-  // TODO(yhanada): notification_view1 and notification_view2 should be deleted
-  //                here. Uncomment the below test.
-  EXPECT_TRUE(gfx::IntersectRects(notification_view1->bounds(),
-                                  message_list_view()->bounds())
-                  .IsEmpty());
-  EXPECT_TRUE(gfx::IntersectRects(notification_view2->bounds(),
-                                  message_list_view()->bounds())
-                  .IsEmpty());
-  // EXPECT_EQ(0, message_list_view()->child_count());
+  EXPECT_EQ(0, message_list_view()->child_count());
+}
+
+// Regression test for crbug.com/713983
+TEST_F(MessageListViewTest, RemoveWhileClearAll) {
+  message_list_view()->SetBounds(0, 0, 800, 600);
+
+  // Create dummy notifications.
+  auto* notification_view1 = CreateNotificationView(
+      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
+                   base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"),
+                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+                   NotifierId(NotifierId::APPLICATION, "extension_id"),
+                   message_center::RichNotificationData(), nullptr));
+  auto* notification_view2 = CreateNotificationView(
+      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
+                   base::UTF8ToUTF16("title 2"), base::UTF8ToUTF16("message2"),
+                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+                   NotifierId(NotifierId::APPLICATION, "extension_id"),
+                   message_center::RichNotificationData(), nullptr));
+
+  message_list_view()->AddNotificationAt(notification_view1, 0);
+  EXPECT_EQ(1, message_list_view()->child_count());
+
+  RunPendingAnimations();
+
+  message_list_view()->AddNotificationAt(notification_view2, 1);
+  EXPECT_EQ(2, message_list_view()->child_count());
+
+  RunPendingAnimations();
+
+  // Call RemoveNotification()
+  EXPECT_TRUE(message_list_view()->Contains(notification_view2));
+  message_list_view()->RemoveNotification(notification_view2);
+
+  // Call "Clear All" while notification_view2 is still in message_list_view.
+  EXPECT_TRUE(message_list_view()->Contains(notification_view2));
+  message_list_view()->ClearAllClosableNotifications(
+      message_list_view()->bounds());
+
+  RunPendingAnimations();
+  EXPECT_EQ(0, message_list_view()->child_count());
 }
 
 }  // namespace