[go: nahoru, domu]

cc: Split ThreadProxy into ProxyMain and ProxyImpl

This is the final patch that splits ThreadProxy into ProxyMain and
ProxyImpl routing all inter-proxy communication using ChannelMain
and ChannelImpl.

ThreadProxy currently implements the logic for glueing together the
Scheduler, LayerTreeHostImpl and the LayerTreeHost and separating these
components across the main and impl thread boundary. This patch isolates
the logic for this glue code in ThreadProxy exclusive to each thread to
ProxyMain and ProxyImpl. This will allow us to abstract the medium the
2 sides use to communicate with each other so these components can be
run across a thread/process/network boundary.

ThreadedChannel implements the in-process threaded case.

BUG=527200
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1417053005

Cr-Commit-Position: refs/heads/master@{#364034}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index df0083a..3be4ebb9 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -502,7 +502,9 @@
     "trees/proxy.h",
     "trees/proxy_common.cc",
     "trees/proxy_common.h",
+    "trees/proxy_impl.cc",
     "trees/proxy_impl.h",
+    "trees/proxy_main.cc",
     "trees/proxy_main.h",
     "trees/remote_proto_channel.h",
     "trees/scoped_abort_remaining_swap_promises.h",
@@ -512,8 +514,6 @@
     "trees/swap_promise_monitor.h",
     "trees/task_runner_provider.cc",
     "trees/task_runner_provider.h",
-    "trees/thread_proxy.cc",
-    "trees/thread_proxy.h",
     "trees/threaded_channel.cc",
     "trees/threaded_channel.h",
     "trees/tree_synchronizer.cc",
@@ -655,6 +655,10 @@
     "test/pixel_test_software_output_device.h",
     "test/pixel_test_utils.cc",
     "test/pixel_test_utils.h",
+    "test/proxy_impl_for_test.cc",
+    "test/proxy_impl_for_test.h",
+    "test/proxy_main_for_test.cc",
+    "test/proxy_main_for_test.h",
     "test/render_pass_test_utils.cc",
     "test/render_pass_test_utils.h",
     "test/scheduler_test_common.cc",
@@ -677,6 +681,8 @@
     "test/test_gles2_interface.h",
     "test/test_gpu_memory_buffer_manager.cc",
     "test/test_gpu_memory_buffer_manager.h",
+    "test/test_hooks.cc",
+    "test/test_hooks.h",
     "test/test_image_factory.cc",
     "test/test_image_factory.h",
     "test/test_in_process_context_provider.cc",
@@ -692,6 +698,8 @@
     "test/test_tile_priorities.h",
     "test/test_web_graphics_context_3d.cc",
     "test/test_web_graphics_context_3d.h",
+    "test/threaded_channel_for_test.cc",
+    "test/threaded_channel_for_test.h",
   ]
 
   configs += [ "//build/config:precompiled_headers" ]
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 508ff1c..7bce8be 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -564,7 +564,9 @@
         'trees/proxy.h',
         'trees/proxy_common.cc',
         'trees/proxy_common.h',
+        'trees/proxy_impl.cc',
         'trees/proxy_impl.h',
+        'trees/proxy_main.cc',
         'trees/proxy_main.h',
         'trees/remote_proto_channel.h',
         'trees/scoped_abort_remaining_swap_promises.h',
@@ -572,8 +574,6 @@
         'trees/single_thread_proxy.h',
         'trees/swap_promise_monitor.cc',
         'trees/swap_promise_monitor.h',
-        'trees/thread_proxy.cc',
-        'trees/thread_proxy.h',
         'trees/task_runner_provider.cc',
         'trees/task_runner_provider.h',
         'trees/threaded_channel.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 5332133..8ce17e2 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -258,6 +258,10 @@
       'test/pixel_test_software_output_device.h',
       'test/pixel_test_utils.cc',
       'test/pixel_test_utils.h',
+      'test/proxy_impl_for_test.cc',
+      'test/proxy_impl_for_test.h',
+      'test/proxy_main_for_test.cc',
+      'test/proxy_main_for_test.h',
       'test/render_pass_test_utils.cc',
       'test/render_pass_test_utils.h',
       'test/scheduler_test_common.cc',
@@ -280,6 +284,8 @@
       'test/test_gles2_interface.h',
       'test/test_gpu_memory_buffer_manager.cc',
       'test/test_gpu_memory_buffer_manager.h',
+      'test/test_hooks.cc',
+      'test/test_hooks.h',
       'test/test_image_factory.cc',
       'test/test_image_factory.h',
       'test/test_in_process_context_provider.cc',
@@ -295,6 +301,8 @@
       'test/test_tile_priorities.h',
       'test/test_web_graphics_context_3d.cc',
       'test/test_web_graphics_context_3d.h',
+      'test/threaded_channel_for_test.cc',
+      'test/threaded_channel_for_test.h',
     ],
   },
   'targets': [
diff --git a/cc/debug/benchmark_instrumentation.h b/cc/debug/benchmark_instrumentation.h
index 944ac66..99cfa21 100644
--- a/cc/debug/benchmark_instrumentation.h
+++ b/cc/debug/benchmark_instrumentation.h
@@ -20,6 +20,8 @@
 const char kBeginFrameId[] = "begin_frame_id";
 }  // namespace internal
 
+// TODO(khushalsagar): Fix these names for the telemetry benchmarks.
+// See crbug/567993.
 const char kSendBeginFrame[] = "ThreadProxy::ScheduledActionSendBeginMainFrame";
 const char kDoBeginFrame[] = "ThreadProxy::BeginMainFrame";
 
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index 8999b2f..44d16c1 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -1228,7 +1228,7 @@
       SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
 }
 
-// See ThreadProxy::BeginMainFrame "EarlyOut_NotVisible" /
+// See ProxyMain::BeginMainFrame "EarlyOut_NotVisible" /
 // "EarlyOut_OutputSurfaceLost" cases.
 TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
   SchedulerSettings default_scheduler_settings;
@@ -1282,7 +1282,7 @@
   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
 }
 
-// See ThreadProxy::BeginMainFrame "EarlyOut_NoUpdates" case.
+// See ProxyMain::BeginMainFrame "EarlyOut_NoUpdates" case.
 TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
   SchedulerSettings default_scheduler_settings;
   StateMachine state(default_scheduler_settings);
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index a99e2f2..d68ec67 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -30,8 +30,10 @@
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_host_single_thread_client.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/proxy_impl.h"
+#include "cc/trees/proxy_main.h"
 #include "cc/trees/single_thread_proxy.h"
-#include "cc/trees/thread_proxy.h"
+#include "cc/trees/threaded_channel.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/gfx/geometry/size_conversions.h"
 
@@ -93,254 +95,8 @@
                                 layer_settings);
 }
 
-TestHooks::TestHooks() {}
-
-TestHooks::~TestHooks() {}
-
-DrawResult TestHooks::PrepareToDrawOnThread(
-    LayerTreeHostImpl* host_impl,
-    LayerTreeHostImpl::FrameData* frame_data,
-    DrawResult draw_result) {
-  return draw_result;
-}
-
-void TestHooks::CreateResourceAndTileTaskWorkerPool(
-    LayerTreeHostImpl* host_impl,
-    scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
-    scoped_ptr<ResourcePool>* resource_pool) {
-  host_impl->LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
-      tile_task_worker_pool, resource_pool);
-}
-
-// Adapts ThreadProxy for test. Injects test hooks for testing.
-class ThreadProxyForTest : public ThreadProxy {
- public:
-  static scoped_ptr<Proxy> Create(
-      TestHooks* test_hooks,
-      LayerTreeHost* host,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source) {
-    return make_scoped_ptr(
-        new ThreadProxyForTest(test_hooks, host, task_runner_provider,
-                               std::move(external_begin_frame_source)));
-  }
-
-  ~ThreadProxyForTest() override {}
-
- private:
-  TestHooks* test_hooks_;
-
-  void SetNeedsUpdateLayers() override {
-    ThreadProxy::SetNeedsUpdateLayers();
-    test_hooks_->DidSetNeedsUpdateLayers();
-  }
-
-  void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override {
-    test_hooks_->ScheduledActionWillSendBeginMainFrame();
-    ThreadProxy::ScheduledActionSendBeginMainFrame(args);
-    test_hooks_->ScheduledActionSendBeginMainFrame();
-  }
-
-  DrawResult ScheduledActionDrawAndSwapIfPossible() override {
-    DrawResult result = ThreadProxy::ScheduledActionDrawAndSwapIfPossible();
-    test_hooks_->ScheduledActionDrawAndSwapIfPossible();
-    return result;
-  }
-
-  void ScheduledActionCommit() override {
-    ThreadProxy::ScheduledActionCommit();
-    test_hooks_->ScheduledActionCommit();
-  }
-
-  void ScheduledActionBeginOutputSurfaceCreation() override {
-    ThreadProxy::ScheduledActionBeginOutputSurfaceCreation();
-    test_hooks_->ScheduledActionBeginOutputSurfaceCreation();
-  }
-
-  void ScheduledActionPrepareTiles() override {
-    ThreadProxy::ScheduledActionPrepareTiles();
-    test_hooks_->ScheduledActionPrepareTiles();
-  }
-
-  void ScheduledActionInvalidateOutputSurface() override {
-    ThreadProxy::ScheduledActionInvalidateOutputSurface();
-    test_hooks_->ScheduledActionInvalidateOutputSurface();
-  }
-
-  void SendBeginMainFrameNotExpectedSoon() override {
-    ThreadProxy::SendBeginMainFrameNotExpectedSoon();
-    test_hooks_->SendBeginMainFrameNotExpectedSoon();
-  }
-
-  void DidActivateSyncTree() override {
-    ThreadProxy::DidActivateSyncTree();
-    test_hooks_->DidActivateSyncTree();
-  }
-
-  void SetThrottleFrameProductionOnImpl(bool throttle) override {
-    test_hooks_->SetThrottleFrameProductionOnImpl(throttle);
-    ThreadProxy::SetThrottleFrameProductionOnImpl(throttle);
-  }
-
-  void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) override {
-    test_hooks_->InitializeOutputSurfaceOnImpl(output_surface);
-    ThreadProxy::InitializeOutputSurfaceOnImpl(output_surface);
-  }
-
-  void MainThreadHasStoppedFlingingOnImpl() override {
-    test_hooks_->MainThreadHasStoppedFlingingOnImpl();
-    ThreadProxy::MainThreadHasStoppedFlingingOnImpl();
-  }
-
-  void SetInputThrottledUntilCommitOnImpl(bool is_throttled) override {
-    test_hooks_->SetInputThrottledUntilCommitOnImpl(is_throttled);
-    ThreadProxy::SetInputThrottledUntilCommitOnImpl(is_throttled);
-  }
-
-  void UpdateTopControlsStateOnImpl(TopControlsState constraints,
-                                    TopControlsState current,
-                                    bool animate) override {
-    test_hooks_->UpdateTopControlsStateOnImpl(constraints, current, animate);
-    ThreadProxy::UpdateTopControlsStateOnImpl(constraints, current, animate);
-  }
-
-  void SetDeferCommitsOnImpl(bool defer_commits) const override {
-    test_hooks_->SetDeferCommitsOnImpl(defer_commits);
-    ThreadProxy::SetDeferCommitsOnImpl(defer_commits);
-  }
-
-  void BeginMainFrameAbortedOnImpl(
-      CommitEarlyOutReason reason,
-      base::TimeTicks main_thread_start_time) override {
-    test_hooks_->BeginMainFrameAbortedOnImpl(reason);
-    ThreadProxy::BeginMainFrameAbortedOnImpl(reason, main_thread_start_time);
-  }
-
-  void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override {
-    test_hooks_->SetNeedsRedrawOnImpl(damage_rect);
-    ThreadProxy::SetNeedsRedrawOnImpl(damage_rect);
-  };
-
-  void SetNeedsCommitOnImpl() override {
-    test_hooks_->SetNeedsCommitOnImpl();
-    ThreadProxy::SetNeedsCommitOnImpl();
-  }
-
-  void FinishAllRenderingOnImpl(CompletionEvent* completion) override {
-    test_hooks_->FinishAllRenderingOnImpl();
-    ThreadProxy::FinishAllRenderingOnImpl(completion);
-  };
-
-  void SetVisibleOnImpl(bool visible) override {
-    test_hooks_->SetVisibleOnImpl(visible);
-    ThreadProxy::SetVisibleOnImpl(visible);
-  }
-
-  void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override {
-    test_hooks_->ReleaseOutputSurfaceOnImpl();
-    ThreadProxy::ReleaseOutputSurfaceOnImpl(completion);
-  }
-
-  void FinishGLOnImpl(CompletionEvent* completion) override {
-    test_hooks_->FinishGLOnImpl();
-    ThreadProxy::FinishGLOnImpl(completion);
-  }
-
-  void StartCommitOnImpl(CompletionEvent* completion,
-                         LayerTreeHost* layer_tree_host,
-                         base::TimeTicks main_thread_start_time,
-                         bool hold_commit_for_activation) override {
-    test_hooks_->StartCommitOnImpl();
-    ThreadProxy::StartCommitOnImpl(completion, layer_tree_host,
-                                   main_thread_start_time,
-                                   hold_commit_for_activation);
-  }
-
-  void InitializeImplOnImpl(CompletionEvent* completion,
-                            LayerTreeHost* layer_tree_host) override {
-    ThreadProxy::InitializeImplOnImpl(completion, layer_tree_host);
-    test_hooks_->InitializeImplOnImpl();
-  }
-
-  void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override {
-    test_hooks_->WillCloseLayerTreeHostOnImpl();
-    ThreadProxy::LayerTreeHostClosedOnImpl(completion);
-  }
-
-  void DidCompleteSwapBuffers() override {
-    test_hooks_->ReceivedDidCompleteSwapBuffers();
-    ThreadProxy::DidCompleteSwapBuffers();
-  }
-
-  void SetRendererCapabilitiesMainCopy(
-      const RendererCapabilities& capabilities) override {
-    test_hooks_->ReceivedSetRendererCapabilitiesMainCopy(capabilities);
-    ThreadProxy::SetRendererCapabilitiesMainCopy(capabilities);
-  }
-
-  void BeginMainFrameNotExpectedSoon() override {
-    test_hooks_->ReceivedBeginMainFrameNotExpectedSoon();
-    ThreadProxy::BeginMainFrameNotExpectedSoon();
-  }
-
-  void DidCommitAndDrawFrame() override {
-    test_hooks_->ReceivedDidCommitAndDrawFrame();
-    ThreadProxy::DidCommitAndDrawFrame();
-  }
-
-  void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) override {
-    test_hooks_->ReceivedSetAnimationEvents();
-    ThreadProxy::SetAnimationEvents(std::move(events));
-  }
-
-  void DidLoseOutputSurface() override {
-    test_hooks_->ReceivedDidLoseOutputSurface();
-    ThreadProxy::DidLoseOutputSurface();
-  }
-
-  void RequestNewOutputSurface() override {
-    test_hooks_->ReceivedRequestNewOutputSurface();
-    ThreadProxy::RequestNewOutputSurface();
-  }
-
-  void DidInitializeOutputSurface(
-      bool success,
-      const RendererCapabilities& capabilities) override {
-    test_hooks_->ReceivedDidInitializeOutputSurface(success, capabilities);
-    ThreadProxy::DidInitializeOutputSurface(success, capabilities);
-  }
-
-  void DidCompletePageScaleAnimation() override {
-    test_hooks_->ReceivedDidCompletePageScaleAnimation();
-    ThreadProxy::DidCompletePageScaleAnimation();
-  }
-
-  void PostFrameTimingEventsOnMain(
-      scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
-      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
-      override {
-    test_hooks_->ReceivedPostFrameTimingEventsOnMain();
-    ThreadProxy::PostFrameTimingEventsOnMain(std::move(composite_events),
-                                             std::move(main_frame_events));
-  }
-
-  void BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>
-                          begin_main_frame_state) override {
-    test_hooks_->ReceivedBeginMainFrame();
-    ThreadProxy::BeginMainFrame(std::move(begin_main_frame_state));
-  };
-
-  ThreadProxyForTest(TestHooks* test_hooks,
-                     LayerTreeHost* host,
-                     TaskRunnerProvider* task_runner_provider,
-                     scoped_ptr<BeginFrameSource> external_begin_frame_source)
-      : ThreadProxy(host,
-                    task_runner_provider,
-                    std::move(external_begin_frame_source)),
-        test_hooks_(test_hooks) {}
-};
-
-// Adapts SingleThreadProxy for test. Injects test hooks for testing.
+// Creates a SingleThreadProxy that notifies the supplied |test_hooks| of
+// various actions.
 class SingleThreadProxyForTest : public SingleThreadProxy {
  public:
   static scoped_ptr<Proxy> Create(
@@ -357,7 +113,17 @@
   ~SingleThreadProxyForTest() override {}
 
  private:
-  TestHooks* test_hooks_;
+  SingleThreadProxyForTest(
+      TestHooks* test_hooks,
+      LayerTreeHost* host,
+      LayerTreeHostSingleThreadClient* client,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source)
+      : SingleThreadProxy(host,
+                          client,
+                          task_runner_provider,
+                          std::move(external_begin_frame_source)),
+        test_hooks_(test_hooks) {}
 
   void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override {
     test_hooks_->ScheduledActionWillSendBeginMainFrame();
@@ -397,17 +163,7 @@
     test_hooks_->SendBeginMainFrameNotExpectedSoon();
   }
 
-  SingleThreadProxyForTest(
-      TestHooks* test_hooks,
-      LayerTreeHost* host,
-      LayerTreeHostSingleThreadClient* client,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source)
-      : SingleThreadProxy(host,
-                          client,
-                          task_runner_provider,
-                          std::move(external_begin_frame_source)),
-        test_hooks_(test_hooks) {}
+  TestHooks* test_hooks_;
 };
 
 // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks.
@@ -700,9 +456,10 @@
     scoped_ptr<Proxy> proxy;
     if (mode == CompositorMode::Threaded) {
       DCHECK(impl_task_runner.get());
-      proxy = ThreadProxyForTest::Create(
+      scoped_ptr<ProxyMain> proxy_main = ProxyMainForTest::CreateThreaded(
           test_hooks, layer_tree_host.get(), task_runner_provider.get(),
           std::move(external_begin_frame_source));
+      proxy = std::move(proxy_main);
     } else {
       proxy = SingleThreadProxyForTest::Create(
           test_hooks, layer_tree_host.get(), client, task_runner_provider.get(),
@@ -1161,4 +918,21 @@
   return layer_tree_host_.get();
 }
 
+ProxyMainForTest* LayerTreeTest::GetProxyMainForTest() const {
+  DCHECK(HasImplThread());
+  return static_cast<ProxyMainForTest*>(proxy());
+}
+
+ProxyImplForTest* LayerTreeTest::GetProxyImplForTest() const {
+  DCHECK(HasImplThread());
+  ThreadedChannel* threaded_channel =
+      static_cast<ThreadedChannel*>(GetProxyMainForTest()->channel_main());
+  ProxyImpl* proxy_impl = threaded_channel->GetProxyImplForTesting();
+
+  // We check for null ProxyImpl since ProxyImpl exists in the ThreadedChannel
+  // only after it is initialized.
+  DCHECK(proxy_impl);
+  return static_cast<ProxyImplForTest*>(proxy_impl);
+}
+
 }  // namespace cc
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index d727ae6..ea509d5 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -9,6 +9,9 @@
 #include "base/threading/thread.h"
 #include "cc/animation/animation_delegate.h"
 #include "cc/layers/layer_settings.h"
+#include "cc/test/proxy_impl_for_test.h"
+#include "cc/test/proxy_main_for_test.h"
+#include "cc/test/test_hooks.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_host_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -46,130 +49,6 @@
                                  LayerTreeHost* host,
                                  const LayerSettings& layer_settings);
 
-// Used by test stubs to notify the test when something interesting happens.
-class TestHooks : public AnimationDelegate {
- public:
-  TestHooks();
-  ~TestHooks() override;
-
-  void ReadSettings(const LayerTreeSettings& settings);
-
-  virtual void CreateResourceAndTileTaskWorkerPool(
-      LayerTreeHostImpl* host_impl,
-      scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
-      scoped_ptr<ResourcePool>* resource_pool);
-  virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
-                                          const BeginFrameArgs& args) {}
-  virtual void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
-                                             CommitEarlyOutReason reason) {}
-  virtual void WillPrepareTiles(LayerTreeHostImpl* host_impl) {}
-  virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
-                                           bool success) {}
-  virtual DrawResult PrepareToDrawOnThread(
-      LayerTreeHostImpl* host_impl,
-      LayerTreeHostImpl::FrameData* frame_data,
-      DrawResult draw_result);
-  virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) {}
-  virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void NotifyReadyToActivateOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) {}
-  virtual void NotifyAllTileTasksCompleted(LayerTreeHostImpl* host_impl) {}
-  virtual void NotifyTileStateChangedOnThread(LayerTreeHostImpl* host_impl,
-                                              const Tile* tile) {}
-  virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
-                             base::TimeTicks monotonic_time) {}
-  virtual void UpdateAnimationState(LayerTreeHostImpl* host_impl,
-                                    bool has_unfinished_animation) {}
-  virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
-                                 base::TimeTicks monotonic_time) {}
-  virtual void ApplyViewportDeltas(
-      const gfx::Vector2dF& inner_delta,
-      const gfx::Vector2dF& outer_delta,
-      const gfx::Vector2dF& elastic_overscroll_delta,
-      float scale,
-      float top_controls_delta) {}
-  virtual void BeginMainFrame(const BeginFrameArgs& args) {}
-  virtual void WillBeginMainFrame() {}
-  virtual void DidBeginMainFrame() {}
-  virtual void UpdateLayerTreeHost() {}
-  virtual void DidInitializeOutputSurface() {}
-  virtual void DidFailToInitializeOutputSurface() {}
-  virtual void DidAddAnimation() {}
-  virtual void WillCommit() {}
-  virtual void DidCommit() {}
-  virtual void DidCommitAndDrawFrame() {}
-  virtual void DidCompleteSwapBuffers() {}
-  virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
-                                       bool visible) {}
-  virtual void ScheduleComposite() {}
-  virtual void DidSetNeedsUpdateLayers() {}
-  virtual void DidActivateSyncTree() {}
-
-  // Hooks for SchedulerClient.
-  virtual void ScheduledActionWillSendBeginMainFrame() {}
-  virtual void ScheduledActionSendBeginMainFrame() {}
-  virtual void ScheduledActionDrawAndSwapIfPossible() {}
-  virtual void ScheduledActionCommit() {}
-  virtual void ScheduledActionBeginOutputSurfaceCreation() {}
-  virtual void ScheduledActionPrepareTiles() {}
-  virtual void ScheduledActionInvalidateOutputSurface() {}
-  virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
-  virtual void SendBeginMainFrameNotExpectedSoon() {}
-
-  // Hooks for ProxyImpl
-  virtual void SetThrottleFrameProductionOnImpl(bool throttle) {}
-  virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
-                                            TopControlsState current,
-                                            bool animate) {}
-  virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {}
-  virtual void MainThreadHasStoppedFlingingOnImpl() {}
-  virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled) {}
-  virtual void SetDeferCommitsOnImpl(bool defer_commits) {}
-  virtual void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason) {}
-  virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {}
-  virtual void SetNeedsCommitOnImpl() {}
-  virtual void FinishAllRenderingOnImpl() {}
-  virtual void SetVisibleOnImpl(bool visible) {}
-  virtual void ReleaseOutputSurfaceOnImpl() {}
-  virtual void FinishGLOnImpl() {}
-  virtual void StartCommitOnImpl() {}
-  virtual void InitializeImplOnImpl() {}
-  virtual void WillCloseLayerTreeHostOnImpl() {}
-
-  // Hooks for ProxyMain
-  virtual void ReceivedDidCompleteSwapBuffers() {}
-  virtual void ReceivedSetRendererCapabilitiesMainCopy(
-      const RendererCapabilities& capabilities) {}
-  virtual void ReceivedBeginMainFrameNotExpectedSoon() {}
-  virtual void ReceivedDidCommitAndDrawFrame() {}
-  virtual void ReceivedSetAnimationEvents() {}
-  virtual void ReceivedDidLoseOutputSurface() {}
-  virtual void ReceivedRequestNewOutputSurface() {}
-  virtual void ReceivedDidInitializeOutputSurface(
-      bool success,
-      const RendererCapabilities& capabilities) {}
-  virtual void ReceivedDidCompletePageScaleAnimation() {}
-  virtual void ReceivedPostFrameTimingEventsOnMain() {}
-  virtual void ReceivedBeginMainFrame() {}
-
-  // Implementation of AnimationDelegate:
-  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
-                              Animation::TargetProperty target_property,
-                              int group) override {}
-  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
-                               Animation::TargetProperty target_property,
-                               int group) override {}
-
-  virtual void RequestNewOutputSurface() = 0;
-};
-
 class BeginTask;
 class LayerTreeHostClientForTesting;
 class TimeoutTask;
@@ -250,9 +129,10 @@
   virtual void BeginTest() = 0;
   virtual void SetupTree();
 
+  // TODO(khushalsagar): Add mode for running remote channel tests.
   virtual void RunTest(CompositorMode mode, bool delegating_renderer);
 
-  bool HasImplThread() { return !!impl_thread_; }
+  bool HasImplThread() const { return !!impl_thread_; }
   base::SingleThreadTaskRunner* ImplThreadTaskRunner() {
     DCHECK(task_runner_provider());
     base::SingleThreadTaskRunner* impl_thread_task_runner =
@@ -278,6 +158,12 @@
   FakeOutputSurface* output_surface() { return output_surface_; }
   int LastCommittedSourceFrameNumber(LayerTreeHostImpl* impl) const;
 
+  // Use these only for ProxyMain tests in threaded mode.
+  // TODO(khushalsagar): Update these when adding support for remote channel
+  // tests.
+  ProxyMainForTest* GetProxyMainForTest() const;
+  ProxyImplForTest* GetProxyImplForTest() const;
+
   void DestroyLayerTreeHost();
 
   // By default, output surface recreation is synchronous.
diff --git a/cc/test/proxy_impl_for_test.cc b/cc/test/proxy_impl_for_test.cc
new file mode 100644
index 0000000..3cd542b
--- /dev/null
+++ b/cc/test/proxy_impl_for_test.cc
@@ -0,0 +1,163 @@
+// Copyright 2015 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/proxy_impl_for_test.h"
+
+namespace cc {
+scoped_ptr<ProxyImpl> ProxyImplForTest::Create(
+    TestHooks* test_hooks,
+    ChannelImpl* channel_impl,
+    LayerTreeHost* layer_tree_host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  return make_scoped_ptr(new ProxyImplForTest(
+      test_hooks, channel_impl, layer_tree_host, task_runner_provider,
+      std::move(external_begin_frame_source)));
+}
+
+bool ProxyImplForTest::HasCommitCompletionEvent() const {
+  return commit_completion_event_ != nullptr;
+}
+
+bool ProxyImplForTest::GetNextCommitWaitsForActivation() const {
+  return next_commit_waits_for_activation_;
+}
+
+ProxyImplForTest::ProxyImplForTest(
+    TestHooks* test_hooks,
+    ChannelImpl* channel_impl,
+    LayerTreeHost* layer_tree_host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source)
+    : ProxyImpl(channel_impl,
+                layer_tree_host,
+                task_runner_provider,
+                std::move(external_begin_frame_source)),
+      test_hooks_(test_hooks) {}
+
+void ProxyImplForTest::ScheduledActionSendBeginMainFrame(
+    const BeginFrameArgs& args) {
+  test_hooks_->ScheduledActionWillSendBeginMainFrame();
+  ProxyImpl::ScheduledActionSendBeginMainFrame(args);
+  test_hooks_->ScheduledActionSendBeginMainFrame();
+}
+
+DrawResult ProxyImplForTest::ScheduledActionDrawAndSwapIfPossible() {
+  DrawResult result = ProxyImpl::ScheduledActionDrawAndSwapIfPossible();
+  test_hooks_->ScheduledActionDrawAndSwapIfPossible();
+  return result;
+}
+
+void ProxyImplForTest::ScheduledActionCommit() {
+  ProxyImpl::ScheduledActionCommit();
+  test_hooks_->ScheduledActionCommit();
+}
+
+void ProxyImplForTest::ScheduledActionBeginOutputSurfaceCreation() {
+  ProxyImpl::ScheduledActionBeginOutputSurfaceCreation();
+  test_hooks_->ScheduledActionBeginOutputSurfaceCreation();
+}
+
+void ProxyImplForTest::ScheduledActionPrepareTiles() {
+  ProxyImpl::ScheduledActionPrepareTiles();
+  test_hooks_->ScheduledActionPrepareTiles();
+}
+
+void ProxyImplForTest::ScheduledActionInvalidateOutputSurface() {
+  ProxyImpl::ScheduledActionInvalidateOutputSurface();
+  test_hooks_->ScheduledActionInvalidateOutputSurface();
+}
+
+void ProxyImplForTest::SendBeginMainFrameNotExpectedSoon() {
+  ProxyImpl::SendBeginMainFrameNotExpectedSoon();
+  test_hooks_->SendBeginMainFrameNotExpectedSoon();
+}
+
+void ProxyImplForTest::DidActivateSyncTree() {
+  ProxyImpl::DidActivateSyncTree();
+  test_hooks_->DidActivateSyncTree();
+}
+
+void ProxyImplForTest::SetThrottleFrameProductionOnImpl(bool throttle) {
+  test_hooks_->SetThrottleFrameProductionOnImpl(throttle);
+  ProxyImpl::SetThrottleFrameProductionOnImpl(throttle);
+}
+
+void ProxyImplForTest::InitializeOutputSurfaceOnImpl(
+    OutputSurface* output_surface) {
+  test_hooks_->InitializeOutputSurfaceOnImpl(output_surface);
+  ProxyImpl::InitializeOutputSurfaceOnImpl(output_surface);
+}
+
+void ProxyImplForTest::MainThreadHasStoppedFlingingOnImpl() {
+  test_hooks_->MainThreadHasStoppedFlingingOnImpl();
+  ProxyImpl::MainThreadHasStoppedFlingingOnImpl();
+}
+
+void ProxyImplForTest::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
+  test_hooks_->SetInputThrottledUntilCommitOnImpl(is_throttled);
+  ProxyImpl::SetInputThrottledUntilCommitOnImpl(is_throttled);
+}
+
+void ProxyImplForTest::UpdateTopControlsStateOnImpl(
+    TopControlsState constraints,
+    TopControlsState current,
+    bool animate) {
+  test_hooks_->UpdateTopControlsStateOnImpl(constraints, current, animate);
+  ProxyImpl::UpdateTopControlsStateOnImpl(constraints, current, animate);
+}
+
+void ProxyImplForTest::SetDeferCommitsOnImpl(bool defer_commits) const {
+  test_hooks_->SetDeferCommitsOnImpl(defer_commits);
+  ProxyImpl::SetDeferCommitsOnImpl(defer_commits);
+}
+
+void ProxyImplForTest::BeginMainFrameAbortedOnImpl(
+    CommitEarlyOutReason reason,
+    base::TimeTicks main_thread_start_time) {
+  test_hooks_->BeginMainFrameAbortedOnImpl(reason);
+  ProxyImpl::BeginMainFrameAbortedOnImpl(reason, main_thread_start_time);
+}
+
+void ProxyImplForTest::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
+  test_hooks_->SetNeedsRedrawOnImpl(damage_rect);
+  ProxyImpl::SetNeedsRedrawOnImpl(damage_rect);
+}
+
+void ProxyImplForTest::SetNeedsCommitOnImpl() {
+  test_hooks_->SetNeedsCommitOnImpl();
+  ProxyImpl::SetNeedsCommitOnImpl();
+}
+
+void ProxyImplForTest::FinishAllRenderingOnImpl(CompletionEvent* completion) {
+  test_hooks_->FinishAllRenderingOnImpl();
+  ProxyImpl::FinishAllRenderingOnImpl(completion);
+}
+
+void ProxyImplForTest::SetVisibleOnImpl(bool visible) {
+  test_hooks_->SetVisibleOnImpl(visible);
+  ProxyImpl::SetVisibleOnImpl(visible);
+}
+
+void ProxyImplForTest::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
+  test_hooks_->ReleaseOutputSurfaceOnImpl();
+  ProxyImpl::ReleaseOutputSurfaceOnImpl(completion);
+}
+
+void ProxyImplForTest::FinishGLOnImpl(CompletionEvent* completion) {
+  test_hooks_->FinishGLOnImpl();
+  ProxyImpl::FinishGLOnImpl(completion);
+}
+
+void ProxyImplForTest::StartCommitOnImpl(CompletionEvent* completion,
+                                         LayerTreeHost* layer_tree_host,
+                                         base::TimeTicks main_thread_start_time,
+                                         bool hold_commit_for_activation) {
+  test_hooks_->StartCommitOnImpl();
+  ProxyImpl::StartCommitOnImpl(completion, layer_tree_host,
+                               main_thread_start_time,
+                               hold_commit_for_activation);
+}
+
+}  // namespace cc
diff --git a/cc/test/proxy_impl_for_test.h b/cc/test/proxy_impl_for_test.h
new file mode 100644
index 0000000..b81ece5
--- /dev/null
+++ b/cc/test/proxy_impl_for_test.h
@@ -0,0 +1,73 @@
+// Copyright 2015 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_PROXY_IMPL_FOR_TEST_H_
+#define CC_TEST_PROXY_IMPL_FOR_TEST_H_
+
+#include "base/macros.h"
+#include "cc/test/test_hooks.h"
+#include "cc/trees/proxy_impl.h"
+
+namespace cc {
+// Creates a ProxyImpl that notifies the supplied |test_hooks| of various
+// actions.
+class ProxyImplForTest : public ProxyImpl {
+ public:
+  static scoped_ptr<ProxyImpl> Create(
+      TestHooks* test_hooks,
+      ChannelImpl* channel_impl,
+      LayerTreeHost* layer_tree_host,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+  using ProxyImpl::PostAnimationEventsToMainThreadOnImplThread;
+  using ProxyImpl::DidLoseOutputSurfaceOnImplThread;
+  using ProxyImpl::DidCompletePageScaleAnimationOnImplThread;
+  using ProxyImpl::SendBeginMainFrameNotExpectedSoon;
+
+  bool HasCommitCompletionEvent() const;
+  bool GetNextCommitWaitsForActivation() const;
+
+  ProxyImplForTest(TestHooks* test_hooks,
+                   ChannelImpl* channel_impl,
+                   LayerTreeHost* layer_tree_host,
+                   TaskRunnerProvider* task_runner_provider,
+                   scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+  void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override;
+  DrawResult ScheduledActionDrawAndSwapIfPossible() override;
+  void ScheduledActionCommit() override;
+  void ScheduledActionBeginOutputSurfaceCreation() override;
+  void ScheduledActionPrepareTiles() override;
+  void ScheduledActionInvalidateOutputSurface() override;
+  void SendBeginMainFrameNotExpectedSoon() override;
+  void DidActivateSyncTree() override;
+  void SetThrottleFrameProductionOnImpl(bool throttle) override;
+  void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) override;
+  void MainThreadHasStoppedFlingingOnImpl() override;
+  void SetInputThrottledUntilCommitOnImpl(bool is_throttled) override;
+  void UpdateTopControlsStateOnImpl(TopControlsState constraints,
+                                    TopControlsState current,
+                                    bool animate) override;
+  void SetDeferCommitsOnImpl(bool defer_commits) const override;
+  void BeginMainFrameAbortedOnImpl(
+      CommitEarlyOutReason reason,
+      base::TimeTicks main_thread_start_time) override;
+  void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override;
+  void SetNeedsCommitOnImpl() override;
+  void FinishAllRenderingOnImpl(CompletionEvent* completion) override;
+  void SetVisibleOnImpl(bool visible) override;
+  void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override;
+  void FinishGLOnImpl(CompletionEvent* completion) override;
+  void StartCommitOnImpl(CompletionEvent* completion,
+                         LayerTreeHost* layer_tree_host,
+                         base::TimeTicks main_thread_start_time,
+                         bool hold_commit_for_activation) override;
+
+  TestHooks* test_hooks_;
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_PROXY_IMPL_FOR_TEST_H_
diff --git a/cc/test/proxy_main_for_test.cc b/cc/test/proxy_main_for_test.cc
new file mode 100644
index 0000000..4588422e
--- /dev/null
+++ b/cc/test/proxy_main_for_test.cc
@@ -0,0 +1,104 @@
+// Copyright 2015 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/proxy_main_for_test.h"
+
+#include "cc/test/threaded_channel_for_test.h"
+
+namespace cc {
+
+scoped_ptr<ProxyMain> ProxyMainForTest::CreateThreaded(
+    TestHooks* test_hooks,
+    LayerTreeHost* host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  scoped_ptr<ProxyMain> proxy_main(
+      new ProxyMainForTest(test_hooks, host, task_runner_provider,
+                           std::move(external_begin_frame_source)));
+  proxy_main->SetChannel(ThreadedChannelForTest::Create(
+      test_hooks, proxy_main.get(), task_runner_provider));
+  return proxy_main;
+}
+
+ProxyMainForTest::~ProxyMainForTest() {}
+
+ProxyMainForTest::ProxyMainForTest(
+    TestHooks* test_hooks,
+    LayerTreeHost* host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source)
+    : ProxyMain(host,
+                task_runner_provider,
+                std::move(external_begin_frame_source)),
+      test_hooks_(test_hooks) {}
+
+void ProxyMainForTest::SetNeedsUpdateLayers() {
+  ProxyMain::SetNeedsUpdateLayers();
+  test_hooks_->DidSetNeedsUpdateLayers();
+}
+
+void ProxyMainForTest::DidCompleteSwapBuffers() {
+  test_hooks_->ReceivedDidCompleteSwapBuffers();
+  ProxyMain::DidCompleteSwapBuffers();
+}
+
+void ProxyMainForTest::SetRendererCapabilities(
+    const RendererCapabilities& capabilities) {
+  test_hooks_->ReceivedSetRendererCapabilitiesMainCopy(capabilities);
+  ProxyMain::SetRendererCapabilities(capabilities);
+}
+
+void ProxyMainForTest::BeginMainFrameNotExpectedSoon() {
+  test_hooks_->ReceivedBeginMainFrameNotExpectedSoon();
+  ProxyMain::BeginMainFrameNotExpectedSoon();
+}
+
+void ProxyMainForTest::DidCommitAndDrawFrame() {
+  test_hooks_->ReceivedDidCommitAndDrawFrame();
+  ProxyMain::DidCommitAndDrawFrame();
+}
+
+void ProxyMainForTest::SetAnimationEvents(
+    scoped_ptr<AnimationEventsVector> events) {
+  test_hooks_->ReceivedSetAnimationEvents();
+  ProxyMain::SetAnimationEvents(std::move(events));
+}
+
+void ProxyMainForTest::DidLoseOutputSurface() {
+  test_hooks_->ReceivedDidLoseOutputSurface();
+  ProxyMain::DidLoseOutputSurface();
+}
+
+void ProxyMainForTest::RequestNewOutputSurface() {
+  test_hooks_->ReceivedRequestNewOutputSurface();
+  ProxyMain::RequestNewOutputSurface();
+}
+
+void ProxyMainForTest::DidInitializeOutputSurface(
+    bool success,
+    const RendererCapabilities& capabilities) {
+  test_hooks_->ReceivedDidInitializeOutputSurface(success, capabilities);
+  ProxyMain::DidInitializeOutputSurface(success, capabilities);
+}
+
+void ProxyMainForTest::DidCompletePageScaleAnimation() {
+  test_hooks_->ReceivedDidCompletePageScaleAnimation();
+  ProxyMain::DidCompletePageScaleAnimation();
+}
+
+void ProxyMainForTest::PostFrameTimingEventsOnMain(
+    scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+    scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+  test_hooks_->ReceivedPostFrameTimingEventsOnMain();
+  ProxyMain::PostFrameTimingEventsOnMain(std::move(composite_events),
+                                         std::move(main_frame_events));
+}
+
+void ProxyMainForTest::BeginMainFrame(
+    scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+  test_hooks_->ReceivedBeginMainFrame();
+  ProxyMain::BeginMainFrame(std::move(begin_main_frame_state));
+}
+
+}  // namespace cc
diff --git a/cc/test/proxy_main_for_test.h b/cc/test/proxy_main_for_test.h
new file mode 100644
index 0000000..1669cc5a
--- /dev/null
+++ b/cc/test/proxy_main_for_test.h
@@ -0,0 +1,56 @@
+// Copyright 2015 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_PROXY_MAIN_FOR_TEST_H_
+#define CC_TEST_PROXY_MAIN_FOR_TEST_H_
+
+#include "base/macros.h"
+#include "cc/test/test_hooks.h"
+#include "cc/trees/proxy_main.h"
+
+namespace cc {
+
+// Creates a ProxyMain that notifies the supplied |test_hooks| of various
+// actions.
+class ProxyMainForTest : public ProxyMain {
+ public:
+  static scoped_ptr<ProxyMain> CreateThreaded(
+      TestHooks* test_hooks,
+      LayerTreeHost* host,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+  ~ProxyMainForTest() override;
+
+  ProxyMainForTest(TestHooks* test_hooks,
+                   LayerTreeHost* host,
+                   TaskRunnerProvider* task_runner_provider,
+                   scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+  void SetNeedsUpdateLayers() override;
+  void DidCompleteSwapBuffers() override;
+  void SetRendererCapabilities(
+      const RendererCapabilities& capabilities) override;
+  void BeginMainFrameNotExpectedSoon() override;
+  void DidCommitAndDrawFrame() override;
+  void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) override;
+  void DidLoseOutputSurface() override;
+  void RequestNewOutputSurface() override;
+  void DidInitializeOutputSurface(
+      bool success,
+      const RendererCapabilities& capabilities) override;
+  void DidCompletePageScaleAnimation() override;
+  void PostFrameTimingEventsOnMain(
+      scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
+      override;
+  void BeginMainFrame(
+      scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) override;
+
+  TestHooks* test_hooks_;
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_PROXY_MAIN_FOR_TEST_H_
diff --git a/cc/test/test_hooks.cc b/cc/test/test_hooks.cc
new file mode 100644
index 0000000..5c913ac
--- /dev/null
+++ b/cc/test/test_hooks.cc
@@ -0,0 +1,28 @@
+// Copyright 2015 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/test_hooks.h"
+
+namespace cc {
+
+TestHooks::TestHooks() {}
+
+TestHooks::~TestHooks() {}
+
+DrawResult TestHooks::PrepareToDrawOnThread(
+    LayerTreeHostImpl* host_impl,
+    LayerTreeHostImpl::FrameData* frame_data,
+    DrawResult draw_result) {
+  return draw_result;
+}
+
+void TestHooks::CreateResourceAndTileTaskWorkerPool(
+    LayerTreeHostImpl* host_impl,
+    scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
+    scoped_ptr<ResourcePool>* resource_pool) {
+  host_impl->LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
+      tile_task_worker_pool, resource_pool);
+}
+
+}  // namespace cc
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h
new file mode 100644
index 0000000..fd45cbc
--- /dev/null
+++ b/cc/test/test_hooks.h
@@ -0,0 +1,139 @@
+// Copyright 2015 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_TEST_HOOKS_H_
+#define CC_TEST_TEST_HOOKS_H_
+
+#include "base/macros.h"
+#include "cc/animation/animation_delegate.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_impl.h"
+
+namespace cc {
+
+// Used by test stubs to notify the test when something interesting happens.
+class TestHooks : public AnimationDelegate {
+ public:
+  TestHooks();
+  ~TestHooks() override;
+
+  void ReadSettings(const LayerTreeSettings& settings);
+
+  virtual void CreateResourceAndTileTaskWorkerPool(
+      LayerTreeHostImpl* host_impl,
+      scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
+      scoped_ptr<ResourcePool>* resource_pool);
+  virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
+                                          const BeginFrameArgs& args) {}
+  virtual void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
+                                             CommitEarlyOutReason reason) {}
+  virtual void WillPrepareTiles(LayerTreeHostImpl* host_impl) {}
+  virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
+                                           bool success) {}
+  virtual DrawResult PrepareToDrawOnThread(
+      LayerTreeHostImpl* host_impl,
+      LayerTreeHostImpl::FrameData* frame_data,
+      DrawResult draw_result);
+  virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) {}
+  virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void NotifyReadyToActivateOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) {}
+  virtual void NotifyAllTileTasksCompleted(LayerTreeHostImpl* host_impl) {}
+  virtual void NotifyTileStateChangedOnThread(LayerTreeHostImpl* host_impl,
+                                              const Tile* tile) {}
+  virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
+                             base::TimeTicks monotonic_time) {}
+  virtual void UpdateAnimationState(LayerTreeHostImpl* host_impl,
+                                    bool has_unfinished_animation) {}
+  virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
+                                 base::TimeTicks monotonic_time) {}
+  virtual void ApplyViewportDeltas(
+      const gfx::Vector2dF& inner_delta,
+      const gfx::Vector2dF& outer_delta,
+      const gfx::Vector2dF& elastic_overscroll_delta,
+      float scale,
+      float top_controls_delta) {}
+  virtual void BeginMainFrame(const BeginFrameArgs& args) {}
+  virtual void WillBeginMainFrame() {}
+  virtual void DidBeginMainFrame() {}
+  virtual void UpdateLayerTreeHost() {}
+  virtual void DidInitializeOutputSurface() {}
+  virtual void DidFailToInitializeOutputSurface() {}
+  virtual void DidAddAnimation() {}
+  virtual void WillCommit() {}
+  virtual void DidCommit() {}
+  virtual void DidCommitAndDrawFrame() {}
+  virtual void DidCompleteSwapBuffers() {}
+  virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
+                                       bool visible) {}
+  virtual void ScheduleComposite() {}
+  virtual void DidSetNeedsUpdateLayers() {}
+  virtual void DidActivateSyncTree() {}
+
+  // Hooks for SchedulerClient.
+  virtual void ScheduledActionWillSendBeginMainFrame() {}
+  virtual void ScheduledActionSendBeginMainFrame() {}
+  virtual void ScheduledActionDrawAndSwapIfPossible() {}
+  virtual void ScheduledActionCommit() {}
+  virtual void ScheduledActionBeginOutputSurfaceCreation() {}
+  virtual void ScheduledActionPrepareTiles() {}
+  virtual void ScheduledActionInvalidateOutputSurface() {}
+  virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
+  virtual void SendBeginMainFrameNotExpectedSoon() {}
+
+  // Hooks for ProxyImpl
+  virtual void SetThrottleFrameProductionOnImpl(bool throttle) {}
+  virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
+                                            TopControlsState current,
+                                            bool animate) {}
+  virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {}
+  virtual void MainThreadHasStoppedFlingingOnImpl() {}
+  virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled) {}
+  virtual void SetDeferCommitsOnImpl(bool defer_commits) {}
+  virtual void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason) {}
+  virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {}
+  virtual void SetNeedsCommitOnImpl() {}
+  virtual void FinishAllRenderingOnImpl() {}
+  virtual void SetVisibleOnImpl(bool visible) {}
+  virtual void ReleaseOutputSurfaceOnImpl() {}
+  virtual void FinishGLOnImpl() {}
+  virtual void StartCommitOnImpl() {}
+
+  // Hooks for ProxyMain
+  virtual void ReceivedDidCompleteSwapBuffers() {}
+  virtual void ReceivedSetRendererCapabilitiesMainCopy(
+      const RendererCapabilities& capabilities) {}
+  virtual void ReceivedBeginMainFrameNotExpectedSoon() {}
+  virtual void ReceivedDidCommitAndDrawFrame() {}
+  virtual void ReceivedSetAnimationEvents() {}
+  virtual void ReceivedDidLoseOutputSurface() {}
+  virtual void ReceivedRequestNewOutputSurface() {}
+  virtual void ReceivedDidInitializeOutputSurface(
+      bool success,
+      const RendererCapabilities& capabilities) {}
+  virtual void ReceivedDidCompletePageScaleAnimation() {}
+  virtual void ReceivedPostFrameTimingEventsOnMain() {}
+  virtual void ReceivedBeginMainFrame() {}
+
+  // Implementation of AnimationDelegate:
+  void NotifyAnimationStarted(base::TimeTicks monotonic_time,
+                              Animation::TargetProperty target_property,
+                              int group) override {}
+  void NotifyAnimationFinished(base::TimeTicks monotonic_time,
+                               Animation::TargetProperty target_property,
+                               int group) override {}
+
+  virtual void RequestNewOutputSurface() = 0;
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_TEST_HOOKS_H_
diff --git a/cc/test/threaded_channel_for_test.cc b/cc/test/threaded_channel_for_test.cc
new file mode 100644
index 0000000..35489bd
--- /dev/null
+++ b/cc/test/threaded_channel_for_test.cc
@@ -0,0 +1,36 @@
+// Copyright 2011 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/threaded_channel_for_test.h"
+
+#include "cc/test/proxy_impl_for_test.h"
+
+namespace cc {
+
+scoped_ptr<ThreadedChannel> ThreadedChannelForTest::Create(
+    TestHooks* test_hooks,
+    ProxyMain* proxy_main,
+    TaskRunnerProvider* task_runner_provider) {
+  return make_scoped_ptr(
+      new ThreadedChannelForTest(test_hooks, proxy_main, task_runner_provider));
+}
+
+ThreadedChannelForTest::ThreadedChannelForTest(
+    TestHooks* test_hooks,
+    ProxyMain* proxy_main,
+    TaskRunnerProvider* task_runner_provider)
+    : ThreadedChannel(proxy_main, task_runner_provider),
+      test_hooks_(test_hooks) {}
+
+scoped_ptr<ProxyImpl> ThreadedChannelForTest::CreateProxyImpl(
+    ChannelImpl* channel_impl,
+    LayerTreeHost* layer_tree_host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  return ProxyImplForTest::Create(test_hooks_, channel_impl, layer_tree_host,
+                                  task_runner_provider,
+                                  std::move(external_begin_frame_source));
+}
+
+}  // namespace cc
diff --git a/cc/test/threaded_channel_for_test.h b/cc/test/threaded_channel_for_test.h
new file mode 100644
index 0000000..bd74790
--- /dev/null
+++ b/cc/test/threaded_channel_for_test.h
@@ -0,0 +1,38 @@
+// Copyright 2011 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_THREADED_CHANNEL_FOR_TEST_H_
+#define CC_TEST_THREADED_CHANNEL_FOR_TEST_H_
+
+#include "base/macros.h"
+#include "cc/test/test_hooks.h"
+#include "cc/trees/threaded_channel.h"
+
+namespace cc {
+
+// ThreadedChannel that notifies |test_hooks| of internal actions by ProxyImpl.
+class ThreadedChannelForTest : public ThreadedChannel {
+ public:
+  static scoped_ptr<ThreadedChannel> Create(
+      TestHooks* test_hooks,
+      ProxyMain* proxy_main,
+      TaskRunnerProvider* task_runner_provider);
+
+ private:
+  ThreadedChannelForTest(TestHooks* test_hooks,
+                         ProxyMain* proxy_main,
+                         TaskRunnerProvider* task_runner_provider);
+
+  scoped_ptr<ProxyImpl> CreateProxyImpl(
+      ChannelImpl* channel_impl,
+      LayerTreeHost* layer_tree_host,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source) override;
+
+  TestHooks* test_hooks_;
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_THREADED_CHANNEL_FOR_TEST_H_
diff --git a/cc/trees/channel_main.h b/cc/trees/channel_main.h
index 8f8c4ee..39861e0 100644
--- a/cc/trees/channel_main.h
+++ b/cc/trees/channel_main.h
@@ -9,10 +9,12 @@
 #include "cc/base/completion_event.h"
 #include "cc/input/top_controls_state.h"
 #include "cc/output/output_surface.h"
+#include "cc/scheduler/begin_frame_source.h"
 #include "cc/scheduler/commit_earlyout_reason.h"
 #include "cc/trees/proxy_common.h"
 
 namespace cc {
+
 // ChannelMain and ChannelImpl provide an abstract communication layer for
 // the main and impl side of the compositor.
 //
@@ -25,7 +27,9 @@
 
 class CC_EXPORT ChannelMain {
  public:
-  // Interface for commands sent to the ProxyImpl
+  virtual ~ChannelMain() {}
+
+  // Interface for commands sent to ProxyImpl
   virtual void SetThrottleFrameProductionOnImpl(bool throttle) = 0;
   virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
                                             TopControlsState current,
@@ -37,7 +41,6 @@
   virtual void FinishAllRenderingOnImpl(CompletionEvent* completion) = 0;
   virtual void SetVisibleOnImpl(bool visible) = 0;
   virtual void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) = 0;
-  virtual void FinishGLOnImpl(CompletionEvent* completion) = 0;
   virtual void MainFrameWillHappenOnImplForTesting(
       CompletionEvent* completion,
       bool* main_frame_will_happen) = 0;
@@ -50,11 +53,14 @@
                                  LayerTreeHost* layer_tree_host,
                                  base::TimeTicks main_thread_start_time,
                                  bool hold_commit_for_activation) = 0;
-  virtual void InitializeImplOnImpl(CompletionEvent* completion,
-                                    LayerTreeHost* layer_tree_host) = 0;
-  virtual void LayerTreeHostClosedOnImpl(CompletionEvent* completion) = 0;
 
-  virtual ~ChannelMain() {}
+  // Must be called before using the channel.
+  virtual void SynchronouslyInitializeImpl(
+      LayerTreeHost* layer_tree_host,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source) = 0;
+
+  // Must be called before deleting the channel.
+  virtual void SynchronouslyCloseImpl() = 0;
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index b5f0231..6eb60f6 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -42,8 +42,8 @@
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/proxy_main.h"
 #include "cc/trees/single_thread_proxy.h"
-#include "cc/trees/thread_proxy.h"
 #include "cc/trees/tree_synchronizer.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
@@ -143,8 +143,10 @@
     scoped_ptr<BeginFrameSource> external_begin_frame_source) {
   task_runner_provider_ =
       TaskRunnerProvider::Create(main_task_runner, impl_task_runner);
-  InitializeProxy(ThreadProxy::Create(this, task_runner_provider_.get(),
-                                      std::move(external_begin_frame_source)));
+  scoped_ptr<ProxyMain> proxy_main =
+      ProxyMain::CreateThreaded(this, task_runner_provider_.get(),
+                                std::move(external_begin_frame_source));
+  InitializeProxy(std::move(proxy_main));
 }
 
 void LayerTreeHost::InitializeSingleThreaded(
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index f97d3d2..fdcc26d 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -49,7 +49,6 @@
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/single_thread_proxy.h"
-#include "cc/trees/thread_proxy.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "skia/ext/refptr.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc
index 293c864..e00b085 100644
--- a/cc/trees/layer_tree_host_unittest_proxy.cc
+++ b/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -7,15 +7,16 @@
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_picture_layer.h"
 #include "cc/test/layer_tree_test.h"
-#include "cc/trees/thread_proxy.h"
+#include "cc/trees/proxy_impl.h"
+#include "cc/trees/proxy_main.h"
 
-#define THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME) \
+#define PROXY_MAIN_THREADED_TEST_F(TEST_FIXTURE_NAME) \
   TEST_F(TEST_FIXTURE_NAME, MultiThread) { Run(true); }
 
-// Do common tests for single thread proxy and thread proxy.
+// Do common tests for single thread proxy and proxy main in threaded mode.
 // TODO(simonhong): Add SINGLE_THREAD_PROXY_TEST_F
 #define PROXY_TEST_SCHEDULED_ACTION(TEST_FIXTURE_NAME) \
-  THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME);
+  PROXY_MAIN_THREADED_TEST_F(TEST_FIXTURE_NAME);
 
 namespace cc {
 
@@ -73,12 +74,12 @@
 
 PROXY_TEST_SCHEDULED_ACTION(ProxyTestScheduledActionsBasic);
 
-class ThreadProxyTest : public ProxyTest {
+class ProxyMainThreaded : public ProxyTest {
  protected:
-  ThreadProxyTest()
+  ProxyMainThreaded()
       : update_check_layer_(
             FakePictureLayer::Create(layer_settings(), &client_)) {}
-  ~ThreadProxyTest() override {}
+  ~ProxyMainThreaded() override {}
 
   void SetupTree() override {
     layer_tree_host()->SetRootLayer(update_check_layer_);
@@ -86,83 +87,69 @@
     client_.set_bounds(update_check_layer_->bounds());
   }
 
-  const ThreadProxy::MainThreadOnly& ThreadProxyMainOnly() const {
-    DCHECK(task_runner_provider());
-    DCHECK(task_runner_provider()->HasImplThread());
-    DCHECK(proxy());
-    return static_cast<const ThreadProxy*>(proxy())->main();
-  }
-
-  const ThreadProxy::CompositorThreadOnly& ThreadProxyImplOnly() const {
-    DCHECK(task_runner_provider());
-    DCHECK(task_runner_provider()->HasImplThread());
-    DCHECK(proxy());
-    return static_cast<const ThreadProxy*>(proxy())->impl();
-  }
-
  protected:
   FakeContentLayerClient client_;
   scoped_refptr<FakePictureLayer> update_check_layer_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTest);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreaded);
 };
 
-class ThreadProxyTestSetNeedsCommit : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsCommit : public ProxyMainThreaded {
  protected:
-  ThreadProxyTestSetNeedsCommit() {}
-  ~ThreadProxyTestSetNeedsCommit() override {}
+  ProxyMainThreadedSetNeedsCommit() {}
+  ~ProxyMainThreadedSetNeedsCommit() override {}
 
   void BeginTest() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
 
     proxy()->SetNeedsCommit();
 
-    EXPECT_EQ(ThreadProxy::COMMIT_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
+    EXPECT_EQ(ProxyMain::COMMIT_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
   }
 
   void DidBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
   }
 
   void DidCommit() override {
     EXPECT_EQ(1, update_check_layer_->update_count());
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
     EndTest();
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsCommit);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsCommit);
 };
 
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommit);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsCommit);
 
-class ThreadProxyTestSetNeedsAnimate : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsAnimate : public ProxyMainThreaded {
  protected:
-  ThreadProxyTestSetNeedsAnimate() {}
-  ~ThreadProxyTestSetNeedsAnimate() override {}
+  ProxyMainThreadedSetNeedsAnimate() {}
+  ~ProxyMainThreadedSetNeedsAnimate() override {}
 
   void BeginTest() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
 
     proxy()->SetNeedsAnimate();
 
-    EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
+    EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
   }
 
   void DidBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
   }
 
   void DidCommit() override {
@@ -171,31 +158,31 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsAnimate);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsAnimate);
 };
 
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsAnimate);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsAnimate);
 
-class ThreadProxyTestSetNeedsUpdateLayers : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsUpdateLayers : public ProxyMainThreaded {
  protected:
-  ThreadProxyTestSetNeedsUpdateLayers() {}
-  ~ThreadProxyTestSetNeedsUpdateLayers() override {}
+  ProxyMainThreadedSetNeedsUpdateLayers() {}
+  ~ProxyMainThreadedSetNeedsUpdateLayers() override {}
 
   void BeginTest() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
 
     proxy()->SetNeedsUpdateLayers();
 
-    EXPECT_EQ(ThreadProxy::UPDATE_LAYERS_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
+    EXPECT_EQ(ProxyMain::UPDATE_LAYERS_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
   }
 
   void DidBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
   }
 
   void DidCommit() override {
@@ -204,40 +191,40 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsUpdateLayers);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsUpdateLayers);
 };
 
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsUpdateLayers);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsUpdateLayers);
 
-class ThreadProxyTestSetNeedsUpdateLayersWhileAnimating
-    : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating
+    : public ProxyMainThreaded {
  protected:
-  ThreadProxyTestSetNeedsUpdateLayersWhileAnimating() {}
-  ~ThreadProxyTestSetNeedsUpdateLayersWhileAnimating() override {}
+  ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating() {}
+  ~ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating() override {}
 
   void BeginTest() override { proxy()->SetNeedsAnimate(); }
 
   void WillBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
-              ThreadProxyMainOnly().final_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
+    EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+              GetProxyMainForTest()->final_pipeline_stage());
 
     proxy()->SetNeedsUpdateLayers();
 
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::UPDATE_LAYERS_PIPELINE_STAGE,
-              ThreadProxyMainOnly().final_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::UPDATE_LAYERS_PIPELINE_STAGE,
+              GetProxyMainForTest()->final_pipeline_stage());
   }
 
   void DidBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
   }
 
   void DidCommit() override {
@@ -246,39 +233,39 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsUpdateLayersWhileAnimating);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating);
 };
 
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsUpdateLayersWhileAnimating);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating);
 
-class ThreadProxyTestSetNeedsCommitWhileAnimating : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsCommitWhileAnimating : public ProxyMainThreaded {
  protected:
-  ThreadProxyTestSetNeedsCommitWhileAnimating() {}
-  ~ThreadProxyTestSetNeedsCommitWhileAnimating() override {}
+  ProxyMainThreadedSetNeedsCommitWhileAnimating() {}
+  ~ProxyMainThreadedSetNeedsCommitWhileAnimating() override {}
 
   void BeginTest() override { proxy()->SetNeedsAnimate(); }
 
   void WillBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
-              ThreadProxyMainOnly().final_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
+    EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+              GetProxyMainForTest()->final_pipeline_stage());
 
     proxy()->SetNeedsCommit();
 
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::COMMIT_PIPELINE_STAGE,
-              ThreadProxyMainOnly().final_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::COMMIT_PIPELINE_STAGE,
+              GetProxyMainForTest()->final_pipeline_stage());
   }
 
   void DidBeginMainFrame() override {
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().max_requested_pipeline_stage);
-    EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
-              ThreadProxyMainOnly().current_pipeline_stage);
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->max_requested_pipeline_stage());
+    EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+              GetProxyMainForTest()->current_pipeline_stage());
   }
 
   void DidCommit() override {
@@ -287,15 +274,15 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsCommitWhileAnimating);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsCommitWhileAnimating);
 };
 
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommitWhileAnimating);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsCommitWhileAnimating);
 
-class ThreadProxyTestCommitWaitsForActivation : public ThreadProxyTest {
+class ProxyMainThreadedCommitWaitsForActivation : public ProxyMainThreaded {
  protected:
-  ThreadProxyTestCommitWaitsForActivation() : commits_completed_(0) {}
-  ~ThreadProxyTestCommitWaitsForActivation() override {}
+  ProxyMainThreadedCommitWaitsForActivation() : commits_completed_(0) {}
+  ~ProxyMainThreadedCommitWaitsForActivation() override {}
 
   void BeginTest() override { proxy()->SetNeedsCommit(); }
 
@@ -304,25 +291,25 @@
       case 0:
         // The first commit does not wait for activation. Verify that the
         // completion event is cleared.
-        EXPECT_FALSE(ThreadProxyImplOnly().commit_completion_event);
-        EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+        EXPECT_FALSE(GetProxyImplForTest()->HasCommitCompletionEvent());
+        EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
         break;
       case 1:
         // The second commit should be held until activation.
-        EXPECT_TRUE(ThreadProxyImplOnly().commit_completion_event);
-        EXPECT_TRUE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+        EXPECT_TRUE(GetProxyImplForTest()->HasCommitCompletionEvent());
+        EXPECT_TRUE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
         break;
       case 2:
         // The third commit should not wait for activation.
-        EXPECT_FALSE(ThreadProxyImplOnly().commit_completion_event);
-        EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+        EXPECT_FALSE(GetProxyImplForTest()->HasCommitCompletionEvent());
+        EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
     }
   }
 
   void DidActivateSyncTree() override {
     // The next_commit_waits_for_activation should have been cleared after the
     // sync tree is activated.
-    EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+    EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
   }
 
   void DidCommit() override {
@@ -349,9 +336,9 @@
  private:
   int commits_completed_;
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestCommitWaitsForActivation);
+  DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedCommitWaitsForActivation);
 };
 
-THREAD_PROXY_TEST_F(ThreadProxyTestCommitWaitsForActivation);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedCommitWaitsForActivation);
 
 }  // namespace cc
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
new file mode 100644
index 0000000..810e73e
--- /dev/null
+++ b/cc/trees/proxy_impl.cc
@@ -0,0 +1,684 @@
+// Copyright 2015 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/trees/proxy_impl.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/auto_reset.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
+#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
+#include "cc/input/top_controls_manager.h"
+#include "cc/output/context_provider.h"
+#include "cc/output/output_surface.h"
+#include "cc/scheduler/compositor_timing_history.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/task_runner_provider.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+
+namespace cc {
+
+namespace {
+
+// Measured in seconds.
+const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
+
+unsigned int nextBeginFrameId = 0;
+
+}  // namespace
+
+scoped_ptr<ProxyImpl> ProxyImpl::Create(
+    ChannelImpl* channel_impl,
+    LayerTreeHost* layer_tree_host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  return make_scoped_ptr(new ProxyImpl(channel_impl, layer_tree_host,
+                                       task_runner_provider,
+                                       std::move(external_begin_frame_source)));
+}
+
+ProxyImpl::ProxyImpl(ChannelImpl* channel_impl,
+                     LayerTreeHost* layer_tree_host,
+                     TaskRunnerProvider* task_runner_provider,
+                     scoped_ptr<BeginFrameSource> external_begin_frame_source)
+    : layer_tree_host_id_(layer_tree_host->id()),
+      next_commit_waits_for_activation_(false),
+      commit_completion_event_(nullptr),
+      next_frame_is_newly_committed_frame_(false),
+      inside_draw_(false),
+      input_throttled_until_commit_(false),
+      task_runner_provider_(task_runner_provider),
+      smoothness_priority_expiration_notifier_(
+          task_runner_provider->ImplThreadTaskRunner(),
+          base::Bind(&ProxyImpl::RenewTreePriority, base::Unretained(this)),
+          base::TimeDelta::FromSeconds(
+              kSmoothnessTakesPriorityExpirationDelay)),
+      external_begin_frame_source_(std::move(external_begin_frame_source)),
+      rendering_stats_instrumentation_(
+          layer_tree_host->rendering_stats_instrumentation()),
+      channel_impl_(channel_impl) {
+  TRACE_EVENT0("cc", "ProxyImpl::ProxyImpl");
+  DCHECK(IsImplThread());
+  DCHECK(IsMainThreadBlocked());
+
+  layer_tree_host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this);
+
+  SchedulerSettings scheduler_settings(
+      layer_tree_host->settings().ToSchedulerSettings());
+
+  scoped_ptr<CompositorTimingHistory> compositor_timing_history(
+      new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA,
+                                  rendering_stats_instrumentation_));
+
+  scheduler_ = Scheduler::Create(this, scheduler_settings, layer_tree_host_id_,
+                                 task_runner_provider_->ImplThreadTaskRunner(),
+                                 external_begin_frame_source_.get(),
+                                 std::move(compositor_timing_history));
+
+  DCHECK_EQ(scheduler_->visible(), layer_tree_host_impl_->visible());
+}
+
+ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly()
+    : layer_tree_host(nullptr) {}
+
+ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
+
+ProxyImpl::~ProxyImpl() {
+  TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl");
+  DCHECK(IsImplThread());
+  DCHECK(IsMainThreadBlocked());
+
+  scheduler_ = nullptr;
+  external_begin_frame_source_ = nullptr;
+  layer_tree_host_impl_ = nullptr;
+  // We need to explicitly shutdown the notifier to destroy any weakptrs it is
+  // holding while still on the compositor thread. This also ensures any
+  // callbacks holding a ProxyImpl pointer are cancelled.
+  smoothness_priority_expiration_notifier_.Shutdown();
+}
+
+void ProxyImpl::SetThrottleFrameProductionOnImpl(bool throttle) {
+  TRACE_EVENT1("cc", "ProxyImpl::SetThrottleFrameProductionOnImplThread",
+               "throttle", throttle);
+  DCHECK(IsImplThread());
+  scheduler_->SetThrottleFrameProduction(throttle);
+}
+
+void ProxyImpl::UpdateTopControlsStateOnImpl(TopControlsState constraints,
+                                             TopControlsState current,
+                                             bool animate) {
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->top_controls_manager()->UpdateTopControlsState(
+      constraints, current, animate);
+}
+
+void ProxyImpl::InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {
+  TRACE_EVENT0("cc", "ProxyImpl::InitializeOutputSurfaceOnImplThread");
+  DCHECK(IsImplThread());
+
+  LayerTreeHostImpl* host_impl = layer_tree_host_impl_.get();
+  bool success = host_impl->InitializeRenderer(output_surface);
+  RendererCapabilities capabilities;
+  if (success) {
+    capabilities =
+        host_impl->GetRendererCapabilities().MainThreadCapabilities();
+  }
+
+  channel_impl_->DidInitializeOutputSurface(success, capabilities);
+
+  if (success)
+    scheduler_->DidCreateAndInitializeOutputSurface();
+}
+
+void ProxyImpl::MainThreadHasStoppedFlingingOnImpl() {
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->MainThreadHasStoppedFlinging();
+}
+
+void ProxyImpl::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
+  DCHECK(IsImplThread());
+  if (is_throttled == input_throttled_until_commit_)
+    return;
+  input_throttled_until_commit_ = is_throttled;
+  RenewTreePriority();
+}
+
+void ProxyImpl::SetDeferCommitsOnImpl(bool defer_commits) const {
+  DCHECK(IsImplThread());
+  scheduler_->SetDeferCommits(defer_commits);
+}
+
+void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
+  DCHECK(IsImplThread());
+  SetNeedsRedrawRectOnImplThread(damage_rect);
+}
+
+void ProxyImpl::SetNeedsCommitOnImpl() {
+  DCHECK(IsImplThread());
+  SetNeedsCommitOnImplThread();
+}
+
+void ProxyImpl::BeginMainFrameAbortedOnImpl(
+    CommitEarlyOutReason reason,
+    base::TimeTicks main_thread_start_time) {
+  TRACE_EVENT1("cc", "ProxyImpl::BeginMainFrameAbortedOnImplThread", "reason",
+               CommitEarlyOutReasonToString(reason));
+  DCHECK(IsImplThread());
+  DCHECK(scheduler_->CommitPending());
+  DCHECK(!layer_tree_host_impl_->pending_tree());
+
+  if (CommitEarlyOutHandledCommit(reason)) {
+    SetInputThrottledUntilCommitOnImpl(false);
+    last_processed_begin_main_frame_args_ = last_begin_main_frame_args_;
+  }
+  layer_tree_host_impl_->BeginMainFrameAborted(reason);
+  scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
+  scheduler_->BeginMainFrameAborted(reason);
+}
+
+void ProxyImpl::FinishAllRenderingOnImpl(CompletionEvent* completion) {
+  TRACE_EVENT0("cc", "ProxyImpl::FinishAllRenderingOnImplThread");
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->FinishAllRendering();
+  completion->Signal();
+}
+
+void ProxyImpl::SetVisibleOnImpl(bool visible) {
+  TRACE_EVENT1("cc", "ProxyImpl::SetVisibleOnImplThread", "visible", visible);
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->SetVisible(visible);
+  scheduler_->SetVisible(visible);
+}
+
+void ProxyImpl::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
+  DCHECK(IsImplThread());
+
+  // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call
+  // LayerTreeHost::DidLoseOutputSurface since it already knows.
+  scheduler_->DidLoseOutputSurface();
+  layer_tree_host_impl_->ReleaseOutputSurface();
+  completion->Signal();
+}
+
+void ProxyImpl::FinishGLOnImpl(CompletionEvent* completion) {
+  TRACE_EVENT0("cc", "ProxyImpl::FinishGLOnImplThread");
+  DCHECK(IsImplThread());
+  if (layer_tree_host_impl_->output_surface()) {
+    ContextProvider* context_provider =
+        layer_tree_host_impl_->output_surface()->context_provider();
+    if (context_provider)
+      context_provider->ContextGL()->Finish();
+  }
+  completion->Signal();
+}
+
+void ProxyImpl::MainFrameWillHappenOnImplForTesting(
+    CompletionEvent* completion,
+    bool* main_frame_will_happen) {
+  DCHECK(IsImplThread());
+  if (layer_tree_host_impl_->output_surface()) {
+    *main_frame_will_happen = scheduler_->MainFrameForTestingWillHappen();
+  } else {
+    *main_frame_will_happen = false;
+  }
+  completion->Signal();
+}
+
+void ProxyImpl::StartCommitOnImpl(CompletionEvent* completion,
+                                  LayerTreeHost* layer_tree_host,
+                                  base::TimeTicks main_thread_start_time,
+                                  bool hold_commit_for_activation) {
+  TRACE_EVENT0("cc", "ProxyImpl::StartCommitOnImplThread");
+  DCHECK(!commit_completion_event_);
+  DCHECK(IsImplThread() && IsMainThreadBlocked());
+  DCHECK(scheduler_);
+  DCHECK(scheduler_->CommitPending());
+
+  if (hold_commit_for_activation) {
+    // This commit may be aborted. Store the value for
+    // hold_commit_for_activation so that whenever the next commit is started,
+    // the main thread will be unblocked only after pending tree activation.
+    next_commit_waits_for_activation_ = hold_commit_for_activation;
+  }
+
+  if (!layer_tree_host_impl_) {
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree",
+                         TRACE_EVENT_SCOPE_THREAD);
+    completion->Signal();
+    return;
+  }
+
+  // Ideally, we should inform to impl thread when BeginMainFrame is started.
+  // But, we can avoid a PostTask in here.
+  scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
+  commit_completion_event_ = completion;
+  DCHECK(!blocked_main_commit().layer_tree_host);
+  blocked_main_commit().layer_tree_host = layer_tree_host;
+  scheduler_->NotifyReadyToCommit();
+}
+
+void ProxyImpl::UpdateRendererCapabilitiesOnImplThread() {
+  DCHECK(IsImplThread());
+  channel_impl_->SetRendererCapabilitiesMainCopy(
+      layer_tree_host_impl_->GetRendererCapabilities()
+          .MainThreadCapabilities());
+}
+
+void ProxyImpl::DidLoseOutputSurfaceOnImplThread() {
+  TRACE_EVENT0("cc", "ProxyImpl::DidLoseOutputSurfaceOnImplThread");
+  DCHECK(IsImplThread());
+  channel_impl_->DidLoseOutputSurface();
+  scheduler_->DidLoseOutputSurface();
+}
+
+void ProxyImpl::CommitVSyncParameters(base::TimeTicks timebase,
+                                      base::TimeDelta interval) {
+  DCHECK(IsImplThread());
+  scheduler_->CommitVSyncParameters(timebase, interval);
+}
+
+void ProxyImpl::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
+  DCHECK(IsImplThread());
+  scheduler_->SetEstimatedParentDrawTime(draw_time);
+}
+
+void ProxyImpl::DidSwapBuffersOnImplThread() {
+  DCHECK(IsImplThread());
+  scheduler_->DidSwapBuffers();
+}
+
+void ProxyImpl::DidSwapBuffersCompleteOnImplThread() {
+  TRACE_EVENT0("cc,benchmark", "ProxyImpl::DidSwapBuffersCompleteOnImplThread");
+  DCHECK(IsImplThread());
+  scheduler_->DidSwapBuffersComplete();
+  channel_impl_->DidCompleteSwapBuffers();
+}
+
+void ProxyImpl::OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) {
+  DCHECK(IsImplThread());
+  scheduler_->SetResourcelessSoftareDraw(resourceless_draw);
+}
+
+void ProxyImpl::OnCanDrawStateChanged(bool can_draw) {
+  TRACE_EVENT1("cc", "ProxyImpl::OnCanDrawStateChanged", "can_draw", can_draw);
+  DCHECK(IsImplThread());
+  scheduler_->SetCanDraw(can_draw);
+}
+
+void ProxyImpl::NotifyReadyToActivate() {
+  TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToActivate");
+  DCHECK(IsImplThread());
+  scheduler_->NotifyReadyToActivate();
+}
+
+void ProxyImpl::NotifyReadyToDraw() {
+  TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToDraw");
+  DCHECK(IsImplThread());
+  scheduler_->NotifyReadyToDraw();
+}
+
+void ProxyImpl::SetNeedsRedrawOnImplThread() {
+  TRACE_EVENT0("cc", "ProxyImpl::SetNeedsRedrawOnImplThread");
+  DCHECK(IsImplThread());
+  scheduler_->SetNeedsRedraw();
+}
+
+void ProxyImpl::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->SetViewportDamage(damage_rect);
+  SetNeedsRedrawOnImplThread();
+}
+
+void ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread() {
+  TRACE_EVENT0("cc", "ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread");
+  DCHECK(IsImplThread());
+  scheduler_->SetNeedsOneBeginImplFrame();
+}
+
+void ProxyImpl::SetNeedsPrepareTilesOnImplThread() {
+  DCHECK(IsImplThread());
+  scheduler_->SetNeedsPrepareTiles();
+}
+
+void ProxyImpl::SetNeedsCommitOnImplThread() {
+  TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
+  DCHECK(IsImplThread());
+  scheduler_->SetNeedsBeginMainFrame();
+}
+
+void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
+  TRACE_EVENT1("cc", "ProxyImpl::SetVideoNeedsBeginFrames",
+               "needs_begin_frames", needs_begin_frames);
+  DCHECK(IsImplThread());
+  // In tests the layer tree is destroyed after the scheduler is.
+  if (scheduler_)
+    scheduler_->SetVideoNeedsBeginFrames(needs_begin_frames);
+}
+
+void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread(
+    scoped_ptr<AnimationEventsVector> events) {
+  TRACE_EVENT0("cc", "ProxyImpl::PostAnimationEventsToMainThreadOnImplThread");
+  DCHECK(IsImplThread());
+  channel_impl_->SetAnimationEvents(std::move(events));
+}
+
+bool ProxyImpl::IsInsideDraw() {
+  return inside_draw_;
+}
+
+void ProxyImpl::RenewTreePriority() {
+  DCHECK(IsImplThread());
+  bool smoothness_takes_priority =
+      layer_tree_host_impl_->pinch_gesture_active() ||
+      layer_tree_host_impl_->page_scale_animation_active() ||
+      layer_tree_host_impl_->IsActivelyScrolling();
+
+  // Schedule expiration if smoothness currently takes priority.
+  if (smoothness_takes_priority)
+    smoothness_priority_expiration_notifier_.Schedule();
+
+  // We use the same priority for both trees by default.
+  TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
+
+  // Smoothness takes priority if we have an expiration for it scheduled.
+  if (smoothness_priority_expiration_notifier_.HasPendingNotification())
+    tree_priority = SMOOTHNESS_TAKES_PRIORITY;
+
+  // New content always takes priority when there is an invalid viewport size or
+  // ui resources have been evicted.
+  if (layer_tree_host_impl_->active_tree()->ViewportSizeInvalid() ||
+      layer_tree_host_impl_->EvictedUIResourcesExist() ||
+      input_throttled_until_commit_) {
+    // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
+    // tree might be freed. We need to set RequiresHighResToDraw to ensure that
+    // high res tiles will be required to activate pending tree.
+    layer_tree_host_impl_->SetRequiresHighResToDraw();
+    tree_priority = NEW_CONTENT_TAKES_PRIORITY;
+  }
+
+  layer_tree_host_impl_->SetTreePriority(tree_priority);
+
+  // Only put the scheduler in impl latency prioritization mode if we don't
+  // have a scroll listener. This gives the scroll listener a better chance of
+  // handling scroll updates within the same frame. The tree itself is still
+  // kept in prefer smoothness mode to allow checkerboarding.
+  ScrollHandlerState scroll_handler_state =
+      layer_tree_host_impl_->scroll_affects_scroll_handler()
+          ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
+          : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
+  scheduler_->SetTreePrioritiesAndScrollState(tree_priority,
+                                              scroll_handler_state);
+
+  // Notify the the client of this compositor via the output surface.
+  // TODO(epenner): Route this to compositor-thread instead of output-surface
+  // after GTFO refactor of compositor-thread (http://crbug/170828).
+  if (layer_tree_host_impl_->output_surface()) {
+    layer_tree_host_impl_->output_surface()->UpdateSmoothnessTakesPriority(
+        tree_priority == SMOOTHNESS_TAKES_PRIORITY);
+  }
+}
+
+void ProxyImpl::PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
+                                                     base::TimeDelta delay) {
+  DCHECK(IsImplThread());
+  task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE,
+                                                                 task, delay);
+}
+
+void ProxyImpl::DidActivateSyncTree() {
+  TRACE_EVENT0("cc", "ProxyImpl::DidActivateSyncTreeOnImplThread");
+  DCHECK(IsImplThread());
+
+  if (next_commit_waits_for_activation_) {
+    TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
+                         TRACE_EVENT_SCOPE_THREAD);
+    DCHECK(commit_completion_event_);
+    commit_completion_event_->Signal();
+    commit_completion_event_ = nullptr;
+    next_commit_waits_for_activation_ = false;
+  }
+
+  last_processed_begin_main_frame_args_ = last_begin_main_frame_args_;
+}
+
+void ProxyImpl::WillPrepareTiles() {
+  DCHECK(IsImplThread());
+  scheduler_->WillPrepareTiles();
+}
+
+void ProxyImpl::DidPrepareTiles() {
+  DCHECK(IsImplThread());
+  scheduler_->DidPrepareTiles();
+}
+
+void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() {
+  DCHECK(IsImplThread());
+  channel_impl_->DidCompletePageScaleAnimation();
+}
+
+void ProxyImpl::OnDrawForOutputSurface() {
+  DCHECK(IsImplThread());
+  scheduler_->OnDrawForOutputSurface();
+}
+
+void ProxyImpl::PostFrameTimingEventsOnImplThread(
+    scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+    scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+  DCHECK(IsImplThread());
+  channel_impl_->PostFrameTimingEventsOnMain(std::move(composite_events),
+                                             std::move(main_frame_events));
+}
+
+void ProxyImpl::WillBeginImplFrame(const BeginFrameArgs& args) {
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->WillBeginImplFrame(args);
+  if (last_processed_begin_main_frame_args_.IsValid()) {
+    // Last processed begin main frame args records the frame args that we sent
+    // to the main thread for the last frame that we've processed. If that is
+    // set, that means the current frame is one past the frame in which we've
+    // finished the processing.
+    layer_tree_host_impl_->RecordMainFrameTiming(
+        last_processed_begin_main_frame_args_, args);
+    last_processed_begin_main_frame_args_ = BeginFrameArgs();
+  }
+}
+
+void ProxyImpl::DidFinishImplFrame() {
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->DidFinishImplFrame();
+}
+
+void ProxyImpl::ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) {
+  DCHECK(IsImplThread());
+  unsigned int begin_frame_id = nextBeginFrameId++;
+  benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
+      benchmark_instrumentation::kSendBeginFrame, begin_frame_id);
+  scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
+      new BeginMainFrameAndCommitState);
+  begin_main_frame_state->begin_frame_id = begin_frame_id;
+  begin_main_frame_state->begin_frame_args = args;
+  begin_main_frame_state->scroll_info =
+      layer_tree_host_impl_->ProcessScrollDeltas();
+  begin_main_frame_state->memory_allocation_limit_bytes =
+      layer_tree_host_impl_->memory_allocation_limit_bytes();
+  begin_main_frame_state->evicted_ui_resources =
+      layer_tree_host_impl_->EvictedUIResourcesExist();
+  // TODO(vmpstr): This needs to be fixed if
+  // main_frame_before_activation_enabled is set, since we might run this code
+  // twice before recording a duration. crbug.com/469824
+  last_begin_main_frame_args_ = begin_main_frame_state->begin_frame_args;
+  channel_impl_->BeginMainFrame(std::move(begin_main_frame_state));
+  devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_);
+}
+
+DrawResult ProxyImpl::ScheduledActionDrawAndSwapIfPossible() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawAndSwap");
+  DCHECK(IsImplThread());
+
+  // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
+  // handle DRAW_ABORTED_CANT_DRAW.  Moreover, the scheduler should
+  // never generate this call when it can't draw.
+  DCHECK(layer_tree_host_impl_->CanDraw());
+
+  bool forced_draw = false;
+  return DrawAndSwapInternal(forced_draw);
+}
+
+DrawResult ProxyImpl::ScheduledActionDrawAndSwapForced() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawAndSwapForced");
+  DCHECK(IsImplThread());
+  bool forced_draw = true;
+  return DrawAndSwapInternal(forced_draw);
+}
+
+void ProxyImpl::ScheduledActionCommit() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionCommit");
+  DCHECK(IsImplThread());
+  DCHECK(IsMainThreadBlocked());
+  DCHECK(commit_completion_event_);
+
+  layer_tree_host_impl_->BeginCommit();
+  blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
+      layer_tree_host_impl_.get());
+
+  // Remove the LayerTreeHost reference before the completion event is signaled
+  // and cleared. This is necessary since blocked_main_commit() allows access
+  // only while we have the completion event to ensure the main thread is
+  // blocked for a commit.
+  blocked_main_commit().layer_tree_host = nullptr;
+
+  if (next_commit_waits_for_activation_) {
+    // For some layer types in impl-side painting, the commit is held until
+    // the sync tree is activated.  It's also possible that the
+    // sync tree has already activated if there was no work to be done.
+    TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
+  } else {
+    commit_completion_event_->Signal();
+    commit_completion_event_ = nullptr;
+  }
+
+  scheduler_->DidCommit();
+
+  // Delay this step until afer the main thread has been released as it's
+  // often a good bit of work to update the tree and prepare the new frame.
+  layer_tree_host_impl_->CommitComplete();
+
+  SetInputThrottledUntilCommitOnImpl(false);
+
+  next_frame_is_newly_committed_frame_ = true;
+}
+
+void ProxyImpl::ScheduledActionActivateSyncTree() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionActivateSyncTree");
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->ActivateSyncTree();
+}
+
+void ProxyImpl::ScheduledActionBeginOutputSurfaceCreation() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionBeginOutputSurfaceCreation");
+  DCHECK(IsImplThread());
+  channel_impl_->RequestNewOutputSurface();
+}
+
+void ProxyImpl::ScheduledActionPrepareTiles() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPrepareTiles");
+  DCHECK(IsImplThread());
+  layer_tree_host_impl_->PrepareTiles();
+}
+
+void ProxyImpl::ScheduledActionInvalidateOutputSurface() {
+  TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionInvalidateOutputSurface");
+  DCHECK(IsImplThread());
+  DCHECK(layer_tree_host_impl_->output_surface());
+  layer_tree_host_impl_->output_surface()->Invalidate();
+}
+
+void ProxyImpl::SendBeginFramesToChildren(const BeginFrameArgs& args) {
+  NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
+void ProxyImpl::SendBeginMainFrameNotExpectedSoon() {
+  DCHECK(IsImplThread());
+  channel_impl_->BeginMainFrameNotExpectedSoon();
+}
+
+DrawResult ProxyImpl::DrawAndSwapInternal(bool forced_draw) {
+  TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
+
+  DCHECK(IsImplThread());
+  DCHECK(layer_tree_host_impl_.get());
+
+  base::AutoReset<bool> mark_inside(&inside_draw_, true);
+
+  if (layer_tree_host_impl_->pending_tree()) {
+    bool update_lcd_text = false;
+    layer_tree_host_impl_->pending_tree()->UpdateDrawProperties(
+        update_lcd_text);
+  }
+
+  // This method is called on a forced draw, regardless of whether we are able
+  // to produce a frame, as the calling site on main thread is blocked until its
+  // request completes, and we signal completion here. If CanDraw() is false, we
+  // will indicate success=false to the caller, but we must still signal
+  // completion to avoid deadlock.
+
+  // We guard PrepareToDraw() with CanDraw() because it always returns a valid
+  // frame, so can only be used when such a frame is possible. Since
+  // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
+  // CanDraw() as well.
+
+  LayerTreeHostImpl::FrameData frame;
+  bool draw_frame = false;
+
+  DrawResult result;
+  if (layer_tree_host_impl_->CanDraw()) {
+    result = layer_tree_host_impl_->PrepareToDraw(&frame);
+    draw_frame = forced_draw || result == DRAW_SUCCESS;
+  } else {
+    result = DRAW_ABORTED_CANT_DRAW;
+  }
+
+  if (draw_frame) {
+    layer_tree_host_impl_->DrawLayers(&frame);
+    result = DRAW_SUCCESS;
+  } else {
+    DCHECK_NE(DRAW_SUCCESS, result);
+  }
+  layer_tree_host_impl_->DidDrawAllLayers(frame);
+
+  bool start_ready_animations = draw_frame;
+  layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
+
+  if (draw_frame)
+    layer_tree_host_impl_->SwapBuffers(frame);
+
+  // Tell the main thread that the the newly-commited frame was drawn.
+  if (next_frame_is_newly_committed_frame_) {
+    next_frame_is_newly_committed_frame_ = false;
+    channel_impl_->DidCommitAndDrawFrame();
+  }
+
+  DCHECK_NE(INVALID_RESULT, result);
+  return result;
+}
+
+bool ProxyImpl::IsImplThread() const {
+  return task_runner_provider_->IsImplThread();
+}
+
+bool ProxyImpl::IsMainThreadBlocked() const {
+  return task_runner_provider_->IsMainThreadBlocked();
+}
+
+ProxyImpl::BlockedMainCommitOnly& ProxyImpl::blocked_main_commit() {
+  DCHECK(IsMainThreadBlocked() && commit_completion_event_);
+  return main_thread_blocked_commit_vars_unsafe_;
+}
+
+}  // namespace cc
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index 4b0cdaa..092385b5 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -5,59 +5,171 @@
 #ifndef CC_TREES_PROXY_IMPL_H_
 #define CC_TREES_PROXY_IMPL_H_
 
-#include "base/memory/weak_ptr.h"
-#include "cc/base/cc_export.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
 #include "cc/base/completion_event.h"
+#include "cc/base/delayed_unique_notifier.h"
 #include "cc/input/top_controls_state.h"
-#include "cc/output/output_surface.h"
-#include "cc/scheduler/commit_earlyout_reason.h"
-#include "cc/trees/proxy_common.h"
+#include "cc/scheduler/scheduler.h"
+#include "cc/trees/channel_impl.h"
+#include "cc/trees/layer_tree_host_impl.h"
 
 namespace cc {
-// TODO(khushalsagar): The impl side of ThreadProxy. It is currently defined as
-// an interface with the implementation provided by ThreadProxy and will be
-// made an independent class.
-// The methods added to this interface should only use the CompositorThreadOnly
-// variables from ThreadProxy.
-// See crbug/527200
-class CC_EXPORT ProxyImpl {
- private:
-  friend class ThreadedChannel;
 
-  // Callback for impl side commands received from the channel.
-  virtual void SetThrottleFrameProductionOnImpl(bool throttle) = 0;
+// This class aggregates all the interactions that the main side of the
+// compositor needs to have with the impl side. It is created and owned by the
+// ChannelImpl implementation. The class lives entirely on the impl thread.
+class CC_EXPORT ProxyImpl : public NON_EXPORTED_BASE(LayerTreeHostImplClient),
+                            public NON_EXPORTED_BASE(SchedulerClient) {
+ public:
+  static scoped_ptr<ProxyImpl> Create(
+      ChannelImpl* channel_impl,
+      LayerTreeHost* layer_tree_host,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+  ~ProxyImpl() override;
+
+  // Virtual for testing.
+  virtual void SetThrottleFrameProductionOnImpl(bool throttle);
   virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
                                             TopControlsState current,
-                                            bool animate) = 0;
-  virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) = 0;
-  virtual void MainThreadHasStoppedFlingingOnImpl() = 0;
-  virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled) = 0;
-  virtual void SetDeferCommitsOnImpl(bool defer_commits) const = 0;
-  virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) = 0;
-  virtual void SetNeedsCommitOnImpl() = 0;
-  virtual void FinishAllRenderingOnImpl(CompletionEvent* completion) = 0;
-  virtual void SetVisibleOnImpl(bool visible) = 0;
-  virtual void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) = 0;
-  virtual void FinishGLOnImpl(CompletionEvent* completion) = 0;
-  virtual void MainFrameWillHappenOnImplForTesting(
-      CompletionEvent* completion,
-      bool* main_frame_will_happen) = 0;
+                                            bool animate);
+  virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface);
+  virtual void MainThreadHasStoppedFlingingOnImpl();
+  virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled);
+  virtual void SetDeferCommitsOnImpl(bool defer_commits) const;
+  virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
+  virtual void SetNeedsCommitOnImpl();
   virtual void BeginMainFrameAbortedOnImpl(
       CommitEarlyOutReason reason,
-      base::TimeTicks main_thread_start_time) = 0;
+      base::TimeTicks main_thread_start_time);
+  virtual void FinishAllRenderingOnImpl(CompletionEvent* completion);
+  virtual void SetVisibleOnImpl(bool visible);
+  virtual void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion);
+  virtual void FinishGLOnImpl(CompletionEvent* completion);
+  virtual void MainFrameWillHappenOnImplForTesting(
+      CompletionEvent* completion,
+      bool* main_frame_will_happen);
   virtual void StartCommitOnImpl(CompletionEvent* completion,
                                  LayerTreeHost* layer_tree_host,
                                  base::TimeTicks main_thread_start_time,
-                                 bool hold_commit_for_activation) = 0;
-  virtual void InitializeImplOnImpl(CompletionEvent* completion,
-                                    LayerTreeHost* layer_tree_host) = 0;
-  virtual void LayerTreeHostClosedOnImpl(CompletionEvent* completion) = 0;
-
-  // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split.
-  virtual base::WeakPtr<ProxyImpl> GetImplWeakPtr() = 0;
+                                 bool hold_commit_for_activation);
 
  protected:
-  virtual ~ProxyImpl() {}
+  // protected for testing.
+  ProxyImpl(ChannelImpl* channel_impl,
+            LayerTreeHost* layer_tree_host,
+            TaskRunnerProvider* task_runner_provider,
+            scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ private:
+  // The members of this struct should be accessed on the impl thread only when
+  // the main thread is blocked for a commit.
+  struct BlockedMainCommitOnly {
+    BlockedMainCommitOnly();
+    ~BlockedMainCommitOnly();
+    LayerTreeHost* layer_tree_host;
+  };
+
+  friend class ProxyImplForTest;
+
+  // LayerTreeHostImplClient implementation
+  void UpdateRendererCapabilitiesOnImplThread() override;
+  void DidLoseOutputSurfaceOnImplThread() override;
+  void CommitVSyncParameters(base::TimeTicks timebase,
+                             base::TimeDelta interval) override;
+  void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override;
+  void DidSwapBuffersOnImplThread() override;
+  void DidSwapBuffersCompleteOnImplThread() override;
+  void OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) override;
+  void OnCanDrawStateChanged(bool can_draw) override;
+  void NotifyReadyToActivate() override;
+  void NotifyReadyToDraw() override;
+  // Please call these 3 functions through
+  // LayerTreeHostImpl's SetNeedsRedraw(), SetNeedsRedrawRect() and
+  // SetNeedsOneBeginImplFrame().
+  void SetNeedsRedrawOnImplThread() override;
+  void SetNeedsRedrawRectOnImplThread(const gfx::Rect& dirty_rect) override;
+  void SetNeedsOneBeginImplFrameOnImplThread() override;
+  void SetNeedsPrepareTilesOnImplThread() override;
+  void SetNeedsCommitOnImplThread() override;
+  void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
+  void PostAnimationEventsToMainThreadOnImplThread(
+      scoped_ptr<AnimationEventsVector> queue) override;
+  bool IsInsideDraw() override;
+  void RenewTreePriority() override;
+  void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
+                                            base::TimeDelta delay) override;
+  void DidActivateSyncTree() override;
+  void WillPrepareTiles() override;
+  void DidPrepareTiles() override;
+  void DidCompletePageScaleAnimationOnImplThread() override;
+  void OnDrawForOutputSurface() override;
+  // This should only be called by LayerTreeHostImpl::PostFrameTimingEvents.
+  void PostFrameTimingEventsOnImplThread(
+      scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
+      override;
+
+  // SchedulerClient implementation
+  void WillBeginImplFrame(const BeginFrameArgs& args) override;
+  void DidFinishImplFrame() override;
+  void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override;
+  DrawResult ScheduledActionDrawAndSwapIfPossible() override;
+  DrawResult ScheduledActionDrawAndSwapForced() override;
+  void ScheduledActionCommit() override;
+  void ScheduledActionActivateSyncTree() override;
+  void ScheduledActionBeginOutputSurfaceCreation() override;
+  void ScheduledActionPrepareTiles() override;
+  void ScheduledActionInvalidateOutputSurface() override;
+  void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
+  void SendBeginMainFrameNotExpectedSoon() override;
+
+  DrawResult DrawAndSwapInternal(bool forced_draw);
+
+  bool IsImplThread() const;
+  bool IsMainThreadBlocked() const;
+
+  const int layer_tree_host_id_;
+
+  scoped_ptr<Scheduler> scheduler_;
+
+  // Set when the main thread is waiting on a pending tree activation.
+  bool next_commit_waits_for_activation_;
+
+  // Set when the main thread is waiting on a commit to complete or on a
+  // pending tree activation.
+  CompletionEvent* commit_completion_event_;
+
+  // Set when the next draw should post DidCommitAndDrawFrame to the main
+  // thread.
+  bool next_frame_is_newly_committed_frame_;
+
+  bool inside_draw_;
+  bool input_throttled_until_commit_;
+
+  TaskRunnerProvider* task_runner_provider_;
+
+  DelayedUniqueNotifier smoothness_priority_expiration_notifier_;
+
+  scoped_ptr<BeginFrameSource> external_begin_frame_source_;
+
+  RenderingStatsInstrumentation* rendering_stats_instrumentation_;
+
+  // Values used to keep track of frame durations. Used only in frame timing.
+  BeginFrameArgs last_begin_main_frame_args_;
+  BeginFrameArgs last_processed_begin_main_frame_args_;
+
+  scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl_;
+
+  ChannelImpl* channel_impl_;
+
+  // Use accessors instead of this variable directly.
+  BlockedMainCommitOnly main_thread_blocked_commit_vars_unsafe_;
+  BlockedMainCommitOnly& blocked_main_commit();
+
+  DISALLOW_COPY_AND_ASSIGN(ProxyImpl);
 };
 
 }  // namespace cc
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
new file mode 100644
index 0000000..dd5ac1a
--- /dev/null
+++ b/cc/trees/proxy_main.cc
@@ -0,0 +1,465 @@
+// Copyright 2015 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/trees/proxy_main.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
+#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
+#include "cc/output/output_surface.h"
+#include "cc/output/swap_promise.h"
+#include "cc/trees/blocking_task_runner.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/scoped_abort_remaining_swap_promises.h"
+#include "cc/trees/threaded_channel.h"
+
+namespace cc {
+
+scoped_ptr<ProxyMain> ProxyMain::CreateThreaded(
+    LayerTreeHost* layer_tree_host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  scoped_ptr<ProxyMain> proxy_main(
+      new ProxyMain(layer_tree_host, task_runner_provider,
+                    std::move(external_begin_frame_source)));
+  proxy_main->SetChannel(
+      ThreadedChannel::Create(proxy_main.get(), task_runner_provider));
+  return proxy_main;
+}
+
+ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
+                     TaskRunnerProvider* task_runner_provider,
+                     scoped_ptr<BeginFrameSource> external_begin_frame_source)
+    : layer_tree_host_(layer_tree_host),
+      task_runner_provider_(task_runner_provider),
+      layer_tree_host_id_(layer_tree_host->id()),
+      max_requested_pipeline_stage_(NO_PIPELINE_STAGE),
+      current_pipeline_stage_(NO_PIPELINE_STAGE),
+      final_pipeline_stage_(NO_PIPELINE_STAGE),
+      commit_waits_for_activation_(false),
+      started_(false),
+      defer_commits_(false),
+      external_begin_frame_source_(std::move(external_begin_frame_source)) {
+  TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
+  DCHECK(task_runner_provider_);
+  DCHECK(IsMainThread());
+  DCHECK(!layer_tree_host_->settings().use_external_begin_frame_source ||
+         external_begin_frame_source_);
+}
+
+ProxyMain::~ProxyMain() {
+  TRACE_EVENT0("cc", "ProxyMain::~ProxyMain");
+  DCHECK(IsMainThread());
+  DCHECK(!started_);
+}
+
+void ProxyMain::SetChannel(scoped_ptr<ChannelMain> channel_main) {
+  DCHECK(!channel_main_);
+  channel_main_ = std::move(channel_main);
+}
+
+void ProxyMain::DidCompleteSwapBuffers() {
+  DCHECK(IsMainThread());
+  layer_tree_host_->DidCompleteSwapBuffers();
+}
+
+void ProxyMain::SetRendererCapabilities(
+    const RendererCapabilities& capabilities) {
+  DCHECK(IsMainThread());
+  renderer_capabilities_ = capabilities;
+}
+
+void ProxyMain::BeginMainFrameNotExpectedSoon() {
+  TRACE_EVENT0("cc", "ProxyMain::BeginMainFrameNotExpectedSoon");
+  DCHECK(IsMainThread());
+  layer_tree_host_->BeginMainFrameNotExpectedSoon();
+}
+
+void ProxyMain::DidCommitAndDrawFrame() {
+  DCHECK(IsMainThread());
+  layer_tree_host_->DidCommitAndDrawFrame();
+}
+
+void ProxyMain::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
+  TRACE_EVENT0("cc", "ProxyMain::SetAnimationEvents");
+  DCHECK(IsMainThread());
+  layer_tree_host_->SetAnimationEvents(std::move(events));
+}
+
+void ProxyMain::DidLoseOutputSurface() {
+  TRACE_EVENT0("cc", "ProxyMain::DidLoseOutputSurface");
+  DCHECK(IsMainThread());
+  layer_tree_host_->DidLoseOutputSurface();
+}
+
+void ProxyMain::RequestNewOutputSurface() {
+  DCHECK(IsMainThread());
+  layer_tree_host_->RequestNewOutputSurface();
+}
+
+void ProxyMain::DidInitializeOutputSurface(
+    bool success,
+    const RendererCapabilities& capabilities) {
+  TRACE_EVENT0("cc", "ProxyMain::DidInitializeOutputSurface");
+  DCHECK(IsMainThread());
+
+  if (!success) {
+    layer_tree_host_->DidFailToInitializeOutputSurface();
+    return;
+  }
+  renderer_capabilities_ = capabilities;
+  layer_tree_host_->DidInitializeOutputSurface();
+}
+
+void ProxyMain::DidCompletePageScaleAnimation() {
+  DCHECK(IsMainThread());
+  layer_tree_host_->DidCompletePageScaleAnimation();
+}
+
+void ProxyMain::PostFrameTimingEventsOnMain(
+    scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+    scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+  DCHECK(IsMainThread());
+  layer_tree_host_->RecordFrameTimingEvents(std::move(composite_events),
+                                            std::move(main_frame_events));
+}
+
+void ProxyMain::BeginMainFrame(
+    scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+  benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
+      benchmark_instrumentation::kDoBeginFrame,
+      begin_main_frame_state->begin_frame_id);
+
+  base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
+
+  TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
+  DCHECK(IsMainThread());
+  DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
+
+  if (defer_commits_) {
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
+                         TRACE_EVENT_SCOPE_THREAD);
+    channel_main_->BeginMainFrameAbortedOnImpl(
+        CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
+        begin_main_frame_start_time);
+    return;
+  }
+
+  // If the commit finishes, LayerTreeHost will transfer its swap promises to
+  // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
+  // remaining swap promises.
+  ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
+
+  final_pipeline_stage_ = max_requested_pipeline_stage_;
+  max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
+
+  if (!layer_tree_host_->visible()) {
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
+    channel_main_->BeginMainFrameAbortedOnImpl(
+        CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
+    return;
+  }
+
+  if (layer_tree_host_->output_surface_lost()) {
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_OutputSurfaceLost",
+                         TRACE_EVENT_SCOPE_THREAD);
+    channel_main_->BeginMainFrameAbortedOnImpl(
+        CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
+        begin_main_frame_start_time);
+    return;
+  }
+
+  current_pipeline_stage_ = ANIMATE_PIPELINE_STAGE;
+
+  layer_tree_host_->ApplyScrollAndScale(
+      begin_main_frame_state->scroll_info.get());
+
+  layer_tree_host_->WillBeginMainFrame();
+
+  layer_tree_host_->BeginMainFrame(begin_main_frame_state->begin_frame_args);
+  layer_tree_host_->AnimateLayers(
+      begin_main_frame_state->begin_frame_args.frame_time);
+
+  // Recreate all UI resources if there were evicted UI resources when the impl
+  // thread initiated the commit.
+  if (begin_main_frame_state->evicted_ui_resources)
+    layer_tree_host_->RecreateUIResources();
+
+  layer_tree_host_->RequestMainFrameUpdate();
+  TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
+
+  bool can_cancel_this_commit = final_pipeline_stage_ < COMMIT_PIPELINE_STAGE &&
+                                !begin_main_frame_state->evicted_ui_resources;
+
+  current_pipeline_stage_ = UPDATE_LAYERS_PIPELINE_STAGE;
+  bool should_update_layers =
+      final_pipeline_stage_ >= UPDATE_LAYERS_PIPELINE_STAGE;
+  bool updated = should_update_layers && layer_tree_host_->UpdateLayers();
+
+  layer_tree_host_->WillCommit();
+  devtools_instrumentation::ScopedCommitTrace commit_task(
+      layer_tree_host_->id());
+
+  current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
+  if (!updated && can_cancel_this_commit) {
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
+    channel_main_->BeginMainFrameAbortedOnImpl(
+        CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
+
+    // Although the commit is internally aborted, this is because it has been
+    // detected to be a no-op.  From the perspective of an embedder, this commit
+    // went through, and input should no longer be throttled, etc.
+    current_pipeline_stage_ = NO_PIPELINE_STAGE;
+    layer_tree_host_->CommitComplete();
+    layer_tree_host_->DidBeginMainFrame();
+    layer_tree_host_->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
+    return;
+  }
+
+  // Notify the impl thread that the main thread is ready to commit. This will
+  // begin the commit process, which is blocking from the main thread's
+  // point of view, but asynchronously performed on the impl thread,
+  // coordinated by the Scheduler.
+  {
+    TRACE_EVENT0("cc", "ProxyMain::BeginMainFrame::commit");
+
+    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+
+    // This CapturePostTasks should be destroyed before CommitComplete() is
+    // called since that goes out to the embedder, and we want the embedder
+    // to receive its callbacks before that.
+    BlockingTaskRunner::CapturePostTasks blocked(
+        task_runner_provider_->blocking_main_thread_task_runner());
+
+    bool hold_commit_for_activation = commit_waits_for_activation_;
+    commit_waits_for_activation_ = false;
+    CompletionEvent completion;
+    channel_main_->StartCommitOnImpl(&completion, layer_tree_host_,
+                                     begin_main_frame_start_time,
+                                     hold_commit_for_activation);
+    completion.Wait();
+  }
+
+  current_pipeline_stage_ = NO_PIPELINE_STAGE;
+  layer_tree_host_->CommitComplete();
+  layer_tree_host_->DidBeginMainFrame();
+}
+
+void ProxyMain::FinishAllRendering() {
+  DCHECK(IsMainThread());
+  DCHECK(!defer_commits_);
+
+  // Make sure all GL drawing is finished on the impl thread.
+  DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+  CompletionEvent completion;
+  channel_main_->FinishAllRenderingOnImpl(&completion);
+  completion.Wait();
+}
+
+bool ProxyMain::IsStarted() const {
+  DCHECK(IsMainThread());
+  return started_;
+}
+
+bool ProxyMain::CommitToActiveTree() const {
+  // With ProxyMain, we use a pending tree and activate it once it's ready to
+  // draw to allow input to modify the active tree and draw during raster.
+  return false;
+}
+
+void ProxyMain::SetOutputSurface(OutputSurface* output_surface) {
+  channel_main_->InitializeOutputSurfaceOnImpl(output_surface);
+}
+
+void ProxyMain::SetVisible(bool visible) {
+  TRACE_EVENT1("cc", "ProxyMain::SetVisible", "visible", visible);
+  channel_main_->SetVisibleOnImpl(visible);
+}
+
+void ProxyMain::SetThrottleFrameProduction(bool throttle) {
+  TRACE_EVENT1("cc", "ProxyMain::SetThrottleFrameProduction", "throttle",
+               throttle);
+  channel_main_->SetThrottleFrameProductionOnImpl(throttle);
+}
+
+const RendererCapabilities& ProxyMain::GetRendererCapabilities() const {
+  DCHECK(IsMainThread());
+  DCHECK(!layer_tree_host_->output_surface_lost());
+  return renderer_capabilities_;
+}
+
+void ProxyMain::SetNeedsAnimate() {
+  DCHECK(IsMainThread());
+  if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
+    TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
+                         TRACE_EVENT_SCOPE_THREAD);
+  }
+}
+
+void ProxyMain::SetNeedsUpdateLayers() {
+  DCHECK(IsMainThread());
+  // If we are currently animating, make sure we also update the layers.
+  if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
+    final_pipeline_stage_ =
+        std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
+    return;
+  }
+  if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
+    TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
+                         TRACE_EVENT_SCOPE_THREAD);
+  }
+}
+
+void ProxyMain::SetNeedsCommit() {
+  DCHECK(IsMainThread());
+  // If we are currently animating, make sure we don't skip the commit. Note
+  // that requesting a commit during the layer update stage means we need to
+  // schedule another full commit.
+  if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
+    final_pipeline_stage_ =
+        std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
+    return;
+  }
+  if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
+    TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
+                         TRACE_EVENT_SCOPE_THREAD);
+  }
+}
+
+void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) {
+  TRACE_EVENT0("cc", "ProxyMain::SetNeedsRedraw");
+  DCHECK(IsMainThread());
+  channel_main_->SetNeedsRedrawOnImpl(damage_rect);
+}
+
+void ProxyMain::SetNextCommitWaitsForActivation() {
+  DCHECK(IsMainThread());
+  commit_waits_for_activation_ = true;
+}
+
+void ProxyMain::NotifyInputThrottledUntilCommit() {
+  DCHECK(IsMainThread());
+  channel_main_->SetInputThrottledUntilCommitOnImpl(true);
+}
+
+void ProxyMain::SetDeferCommits(bool defer_commits) {
+  DCHECK(IsMainThread());
+  if (defer_commits_ == defer_commits)
+    return;
+
+  defer_commits_ = defer_commits;
+  if (defer_commits_)
+    TRACE_EVENT_ASYNC_BEGIN0("cc", "ProxyMain::SetDeferCommits", this);
+  else
+    TRACE_EVENT_ASYNC_END0("cc", "ProxyMain::SetDeferCommits", this);
+
+  channel_main_->SetDeferCommitsOnImpl(defer_commits);
+}
+
+bool ProxyMain::CommitRequested() const {
+  DCHECK(IsMainThread());
+  // TODO(skyostil): Split this into something like CommitRequested() and
+  // CommitInProgress().
+  return current_pipeline_stage_ != NO_PIPELINE_STAGE ||
+         max_requested_pipeline_stage_ >= COMMIT_PIPELINE_STAGE;
+}
+
+bool ProxyMain::BeginMainFrameRequested() const {
+  DCHECK(IsMainThread());
+  return max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
+}
+
+void ProxyMain::MainThreadHasStoppedFlinging() {
+  DCHECK(IsMainThread());
+  channel_main_->MainThreadHasStoppedFlingingOnImpl();
+}
+
+void ProxyMain::Start() {
+  DCHECK(IsMainThread());
+  DCHECK(task_runner_provider_->HasImplThread());
+  DCHECK(channel_main_);
+
+  // Create LayerTreeHostImpl.
+  channel_main_->SynchronouslyInitializeImpl(
+      layer_tree_host_, std::move(external_begin_frame_source_));
+
+  started_ = true;
+}
+
+void ProxyMain::Stop() {
+  TRACE_EVENT0("cc", "ProxyMain::Stop");
+  DCHECK(IsMainThread());
+  DCHECK(started_);
+
+  channel_main_->SynchronouslyCloseImpl();
+
+  layer_tree_host_ = nullptr;
+  started_ = false;
+}
+
+bool ProxyMain::SupportsImplScrolling() const {
+  return true;
+}
+
+bool ProxyMain::MainFrameWillHappenForTesting() {
+  DCHECK(IsMainThread());
+  bool main_frame_will_happen = false;
+  {
+    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+    CompletionEvent completion;
+    channel_main_->MainFrameWillHappenOnImplForTesting(&completion,
+                                                       &main_frame_will_happen);
+    completion.Wait();
+  }
+  return main_frame_will_happen;
+}
+
+void ProxyMain::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
+  NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
+void ProxyMain::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
+  NOTREACHED() << "Only used by SingleProxyMain";
+}
+
+void ProxyMain::ReleaseOutputSurface() {
+  DCHECK(IsMainThread());
+  DCHECK(layer_tree_host_->output_surface_lost());
+
+  DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+  CompletionEvent completion;
+  channel_main_->ReleaseOutputSurfaceOnImpl(&completion);
+  completion.Wait();
+}
+
+void ProxyMain::UpdateTopControlsState(TopControlsState constraints,
+                                       TopControlsState current,
+                                       bool animate) {
+  DCHECK(IsMainThread());
+  channel_main_->UpdateTopControlsStateOnImpl(constraints, current, animate);
+}
+
+bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
+    CommitPipelineStage required_stage) {
+  DCHECK(IsMainThread());
+  DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
+  bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
+  max_requested_pipeline_stage_ =
+      std::max(max_requested_pipeline_stage_, required_stage);
+  if (already_posted)
+    return false;
+  channel_main_->SetNeedsCommitOnImpl();
+  return true;
+}
+
+bool ProxyMain::IsMainThread() const {
+  return task_runner_provider_->IsMainThread();
+}
+
+}  // namespace cc
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index fbe191d..edc2a22 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -5,56 +5,155 @@
 #ifndef CC_TREES_PROXY_MAIN_H_
 #define CC_TREES_PROXY_MAIN_H_
 
-#include "base/memory/weak_ptr.h"
+#include "base/macros.h"
 #include "cc/animation/animation_events.h"
 #include "cc/base/cc_export.h"
 #include "cc/debug/frame_timing_tracker.h"
+#include "cc/input/top_controls_state.h"
+#include "cc/output/output_surface.h"
 #include "cc/output/renderer_capabilities.h"
+#include "cc/trees/channel_main.h"
+#include "cc/trees/proxy.h"
 #include "cc/trees/proxy_common.h"
 
 namespace cc {
-class ThreadedChannel;
+class BeginFrameSource;
+class ChannelMain;
+class LayerTreeHost;
 
-// TODO(khushalsagar): The main side of ThreadProxy. It is currently defined as
-// an interface with the implementation provided by ThreadProxy and will be
-// made an independent class.
-// The methods added to this interface should only use the MainThreadOnly or
-// BlockedMainThread variables from ThreadProxy.
-// See crbug/527200.
-class CC_EXPORT ProxyMain {
+// This class aggregates all interactions that the impl side of the compositor
+// needs to have with the main side.
+// The class is created and lives on the main thread.
+class CC_EXPORT ProxyMain : public Proxy {
  public:
-  // TODO(khushalsagar): Make this ChannelMain*. When ProxyMain and
-  // ProxyImpl are split, ProxyImpl will be passed a reference to ChannelImpl
-  // at creation. Right now we just set it directly from ThreadedChannel
-  // when the impl side is initialized.
-  virtual void SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) = 0;
+  static scoped_ptr<ProxyMain> CreateThreaded(
+      LayerTreeHost* layer_tree_host,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
 
- protected:
-  virtual ~ProxyMain() {}
+  ~ProxyMain() override;
 
- private:
-  friend class ThreadedChannel;
-  // Callback for main side commands received from the Channel.
-  virtual void DidCompleteSwapBuffers() = 0;
-  virtual void SetRendererCapabilitiesMainCopy(
-      const RendererCapabilities& capabilities) = 0;
-  virtual void BeginMainFrameNotExpectedSoon() = 0;
-  virtual void DidCommitAndDrawFrame() = 0;
-  virtual void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue) = 0;
-  virtual void DidLoseOutputSurface() = 0;
-  virtual void RequestNewOutputSurface() = 0;
+  // Commits between the main and impl threads are processed through a pipeline
+  // with the following stages. For efficiency we can early out at any stage if
+  // we decide that no further processing is necessary.
+  enum CommitPipelineStage {
+    NO_PIPELINE_STAGE,
+    ANIMATE_PIPELINE_STAGE,
+    UPDATE_LAYERS_PIPELINE_STAGE,
+    COMMIT_PIPELINE_STAGE,
+  };
+
+  // Virtual for testing.
+  virtual void DidCompleteSwapBuffers();
+  virtual void SetRendererCapabilities(
+      const RendererCapabilities& capabilities);
+  virtual void BeginMainFrameNotExpectedSoon();
+  virtual void DidCommitAndDrawFrame();
+  virtual void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue);
+  virtual void DidLoseOutputSurface();
+  virtual void RequestNewOutputSurface();
   virtual void DidInitializeOutputSurface(
       bool success,
-      const RendererCapabilities& capabilities) = 0;
-  virtual void DidCompletePageScaleAnimation() = 0;
+      const RendererCapabilities& capabilities);
+  virtual void DidCompletePageScaleAnimation();
   virtual void PostFrameTimingEventsOnMain(
       scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
-      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) = 0;
+      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events);
   virtual void BeginMainFrame(
-      scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) = 0;
+      scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
 
-  // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split.
-  virtual base::WeakPtr<ProxyMain> GetMainWeakPtr() = 0;
+  ChannelMain* channel_main() const { return channel_main_.get(); }
+  CommitPipelineStage max_requested_pipeline_stage() const {
+    return max_requested_pipeline_stage_;
+  }
+  CommitPipelineStage current_pipeline_stage() const {
+    return current_pipeline_stage_;
+  }
+  CommitPipelineStage final_pipeline_stage() const {
+    return final_pipeline_stage_;
+  }
+
+ protected:
+  ProxyMain(LayerTreeHost* layer_tree_host,
+            TaskRunnerProvider* task_runner_provider,
+            scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ private:
+  friend class ProxyMainForTest;
+
+  // Proxy implementation.
+  void FinishAllRendering() override;
+  bool IsStarted() const override;
+  bool CommitToActiveTree() const override;
+  void SetOutputSurface(OutputSurface* output_surface) override;
+  void SetVisible(bool visible) override;
+  void SetThrottleFrameProduction(bool throttle) override;
+  const RendererCapabilities& GetRendererCapabilities() const override;
+  void SetNeedsAnimate() override;
+  void SetNeedsUpdateLayers() override;
+  void SetNeedsCommit() override;
+  void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
+  void SetNextCommitWaitsForActivation() override;
+  void NotifyInputThrottledUntilCommit() override;
+  void SetDeferCommits(bool defer_commits) override;
+  bool CommitRequested() const override;
+  bool BeginMainFrameRequested() const override;
+  void MainThreadHasStoppedFlinging() override;
+  void Start() override;
+  void Stop() override;
+  bool SupportsImplScrolling() const override;
+  bool MainFrameWillHappenForTesting() override;
+  void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
+  void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) override;
+  void ReleaseOutputSurface() override;
+  void UpdateTopControlsState(TopControlsState constraints,
+                              TopControlsState current,
+                              bool animate) override;
+
+  // This sets the channel used by ProxyMain to communicate with ProxyImpl.
+  void SetChannel(scoped_ptr<ChannelMain> channel_main);
+
+  // Returns |true| if the request was actually sent, |false| if one was
+  // already outstanding.
+  bool SendCommitRequestToImplThreadIfNeeded(
+      CommitPipelineStage required_stage);
+  bool IsMainThread() const;
+
+  LayerTreeHost* layer_tree_host_;
+
+  TaskRunnerProvider* task_runner_provider_;
+
+  const int layer_tree_host_id_;
+
+  // The furthest pipeline stage which has been requested for the next
+  // commit.
+  CommitPipelineStage max_requested_pipeline_stage_;
+  // The commit pipeline stage that is currently being processed.
+  CommitPipelineStage current_pipeline_stage_;
+  // The commit pipeline stage at which processing for the current commit
+  // will stop. Only valid while we are executing the pipeline (i.e.,
+  // |current_pipeline_stage| is set to a pipeline stage).
+  CommitPipelineStage final_pipeline_stage_;
+
+  bool commit_waits_for_activation_;
+
+  // Set when the Proxy is started using Proxy::Start() and reset when it is
+  // stopped using Proxy::Stop().
+  bool started_;
+
+  bool defer_commits_;
+
+  RendererCapabilities renderer_capabilities_;
+
+  // This holds a valid value only until ProxyImpl is created on the impl thread
+  // with InitializeImplOnImpl().
+  // TODO(khushalsagar): Remove the use of this temporary variable.
+  // See crbug/567930.
+  scoped_ptr<BeginFrameSource> external_begin_frame_source_;
+
+  scoped_ptr<ChannelMain> channel_main_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProxyMain);
 };
 
 }  // namespace cc
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
deleted file mode 100644
index 7e09d7a..0000000
--- a/cc/trees/thread_proxy.cc
+++ /dev/null
@@ -1,1190 +0,0 @@
-// Copyright 2011 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/trees/thread_proxy.h"
-
-#include <algorithm>
-#include <string>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/trace_event/trace_event_synthetic_delay.h"
-#include "cc/debug/benchmark_instrumentation.h"
-#include "cc/debug/devtools_instrumentation.h"
-#include "cc/input/input_handler.h"
-#include "cc/input/top_controls_manager.h"
-#include "cc/output/context_provider.h"
-#include "cc/output/output_surface.h"
-#include "cc/output/swap_promise.h"
-#include "cc/quads/draw_quad.h"
-#include "cc/scheduler/commit_earlyout_reason.h"
-#include "cc/scheduler/compositor_timing_history.h"
-#include "cc/scheduler/scheduler.h"
-#include "cc/trees/blocking_task_runner.h"
-#include "cc/trees/layer_tree_host.h"
-#include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/scoped_abort_remaining_swap_promises.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-
-namespace cc {
-
-namespace {
-
-// Measured in seconds.
-const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
-
-unsigned int nextBeginFrameId = 0;
-
-}  // namespace
-
-struct ThreadProxy::SchedulerStateRequest {
-  CompletionEvent completion;
-  scoped_ptr<base::Value> state;
-};
-
-scoped_ptr<Proxy> ThreadProxy::Create(
-    LayerTreeHost* layer_tree_host,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
-  return make_scoped_ptr(
-      new ThreadProxy(layer_tree_host, task_runner_provider,
-                      std::move(external_begin_frame_source)));
-}
-
-ThreadProxy::ThreadProxy(
-    LayerTreeHost* layer_tree_host,
-    TaskRunnerProvider* task_runner_provider,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source)
-    : task_runner_provider_(task_runner_provider),
-      main_thread_only_vars_unsafe_(this, layer_tree_host),
-      compositor_thread_vars_unsafe_(
-          this,
-          layer_tree_host->id(),
-          layer_tree_host->rendering_stats_instrumentation(),
-          std::move(external_begin_frame_source)) {
-  TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
-  DCHECK(task_runner_provider_);
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(this->main().layer_tree_host);
-  // TODO(khushalsagar): Move this to LayerTreeHost#InitializeThreaded once
-  // ThreadProxy is split. LayerTreeHost creates the channel and passes it to
-  // ProxyMain#SetChannel.
-  SetChannel(ThreadedChannel::Create(this, task_runner_provider_));
-}
-
-ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
-                                            LayerTreeHost* layer_tree_host)
-    : layer_tree_host_id(layer_tree_host->id()),
-      layer_tree_host(layer_tree_host),
-      max_requested_pipeline_stage(NO_PIPELINE_STAGE),
-      current_pipeline_stage(NO_PIPELINE_STAGE),
-      final_pipeline_stage(NO_PIPELINE_STAGE),
-      commit_waits_for_activation(false),
-      started(false),
-      prepare_tiles_pending(false),
-      defer_commits(false),
-      weak_factory(proxy) {}
-
-ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
-
-ThreadProxy::BlockedMainCommitOnly::BlockedMainCommitOnly()
-    : layer_tree_host(nullptr) {}
-
-ThreadProxy::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
-
-ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(
-    ThreadProxy* proxy,
-    int layer_tree_host_id,
-    RenderingStatsInstrumentation* rendering_stats_instrumentation,
-    scoped_ptr<BeginFrameSource> external_begin_frame_source)
-    : layer_tree_host_id(layer_tree_host_id),
-      next_commit_waits_for_activation(false),
-      commit_completion_event(nullptr),
-      next_frame_is_newly_committed_frame(false),
-      inside_draw(false),
-      input_throttled_until_commit(false),
-      smoothness_priority_expiration_notifier(
-          proxy->task_runner_provider()
-              ->ImplThreadTaskRunner(),
-          base::Bind(&ThreadProxy::RenewTreePriority, base::Unretained(proxy)),
-          base::TimeDelta::FromMilliseconds(
-              kSmoothnessTakesPriorityExpirationDelay * 1000)),
-      external_begin_frame_source(std::move(external_begin_frame_source)),
-      rendering_stats_instrumentation(rendering_stats_instrumentation),
-      weak_factory(proxy) {}
-
-ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
-
-ThreadProxy::~ThreadProxy() {
-  TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(!main().started);
-}
-
-void ThreadProxy::SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) {
-  threaded_channel_ = std::move(threaded_channel);
-  main().channel_main = threaded_channel_.get();
-}
-
-void ThreadProxy::FinishAllRendering() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(!main().defer_commits);
-
-  // Make sure all GL drawing is finished on the impl thread.
-  DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-  CompletionEvent completion;
-  main().channel_main->FinishAllRenderingOnImpl(&completion);
-  completion.Wait();
-}
-
-bool ThreadProxy::IsStarted() const {
-  DCHECK(task_runner_provider_->IsMainThread());
-  return main().started;
-}
-
-bool ThreadProxy::CommitToActiveTree() const {
-  // With ThreadProxy, we use a pending tree and activate it once it's ready to
-  // draw to allow input to modify the active tree and draw during raster.
-  return false;
-}
-
-void ThreadProxy::SetVisible(bool visible) {
-  TRACE_EVENT1("cc", "ThreadProxy::SetVisible", "visible", visible);
-  main().channel_main->SetVisibleOnImpl(visible);
-}
-
-void ThreadProxy::SetVisibleOnImpl(bool visible) {
-  TRACE_EVENT1("cc", "ThreadProxy::SetVisibleOnImplThread", "visible", visible);
-  impl().layer_tree_host_impl->SetVisible(visible);
-  impl().scheduler->SetVisible(visible);
-}
-
-void ThreadProxy::SetThrottleFrameProduction(bool throttle) {
-  TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProduction", "throttle",
-               throttle);
-  main().channel_main->SetThrottleFrameProductionOnImpl(throttle);
-}
-
-void ThreadProxy::SetThrottleFrameProductionOnImpl(bool throttle) {
-  TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProductionOnImplThread",
-               "throttle", throttle);
-  impl().scheduler->SetThrottleFrameProduction(throttle);
-}
-
-void ThreadProxy::DidLoseOutputSurface() {
-  TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface");
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->DidLoseOutputSurface();
-}
-
-void ThreadProxy::RequestNewOutputSurface() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->RequestNewOutputSurface();
-}
-
-void ThreadProxy::SetOutputSurface(OutputSurface* output_surface) {
-  main().channel_main->InitializeOutputSurfaceOnImpl(output_surface);
-}
-
-void ThreadProxy::ReleaseOutputSurface() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(main().layer_tree_host->output_surface_lost());
-
-  DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-  CompletionEvent completion;
-  main().channel_main->ReleaseOutputSurfaceOnImpl(&completion);
-  completion.Wait();
-}
-
-void ThreadProxy::DidInitializeOutputSurface(
-    bool success,
-    const RendererCapabilities& capabilities) {
-  TRACE_EVENT0("cc", "ThreadProxy::DidInitializeOutputSurface");
-  DCHECK(task_runner_provider_->IsMainThread());
-
-  if (!success) {
-    main().layer_tree_host->DidFailToInitializeOutputSurface();
-    return;
-  }
-  main().renderer_capabilities_main_thread_copy = capabilities;
-  main().layer_tree_host->DidInitializeOutputSurface();
-}
-
-void ThreadProxy::SetRendererCapabilitiesMainCopy(
-    const RendererCapabilities& capabilities) {
-  main().renderer_capabilities_main_thread_copy = capabilities;
-}
-
-bool ThreadProxy::SendCommitRequestToImplThreadIfNeeded(
-    CommitPipelineStage required_stage) {
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
-  bool already_posted =
-      main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
-  main().max_requested_pipeline_stage =
-      std::max(main().max_requested_pipeline_stage, required_stage);
-  if (already_posted)
-    return false;
-  main().channel_main->SetNeedsCommitOnImpl();
-  return true;
-}
-
-void ThreadProxy::SetNeedsCommitOnImpl() {
-  SetNeedsCommitOnImplThread();
-}
-
-void ThreadProxy::DidCompletePageScaleAnimation() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->DidCompletePageScaleAnimation();
-}
-
-const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(!main().layer_tree_host->output_surface_lost());
-  return main().renderer_capabilities_main_thread_copy;
-}
-
-void ThreadProxy::SetNeedsAnimate() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
-    TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsAnimate",
-                         TRACE_EVENT_SCOPE_THREAD);
-  }
-}
-
-void ThreadProxy::SetNeedsUpdateLayers() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  // If we are currently animating, make sure we also update the layers.
-  if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
-    main().final_pipeline_stage =
-        std::max(main().final_pipeline_stage, UPDATE_LAYERS_PIPELINE_STAGE);
-    return;
-  }
-  if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
-    TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsUpdateLayers",
-                         TRACE_EVENT_SCOPE_THREAD);
-  }
-}
-
-void ThreadProxy::SetNeedsCommit() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  // If we are currently animating, make sure we don't skip the commit. Note
-  // that requesting a commit during the layer update stage means we need to
-  // schedule another full commit.
-  if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
-    main().final_pipeline_stage =
-        std::max(main().final_pipeline_stage, COMMIT_PIPELINE_STAGE);
-    return;
-  }
-  if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
-    TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsCommit",
-                         TRACE_EVENT_SCOPE_THREAD);
-  }
-}
-
-void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().channel_impl->SetRendererCapabilitiesMainCopy(
-      impl()
-          .layer_tree_host_impl->GetRendererCapabilities()
-          .MainThreadCapabilities());
-}
-
-void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
-  TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().channel_impl->DidLoseOutputSurface();
-  impl().scheduler->DidLoseOutputSurface();
-}
-
-void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
-                                        base::TimeDelta interval) {
-  impl().scheduler->CommitVSyncParameters(timebase, interval);
-}
-
-void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
-  impl().scheduler->SetEstimatedParentDrawTime(draw_time);
-}
-
-void ThreadProxy::DidSwapBuffersOnImplThread() {
-  impl().scheduler->DidSwapBuffers();
-}
-
-void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
-  TRACE_EVENT0("cc,benchmark",
-               "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->DidSwapBuffersComplete();
-  impl().channel_impl->DidCompleteSwapBuffers();
-}
-
-void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
-  impl().layer_tree_host_impl->WillBeginImplFrame(args);
-  if (impl().last_processed_begin_main_frame_args.IsValid()) {
-    // Last processed begin main frame args records the frame args that we sent
-    // to the main thread for the last frame that we've processed. If that is
-    // set, that means the current frame is one past the frame in which we've
-    // finished the processing.
-    impl().layer_tree_host_impl->RecordMainFrameTiming(
-        impl().last_processed_begin_main_frame_args, args);
-    impl().last_processed_begin_main_frame_args = BeginFrameArgs();
-  }
-}
-
-void ThreadProxy::OnResourcelessSoftareDrawStateChanged(
-    bool resourceless_draw) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetResourcelessSoftareDraw(resourceless_draw);
-}
-
-void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
-  TRACE_EVENT1(
-      "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetCanDraw(can_draw);
-}
-
-void ThreadProxy::NotifyReadyToActivate() {
-  TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
-  impl().scheduler->NotifyReadyToActivate();
-}
-
-void ThreadProxy::NotifyReadyToDraw() {
-  TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToDraw");
-  impl().scheduler->NotifyReadyToDraw();
-}
-
-void ThreadProxy::SetNeedsCommitOnImplThread() {
-  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetNeedsBeginMainFrame();
-}
-
-void ThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
-  TRACE_EVENT1("cc", "ThreadProxy::SetVideoNeedsBeginFrames",
-               "needs_begin_frames", needs_begin_frames);
-  DCHECK(task_runner_provider_->IsImplThread());
-  // In tests the layer tree is destroyed after the scheduler is.
-  if (impl().scheduler)
-    impl().scheduler->SetVideoNeedsBeginFrames(needs_begin_frames);
-}
-
-void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
-    scoped_ptr<AnimationEventsVector> events) {
-  TRACE_EVENT0("cc",
-               "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().channel_impl->SetAnimationEvents(std::move(events));
-}
-
-bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
-
-void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
-  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().channel_main->SetNeedsRedrawOnImpl(damage_rect);
-}
-
-void ThreadProxy::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  SetNeedsRedrawRectOnImplThread(damage_rect);
-}
-
-void ThreadProxy::SetNextCommitWaitsForActivation() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().commit_waits_for_activation = true;
-}
-
-void ThreadProxy::SetDeferCommits(bool defer_commits) {
-  DCHECK(task_runner_provider_->IsMainThread());
-  if (main().defer_commits == defer_commits)
-    return;
-
-  main().defer_commits = defer_commits;
-  if (main().defer_commits)
-    TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
-  else
-    TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
-
-  main().channel_main->SetDeferCommitsOnImpl(defer_commits);
-}
-
-void ThreadProxy::SetDeferCommitsOnImpl(bool defer_commits) const {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetDeferCommits(defer_commits);
-}
-
-bool ThreadProxy::CommitRequested() const {
-  DCHECK(task_runner_provider_->IsMainThread());
-  // TODO(skyostil): Split this into something like CommitRequested() and
-  // CommitInProgress().
-  return main().current_pipeline_stage != NO_PIPELINE_STAGE ||
-         main().max_requested_pipeline_stage >= COMMIT_PIPELINE_STAGE;
-}
-
-bool ThreadProxy::BeginMainFrameRequested() const {
-  DCHECK(task_runner_provider_->IsMainThread());
-  return main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
-}
-
-void ThreadProxy::SetNeedsRedrawOnImplThread() {
-  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetNeedsRedraw();
-}
-
-void ThreadProxy::SetNeedsOneBeginImplFrameOnImplThread() {
-  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsOneBeginImplFrameOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetNeedsOneBeginImplFrame();
-}
-
-void ThreadProxy::SetNeedsPrepareTilesOnImplThread() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->SetNeedsPrepareTiles();
-}
-
-void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
-  SetNeedsRedrawOnImplThread();
-}
-
-void ThreadProxy::MainThreadHasStoppedFlinging() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().channel_main->MainThreadHasStoppedFlingingOnImpl();
-}
-
-void ThreadProxy::MainThreadHasStoppedFlingingOnImpl() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
-}
-
-void ThreadProxy::NotifyInputThrottledUntilCommit() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().channel_main->SetInputThrottledUntilCommitOnImpl(true);
-}
-
-void ThreadProxy::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  if (is_throttled == impl().input_throttled_until_commit)
-    return;
-  impl().input_throttled_until_commit = is_throttled;
-  RenewTreePriority();
-}
-
-ThreadProxy::MainThreadOnly& ThreadProxy::main() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  return main_thread_only_vars_unsafe_;
-}
-const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
-  DCHECK(task_runner_provider_->IsMainThread());
-  return main_thread_only_vars_unsafe_;
-}
-
-ThreadProxy::BlockedMainCommitOnly& ThreadProxy::blocked_main_commit() {
-  DCHECK(impl().commit_completion_event);
-  DCHECK(task_runner_provider_->IsMainThreadBlocked());
-  return main_thread_blocked_commit_vars_unsafe_;
-}
-
-ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  return compositor_thread_vars_unsafe_;
-}
-
-const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
-  DCHECK(task_runner_provider_->IsImplThread());
-  return compositor_thread_vars_unsafe_;
-}
-
-void ThreadProxy::Start() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(task_runner_provider_->HasImplThread());
-
-  // Create LayerTreeHostImpl.
-  DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-  CompletionEvent completion;
-  main().channel_main->InitializeImplOnImpl(&completion,
-                                            main().layer_tree_host);
-  completion.Wait();
-
-  main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
-
-  main().started = true;
-}
-
-void ThreadProxy::Stop() {
-  TRACE_EVENT0("cc", "ThreadProxy::Stop");
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK(main().started);
-
-  // Synchronously finishes pending GL operations and deletes the impl.
-  // The two steps are done as separate post tasks, so that tasks posted
-  // by the GL implementation due to the Finish can be executed by the
-  // renderer before shutting it down.
-  {
-    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-    CompletionEvent completion;
-    main().channel_main->FinishGLOnImpl(&completion);
-    completion.Wait();
-  }
-  {
-    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-
-    CompletionEvent completion;
-    main().channel_main->LayerTreeHostClosedOnImpl(&completion);
-    completion.Wait();
-  }
-
-  main().weak_factory.InvalidateWeakPtrs();
-  main().layer_tree_host = nullptr;
-  main().started = false;
-}
-
-bool ThreadProxy::SupportsImplScrolling() const {
-  return true;
-}
-
-void ThreadProxy::FinishAllRenderingOnImpl(CompletionEvent* completion) {
-  TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().layer_tree_host_impl->FinishAllRendering();
-  completion->Signal();
-}
-
-void ThreadProxy::ScheduledActionSendBeginMainFrame(
-    const BeginFrameArgs& args) {
-  unsigned int begin_frame_id = nextBeginFrameId++;
-  benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
-      benchmark_instrumentation::kSendBeginFrame, begin_frame_id);
-  scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
-      new BeginMainFrameAndCommitState);
-  begin_main_frame_state->begin_frame_id = begin_frame_id;
-  begin_main_frame_state->begin_frame_args = args;
-  begin_main_frame_state->scroll_info =
-      impl().layer_tree_host_impl->ProcessScrollDeltas();
-  begin_main_frame_state->memory_allocation_limit_bytes =
-      impl().layer_tree_host_impl->memory_allocation_limit_bytes();
-  begin_main_frame_state->evicted_ui_resources =
-      impl().layer_tree_host_impl->EvictedUIResourcesExist();
-  // TODO(vmpstr): This needs to be fixed if
-  // main_frame_before_activation_enabled is set, since we might run this code
-  // twice before recording a duration. crbug.com/469824
-  impl().last_begin_main_frame_args = begin_main_frame_state->begin_frame_args;
-  impl().channel_impl->BeginMainFrame(std::move(begin_main_frame_state));
-  devtools_instrumentation::DidRequestMainThreadFrame(
-      impl().layer_tree_host_id);
-}
-
-void ThreadProxy::SendBeginMainFrameNotExpectedSoon() {
-  impl().channel_impl->BeginMainFrameNotExpectedSoon();
-}
-
-void ThreadProxy::BeginMainFrame(
-    scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
-  benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
-      benchmark_instrumentation::kDoBeginFrame,
-      begin_main_frame_state->begin_frame_id);
-
-  base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
-
-  TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
-  DCHECK(task_runner_provider_->IsMainThread());
-  DCHECK_EQ(NO_PIPELINE_STAGE, main().current_pipeline_stage);
-
-  if (main().defer_commits) {
-    TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
-                         TRACE_EVENT_SCOPE_THREAD);
-    main().channel_main->BeginMainFrameAbortedOnImpl(
-        CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
-        begin_main_frame_start_time);
-    return;
-  }
-
-  // If the commit finishes, LayerTreeHost will transfer its swap promises to
-  // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
-  // remaining swap promises.
-  ScopedAbortRemainingSwapPromises swap_promise_checker(main().layer_tree_host);
-
-  main().final_pipeline_stage = main().max_requested_pipeline_stage;
-  main().max_requested_pipeline_stage = NO_PIPELINE_STAGE;
-
-  if (!main().layer_tree_host->visible()) {
-    TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
-    main().channel_main->BeginMainFrameAbortedOnImpl(
-        CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
-    return;
-  }
-
-  if (main().layer_tree_host->output_surface_lost()) {
-    TRACE_EVENT_INSTANT0(
-        "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
-    main().channel_main->BeginMainFrameAbortedOnImpl(
-        CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
-        begin_main_frame_start_time);
-    return;
-  }
-
-  main().current_pipeline_stage = ANIMATE_PIPELINE_STAGE;
-
-  main().layer_tree_host->ApplyScrollAndScale(
-      begin_main_frame_state->scroll_info.get());
-
-  main().layer_tree_host->WillBeginMainFrame();
-
-  main().layer_tree_host->BeginMainFrame(
-      begin_main_frame_state->begin_frame_args);
-  main().layer_tree_host->AnimateLayers(
-      begin_main_frame_state->begin_frame_args.frame_time);
-
-  // Recreate all UI resources if there were evicted UI resources when the impl
-  // thread initiated the commit.
-  if (begin_main_frame_state->evicted_ui_resources)
-    main().layer_tree_host->RecreateUIResources();
-
-  main().layer_tree_host->RequestMainFrameUpdate();
-  TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
-
-  bool can_cancel_this_commit =
-      main().final_pipeline_stage < COMMIT_PIPELINE_STAGE &&
-      !begin_main_frame_state->evicted_ui_resources;
-
-  main().current_pipeline_stage = UPDATE_LAYERS_PIPELINE_STAGE;
-  bool should_update_layers =
-      main().final_pipeline_stage >= UPDATE_LAYERS_PIPELINE_STAGE;
-  bool updated = should_update_layers && main().layer_tree_host->UpdateLayers();
-
-  main().layer_tree_host->WillCommit();
-  devtools_instrumentation::ScopedCommitTrace commit_task(
-      main().layer_tree_host->id());
-
-  main().current_pipeline_stage = COMMIT_PIPELINE_STAGE;
-  if (!updated && can_cancel_this_commit) {
-    TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
-    main().channel_main->BeginMainFrameAbortedOnImpl(
-        CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
-
-    // Although the commit is internally aborted, this is because it has been
-    // detected to be a no-op.  From the perspective of an embedder, this commit
-    // went through, and input should no longer be throttled, etc.
-    main().current_pipeline_stage = NO_PIPELINE_STAGE;
-    main().layer_tree_host->CommitComplete();
-    main().layer_tree_host->DidBeginMainFrame();
-    main().layer_tree_host->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
-    return;
-  }
-
-  // Notify the impl thread that the main thread is ready to commit. This will
-  // begin the commit process, which is blocking from the main thread's
-  // point of view, but asynchronously performed on the impl thread,
-  // coordinated by the Scheduler.
-  {
-    TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
-
-    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-
-    // This CapturePostTasks should be destroyed before CommitComplete() is
-    // called since that goes out to the embedder, and we want the embedder
-    // to receive its callbacks before that.
-    BlockingTaskRunner::CapturePostTasks blocked(
-        task_runner_provider_->blocking_main_thread_task_runner());
-
-    CompletionEvent completion;
-    main().channel_main->StartCommitOnImpl(&completion, main().layer_tree_host,
-                                           begin_main_frame_start_time,
-                                           main().commit_waits_for_activation);
-    completion.Wait();
-    main().commit_waits_for_activation = false;
-  }
-
-  main().current_pipeline_stage = NO_PIPELINE_STAGE;
-  main().layer_tree_host->CommitComplete();
-  main().layer_tree_host->DidBeginMainFrame();
-}
-
-void ThreadProxy::BeginMainFrameNotExpectedSoon() {
-  TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameNotExpectedSoon");
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->BeginMainFrameNotExpectedSoon();
-}
-
-void ThreadProxy::StartCommitOnImpl(CompletionEvent* completion,
-                                    LayerTreeHost* layer_tree_host,
-                                    base::TimeTicks main_thread_start_time,
-                                    bool hold_commit_for_activation) {
-  TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
-  DCHECK(!impl().commit_completion_event);
-  DCHECK(task_runner_provider_->IsImplThread() &&
-         task_runner_provider_->IsMainThreadBlocked());
-  DCHECK(impl().scheduler);
-  DCHECK(impl().scheduler->CommitPending());
-
-  if (hold_commit_for_activation) {
-    // This commit may be aborted. Store the value for
-    // hold_commit_for_activation so that whenever the next commit is started,
-    // the main thread will be unblocked only after pending tree activation.
-    impl().next_commit_waits_for_activation = hold_commit_for_activation;
-  }
-
-  if (!impl().layer_tree_host_impl) {
-    TRACE_EVENT_INSTANT0(
-        "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
-    completion->Signal();
-    return;
-  }
-
-  // Ideally, we should inform to impl thread when BeginMainFrame is started.
-  // But, we can avoid a PostTask in here.
-  impl().scheduler->NotifyBeginMainFrameStarted(main_thread_start_time);
-  impl().commit_completion_event = completion;
-  DCHECK(!blocked_main_commit().layer_tree_host);
-  blocked_main_commit().layer_tree_host = layer_tree_host;
-  impl().scheduler->NotifyReadyToCommit();
-}
-
-void ThreadProxy::BeginMainFrameAbortedOnImpl(
-    CommitEarlyOutReason reason,
-    base::TimeTicks main_thread_start_time) {
-  TRACE_EVENT1("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread", "reason",
-               CommitEarlyOutReasonToString(reason));
-  DCHECK(task_runner_provider_->IsImplThread());
-  DCHECK(impl().scheduler);
-  DCHECK(impl().scheduler->CommitPending());
-  DCHECK(!impl().layer_tree_host_impl->pending_tree());
-
-  if (CommitEarlyOutHandledCommit(reason)) {
-    SetInputThrottledUntilCommitOnImpl(false);
-    impl().last_processed_begin_main_frame_args =
-        impl().last_begin_main_frame_args;
-  }
-  impl().layer_tree_host_impl->BeginMainFrameAborted(reason);
-  impl().scheduler->NotifyBeginMainFrameStarted(main_thread_start_time);
-  impl().scheduler->BeginMainFrameAborted(reason);
-}
-
-void ThreadProxy::ScheduledActionCommit() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
-  DCHECK(task_runner_provider_->IsImplThread());
-  DCHECK(task_runner_provider_->IsMainThreadBlocked());
-  DCHECK(impl().commit_completion_event);
-  DCHECK(blocked_main_commit().layer_tree_host);
-
-  impl().layer_tree_host_impl->BeginCommit();
-  blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
-      impl().layer_tree_host_impl.get());
-
-  // Remove the LayerTreeHost reference before the completion event is signaled
-  // and cleared. This is necessary since blocked_main_commit() allows access
-  // only while we have the completion event to ensure the main thread is
-  // blocked for a commit.
-  blocked_main_commit().layer_tree_host = nullptr;
-
-  if (impl().next_commit_waits_for_activation) {
-    // For some layer types in impl-side painting, the commit is held until
-    // the sync tree is activated.  It's also possible that the
-    // sync tree has already activated if there was no work to be done.
-    TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
-  } else {
-    impl().commit_completion_event->Signal();
-    impl().commit_completion_event = nullptr;
-  }
-
-  impl().scheduler->DidCommit();
-
-  // Delay this step until afer the main thread has been released as it's
-  // often a good bit of work to update the tree and prepare the new frame.
-  impl().layer_tree_host_impl->CommitComplete();
-
-  SetInputThrottledUntilCommitOnImpl(false);
-
-  impl().next_frame_is_newly_committed_frame = true;
-}
-
-void ThreadProxy::ScheduledActionActivateSyncTree() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivateSyncTree");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().layer_tree_host_impl->ActivateSyncTree();
-}
-
-void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().channel_impl->RequestNewOutputSurface();
-}
-
-DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) {
-  TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
-  DrawResult result;
-
-  DCHECK(task_runner_provider_->IsImplThread());
-  DCHECK(impl().layer_tree_host_impl.get());
-
-  base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
-
-  if (impl().layer_tree_host_impl->pending_tree()) {
-    bool update_lcd_text = false;
-    impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties(
-        update_lcd_text);
-  }
-
-  // This method is called on a forced draw, regardless of whether we are able
-  // to produce a frame, as the calling site on main thread is blocked until its
-  // request completes, and we signal completion here. If CanDraw() is false, we
-  // will indicate success=false to the caller, but we must still signal
-  // completion to avoid deadlock.
-
-  // We guard PrepareToDraw() with CanDraw() because it always returns a valid
-  // frame, so can only be used when such a frame is possible. Since
-  // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
-  // CanDraw() as well.
-
-  LayerTreeHostImpl::FrameData frame;
-  bool draw_frame = false;
-
-  if (impl().layer_tree_host_impl->CanDraw()) {
-    result = impl().layer_tree_host_impl->PrepareToDraw(&frame);
-    draw_frame = forced_draw || result == DRAW_SUCCESS;
-  } else {
-    result = DRAW_ABORTED_CANT_DRAW;
-  }
-
-  if (draw_frame) {
-    impl().layer_tree_host_impl->DrawLayers(&frame);
-    result = DRAW_SUCCESS;
-  } else {
-    DCHECK_NE(DRAW_SUCCESS, result);
-  }
-  impl().layer_tree_host_impl->DidDrawAllLayers(frame);
-
-  bool start_ready_animations = draw_frame;
-  impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
-
-  if (draw_frame)
-    impl().layer_tree_host_impl->SwapBuffers(frame);
-
-  // Tell the main thread that the the newly-commited frame was drawn.
-  if (impl().next_frame_is_newly_committed_frame) {
-    impl().next_frame_is_newly_committed_frame = false;
-    impl().channel_impl->DidCommitAndDrawFrame();
-  }
-
-  DCHECK_NE(INVALID_RESULT, result);
-  return result;
-}
-
-void ThreadProxy::ScheduledActionPrepareTiles() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionPrepareTiles");
-  impl().layer_tree_host_impl->PrepareTiles();
-}
-
-DrawResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
-
-  // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
-  // handle DRAW_ABORTED_CANT_DRAW.  Moreover, the scheduler should
-  // never generate this call when it can't draw.
-  DCHECK(impl().layer_tree_host_impl->CanDraw());
-
-  bool forced_draw = false;
-  return DrawSwapInternal(forced_draw);
-}
-
-DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
-  bool forced_draw = true;
-  return DrawSwapInternal(forced_draw);
-}
-
-void ThreadProxy::ScheduledActionInvalidateOutputSurface() {
-  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionInvalidateOutputSurface");
-  DCHECK(impl().layer_tree_host_impl->output_surface());
-  impl().layer_tree_host_impl->output_surface()->Invalidate();
-}
-
-void ThreadProxy::DidFinishImplFrame() {
-  impl().layer_tree_host_impl->DidFinishImplFrame();
-}
-
-void ThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
-  NOTREACHED() << "Only used by SingleThreadProxy";
-}
-
-void ThreadProxy::SetAuthoritativeVSyncInterval(
-    const base::TimeDelta& interval) {
-  NOTREACHED() << "Only used by SingleThreadProxy";
-}
-
-void ThreadProxy::DidCommitAndDrawFrame() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->DidCommitAndDrawFrame();
-}
-
-void ThreadProxy::DidCompleteSwapBuffers() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->DidCompleteSwapBuffers();
-}
-
-void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
-  TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->SetAnimationEvents(std::move(events));
-}
-
-void ThreadProxy::InitializeImplOnImpl(CompletionEvent* completion,
-                                       LayerTreeHost* layer_tree_host) {
-  TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  DCHECK(task_runner_provider_->IsMainThreadBlocked());
-  DCHECK(layer_tree_host);
-
-  // TODO(khushalsagar): ThreadedChannel will create ProxyImpl here and pass a
-  // reference to itself.
-  impl().channel_impl = threaded_channel_.get();
-
-  impl().layer_tree_host_impl = layer_tree_host->CreateLayerTreeHostImpl(this);
-
-  SchedulerSettings scheduler_settings(
-      layer_tree_host->settings().ToSchedulerSettings());
-
-  scoped_ptr<CompositorTimingHistory> compositor_timing_history(
-      new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA,
-                                  impl().rendering_stats_instrumentation));
-
-  impl().scheduler =
-      Scheduler::Create(this, scheduler_settings, impl().layer_tree_host_id,
-                        task_runner_provider_->ImplThreadTaskRunner(),
-                        impl().external_begin_frame_source.get(),
-                        std::move(compositor_timing_history));
-
-  DCHECK_EQ(impl().scheduler->visible(),
-            impl().layer_tree_host_impl->visible());
-  impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
-  completion->Signal();
-}
-
-void ThreadProxy::InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {
-  TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-
-  LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get();
-  bool success = host_impl->InitializeRenderer(output_surface);
-  RendererCapabilities capabilities;
-  if (success) {
-    capabilities =
-        host_impl->GetRendererCapabilities().MainThreadCapabilities();
-  }
-
-  impl().channel_impl->DidInitializeOutputSurface(success, capabilities);
-
-  if (success)
-    impl().scheduler->DidCreateAndInitializeOutputSurface();
-}
-
-void ThreadProxy::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
-  DCHECK(task_runner_provider_->IsImplThread());
-
-  // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call
-  // LayerTreeHost::DidLoseOutputSurface since it already knows.
-  impl().scheduler->DidLoseOutputSurface();
-  impl().layer_tree_host_impl->ReleaseOutputSurface();
-  completion->Signal();
-}
-
-void ThreadProxy::FinishGLOnImpl(CompletionEvent* completion) {
-  TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  if (impl().layer_tree_host_impl->output_surface()) {
-    ContextProvider* context_provider =
-        impl().layer_tree_host_impl->output_surface()->context_provider();
-    if (context_provider)
-      context_provider->ContextGL()->Finish();
-  }
-  completion->Signal();
-}
-
-void ThreadProxy::LayerTreeHostClosedOnImpl(CompletionEvent* completion) {
-  TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-  DCHECK(task_runner_provider_->IsMainThreadBlocked());
-  impl().scheduler = nullptr;
-  impl().external_begin_frame_source = nullptr;
-  impl().layer_tree_host_impl = nullptr;
-  impl().weak_factory.InvalidateWeakPtrs();
-  // We need to explicitly shutdown the notifier to destroy any weakptrs it is
-  // holding while still on the compositor thread. This also ensures any
-  // callbacks holding a ThreadProxy pointer are cancelled.
-  impl().smoothness_priority_expiration_notifier.Shutdown();
-  completion->Signal();
-}
-
-bool ThreadProxy::MainFrameWillHappenForTesting() {
-  DCHECK(task_runner_provider_->IsMainThread());
-  bool main_frame_will_happen = false;
-  {
-    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-    CompletionEvent completion;
-    main().channel_main->MainFrameWillHappenOnImplForTesting(
-        &completion, &main_frame_will_happen);
-    completion.Wait();
-  }
-  return main_frame_will_happen;
-}
-
-void ThreadProxy::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
-  NOTREACHED() << "Only used by SingleThreadProxy";
-}
-
-void ThreadProxy::MainFrameWillHappenOnImplForTesting(
-    CompletionEvent* completion,
-    bool* main_frame_will_happen) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  if (impl().layer_tree_host_impl->output_surface()) {
-    *main_frame_will_happen = impl().scheduler->MainFrameForTestingWillHappen();
-  } else {
-    *main_frame_will_happen = false;
-  }
-  completion->Signal();
-}
-
-void ThreadProxy::RenewTreePriority() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  bool smoothness_takes_priority =
-      impl().layer_tree_host_impl->pinch_gesture_active() ||
-      impl().layer_tree_host_impl->page_scale_animation_active() ||
-      impl().layer_tree_host_impl->IsActivelyScrolling();
-
-  // Schedule expiration if smoothness currently takes priority.
-  if (smoothness_takes_priority)
-    impl().smoothness_priority_expiration_notifier.Schedule();
-
-  // We use the same priority for both trees by default.
-  TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
-
-  // Smoothness takes priority if we have an expiration for it scheduled.
-  if (impl().smoothness_priority_expiration_notifier.HasPendingNotification())
-    tree_priority = SMOOTHNESS_TAKES_PRIORITY;
-
-  // New content always takes priority when there is an invalid viewport size or
-  // ui resources have been evicted.
-  if (impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() ||
-      impl().layer_tree_host_impl->EvictedUIResourcesExist() ||
-      impl().input_throttled_until_commit) {
-    // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
-    // tree might be freed. We need to set RequiresHighResToDraw to ensure that
-    // high res tiles will be required to activate pending tree.
-    impl().layer_tree_host_impl->SetRequiresHighResToDraw();
-    tree_priority = NEW_CONTENT_TAKES_PRIORITY;
-  }
-
-  impl().layer_tree_host_impl->SetTreePriority(tree_priority);
-
-  // Only put the scheduler in impl latency prioritization mode if we don't
-  // have a scroll listener. This gives the scroll listener a better chance of
-  // handling scroll updates within the same frame. The tree itself is still
-  // kept in prefer smoothness mode to allow checkerboarding.
-  ScrollHandlerState scroll_handler_state =
-      impl().layer_tree_host_impl->scroll_affects_scroll_handler()
-          ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
-          : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
-  impl().scheduler->SetTreePrioritiesAndScrollState(tree_priority,
-                                                    scroll_handler_state);
-
-  // Notify the the client of this compositor via the output surface.
-  // TODO(epenner): Route this to compositor-thread instead of output-surface
-  // after GTFO refactor of compositor-thread (http://crbug/170828).
-  if (impl().layer_tree_host_impl->output_surface()) {
-    impl()
-        .layer_tree_host_impl->output_surface()
-        ->UpdateSmoothnessTakesPriority(tree_priority ==
-                                        SMOOTHNESS_TAKES_PRIORITY);
-  }
-}
-
-void ThreadProxy::PostDelayedAnimationTaskOnImplThread(
-    const base::Closure& task,
-    base::TimeDelta delay) {
-  task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE,
-                                                                 task, delay);
-}
-
-void ThreadProxy::DidActivateSyncTree() {
-  TRACE_EVENT0("cc", "ThreadProxy::DidActivateSyncTreeOnImplThread");
-  DCHECK(task_runner_provider_->IsImplThread());
-
-  if (impl().next_commit_waits_for_activation) {
-    TRACE_EVENT_INSTANT0(
-        "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD);
-    DCHECK(impl().commit_completion_event);
-    impl().commit_completion_event->Signal();
-    impl().commit_completion_event = nullptr;
-    impl().next_commit_waits_for_activation = false;
-  }
-
-  impl().last_processed_begin_main_frame_args =
-      impl().last_begin_main_frame_args;
-}
-
-void ThreadProxy::WillPrepareTiles() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->WillPrepareTiles();
-}
-
-void ThreadProxy::DidPrepareTiles() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->DidPrepareTiles();
-}
-
-void ThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().channel_impl->DidCompletePageScaleAnimation();
-}
-
-void ThreadProxy::OnDrawForOutputSurface() {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().scheduler->OnDrawForOutputSurface();
-}
-
-void ThreadProxy::UpdateTopControlsState(TopControlsState constraints,
-                                         TopControlsState current,
-                                         bool animate) {
-  main().channel_main->UpdateTopControlsStateOnImpl(constraints, current,
-                                                    animate);
-}
-
-void ThreadProxy::UpdateTopControlsStateOnImpl(TopControlsState constraints,
-                                               TopControlsState current,
-                                               bool animate) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().layer_tree_host_impl->top_controls_manager()->UpdateTopControlsState(
-      constraints, current, animate);
-}
-
-void ThreadProxy::PostFrameTimingEventsOnImplThread(
-    scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
-    scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
-  DCHECK(task_runner_provider_->IsImplThread());
-  impl().channel_impl->PostFrameTimingEventsOnMain(
-      std::move(composite_events), std::move(main_frame_events));
-}
-
-void ThreadProxy::PostFrameTimingEventsOnMain(
-    scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
-    scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
-  DCHECK(task_runner_provider_->IsMainThread());
-  main().layer_tree_host->RecordFrameTimingEvents(std::move(composite_events),
-                                                  std::move(main_frame_events));
-}
-
-base::WeakPtr<ProxyMain> ThreadProxy::GetMainWeakPtr() {
-  return main_thread_weak_ptr_;
-}
-
-base::WeakPtr<ProxyImpl> ThreadProxy::GetImplWeakPtr() {
-  return impl_thread_weak_ptr_;
-}
-
-}  // namespace cc
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
deleted file mode 100644
index e10c57e6..0000000
--- a/cc/trees/thread_proxy.h
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright 2011 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_TREES_THREAD_PROXY_H_
-#define CC_TREES_THREAD_PROXY_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "cc/animation/animation_events.h"
-#include "cc/base/completion_event.h"
-#include "cc/base/delayed_unique_notifier.h"
-#include "cc/scheduler/commit_earlyout_reason.h"
-#include "cc/scheduler/scheduler.h"
-#include "cc/trees/layer_tree_host_impl.h"
-#include "cc/trees/proxy.h"
-#include "cc/trees/threaded_channel.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cc {
-
-class BeginFrameSource;
-class ChannelImpl;
-class ChannelMain;
-class ContextProvider;
-class InputHandlerClient;
-class LayerTreeHost;
-class ProxyImpl;
-class ProxyMain;
-class Scheduler;
-class ScopedThreadProxy;
-class ThreadedChannel;
-
-class CC_EXPORT ThreadProxy : public Proxy,
-                              public ProxyMain,
-                              public ProxyImpl,
-                              NON_EXPORTED_BASE(LayerTreeHostImplClient),
-                              NON_EXPORTED_BASE(SchedulerClient) {
- public:
-  static scoped_ptr<Proxy> Create(
-      LayerTreeHost* layer_tree_host,
-      TaskRunnerProvider* task_runner_provider,
-      scoped_ptr<BeginFrameSource> external_begin_frame_source);
-
-  ~ThreadProxy() override;
-
-  // Commits between the main and impl threads are processed through a pipeline
-  // with the following stages. For efficiency we can early out at any stage if
-  // we decide that no further processing is necessary.
-  enum CommitPipelineStage {
-    NO_PIPELINE_STAGE,
-    ANIMATE_PIPELINE_STAGE,
-    UPDATE_LAYERS_PIPELINE_STAGE,
-    COMMIT_PIPELINE_STAGE,
-  };
-
-  struct MainThreadOnly {
-    MainThreadOnly(ThreadProxy* proxy, LayerTreeHost* layer_tree_host);
-    ~MainThreadOnly();
-
-    const int layer_tree_host_id;
-
-    LayerTreeHost* layer_tree_host;
-
-    // The furthest pipeline stage which has been requested for the next
-    // commit.
-    CommitPipelineStage max_requested_pipeline_stage;
-    // The commit pipeline stage that is currently being processed.
-    CommitPipelineStage current_pipeline_stage;
-    // The commit pipeline stage at which processing for the current commit
-    // will stop. Only valid while we are executing the pipeline (i.e.,
-    // |current_pipeline_stage| is set to a pipeline stage).
-    CommitPipelineStage final_pipeline_stage;
-
-    bool commit_waits_for_activation;
-
-    bool started;
-    bool prepare_tiles_pending;
-    bool defer_commits;
-
-    RendererCapabilities renderer_capabilities_main_thread_copy;
-
-    // TODO(khushalsagar): Make this scoped_ptr<ChannelMain> when ProxyMain
-    // and ProxyImpl are split.
-    ChannelMain* channel_main;
-
-    base::WeakPtrFactory<ThreadProxy> weak_factory;
-  };
-
-  // Accessed on the impl thread when the main thread is blocked for a commit.
-  struct BlockedMainCommitOnly {
-    BlockedMainCommitOnly();
-    ~BlockedMainCommitOnly();
-    LayerTreeHost* layer_tree_host;
-  };
-
-  struct CompositorThreadOnly {
-    CompositorThreadOnly(
-        ThreadProxy* proxy,
-        int layer_tree_host_id,
-        RenderingStatsInstrumentation* rendering_stats_instrumentation,
-        scoped_ptr<BeginFrameSource> external_begin_frame_source);
-    ~CompositorThreadOnly();
-
-    const int layer_tree_host_id;
-
-    scoped_ptr<Scheduler> scheduler;
-
-    // Set when the main thread is waiting on a pending tree activation.
-    bool next_commit_waits_for_activation;
-
-    // Set when the main thread is waiting on a commit to complete or on a
-    // pending tree activation.
-    CompletionEvent* commit_completion_event;
-
-    // Set when the next draw should post DidCommitAndDrawFrame to the main
-    // thread.
-    bool next_frame_is_newly_committed_frame;
-
-    bool inside_draw;
-
-    bool input_throttled_until_commit;
-
-    // Whether a commit has been completed since the last time animations were
-    // ticked. If this happens, we need to animate again.
-    bool did_commit_after_animating;
-
-    DelayedUniqueNotifier smoothness_priority_expiration_notifier;
-
-    scoped_ptr<BeginFrameSource> external_begin_frame_source;
-
-    RenderingStatsInstrumentation* rendering_stats_instrumentation;
-
-    // Values used to keep track of frame durations. Used only in frame timing.
-    BeginFrameArgs last_begin_main_frame_args;
-    BeginFrameArgs last_processed_begin_main_frame_args;
-
-    scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl;
-
-    ChannelImpl* channel_impl;
-
-    base::WeakPtrFactory<ThreadProxy> weak_factory;
-  };
-
-  const MainThreadOnly& main() const;
-  const CompositorThreadOnly& impl() const;
-  TaskRunnerProvider* task_runner_provider() { return task_runner_provider_; }
-
-  // Proxy implementation
-  void FinishAllRendering() override;
-  bool IsStarted() const override;
-  bool CommitToActiveTree() const override;
-  void SetOutputSurface(OutputSurface* output_surface) override;
-  void SetVisible(bool visible) override;
-  void SetThrottleFrameProduction(bool throttle) override;
-  const RendererCapabilities& GetRendererCapabilities() const override;
-  void SetNeedsAnimate() override;
-  void SetNeedsUpdateLayers() override;
-  void SetNeedsCommit() override;
-  void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
-  void SetNextCommitWaitsForActivation() override;
-  void NotifyInputThrottledUntilCommit() override;
-  void SetDeferCommits(bool defer_commits) override;
-  bool CommitRequested() const override;
-  bool BeginMainFrameRequested() const override;
-  void MainThreadHasStoppedFlinging() override;
-  void Start() override;
-  void Stop() override;
-  bool SupportsImplScrolling() const override;
-  bool MainFrameWillHappenForTesting() override;
-  void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
-  void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) override;
-  void ReleaseOutputSurface() override;
-  void UpdateTopControlsState(TopControlsState constraints,
-                              TopControlsState current,
-                              bool animate) override;
-
-  // LayerTreeHostImplClient implementation
-  void UpdateRendererCapabilitiesOnImplThread() override;
-  void DidLoseOutputSurfaceOnImplThread() override;
-  void CommitVSyncParameters(base::TimeTicks timebase,
-                             base::TimeDelta interval) override;
-  void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override;
-  void DidSwapBuffersOnImplThread() override;
-  void DidSwapBuffersCompleteOnImplThread() override;
-  void OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) override;
-  void OnCanDrawStateChanged(bool can_draw) override;
-  void NotifyReadyToActivate() override;
-  void NotifyReadyToDraw() override;
-  // Please call these 3 functions through
-  // LayerTreeHostImpl's SetNeedsRedraw(), SetNeedsRedrawRect() and
-  // SetNeedsOneBeginImplFrame().
-  void SetNeedsRedrawOnImplThread() override;
-  void SetNeedsRedrawRectOnImplThread(const gfx::Rect& dirty_rect) override;
-  void SetNeedsOneBeginImplFrameOnImplThread() override;
-  void SetNeedsPrepareTilesOnImplThread() override;
-  void SetNeedsCommitOnImplThread() override;
-  void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
-  void PostAnimationEventsToMainThreadOnImplThread(
-      scoped_ptr<AnimationEventsVector> queue) override;
-  bool IsInsideDraw() override;
-  void RenewTreePriority() override;
-  void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
-                                            base::TimeDelta delay) override;
-  void DidActivateSyncTree() override;
-  void WillPrepareTiles() override;
-  void DidPrepareTiles() override;
-  void DidCompletePageScaleAnimationOnImplThread() override;
-  void OnDrawForOutputSurface() override;
-  // This should only be called by LayerTreeHostImpl::PostFrameTimingEvents.
-  void PostFrameTimingEventsOnImplThread(
-      scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
-      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
-      override;
-
-  // SchedulerClient implementation
-  void WillBeginImplFrame(const BeginFrameArgs& args) override;
-  void DidFinishImplFrame() override;
-  void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override;
-  DrawResult ScheduledActionDrawAndSwapIfPossible() override;
-  DrawResult ScheduledActionDrawAndSwapForced() override;
-  void ScheduledActionCommit() override;
-  void ScheduledActionActivateSyncTree() override;
-  void ScheduledActionBeginOutputSurfaceCreation() override;
-  void ScheduledActionPrepareTiles() override;
-  void ScheduledActionInvalidateOutputSurface() override;
-  void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
-  void SendBeginMainFrameNotExpectedSoon() override;
-
-  // ProxyMain implementation
-  void SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) override;
-
- protected:
-  ThreadProxy(LayerTreeHost* layer_tree_host,
-              TaskRunnerProvider* task_runner_provider,
-              scoped_ptr<BeginFrameSource> external_begin_frame_source);
-
- private:
-  friend class ThreadProxyForTest;
-
-  // ProxyMain implementation.
-  base::WeakPtr<ProxyMain> GetMainWeakPtr() override;
-  void DidCompleteSwapBuffers() override;
-  void SetRendererCapabilitiesMainCopy(
-      const RendererCapabilities& capabilities) override;
-  void BeginMainFrameNotExpectedSoon() override;
-  void DidCommitAndDrawFrame() override;
-  void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue) override;
-  void DidLoseOutputSurface() override;
-  void RequestNewOutputSurface() override;
-  void DidInitializeOutputSurface(
-      bool success,
-      const RendererCapabilities& capabilities) override;
-  void DidCompletePageScaleAnimation() override;
-  void PostFrameTimingEventsOnMain(
-      scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
-      scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
-      override;
-  void BeginMainFrame(
-      scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) override;
-
-  // ProxyImpl implementation
-  base::WeakPtr<ProxyImpl> GetImplWeakPtr() override;
-  void SetThrottleFrameProductionOnImpl(bool throttle) override;
-  void UpdateTopControlsStateOnImpl(TopControlsState constraints,
-                                    TopControlsState current,
-                                    bool animate) override;
-  void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) override;
-  void MainThreadHasStoppedFlingingOnImpl() override;
-  void SetInputThrottledUntilCommitOnImpl(bool is_throttled) override;
-  void SetDeferCommitsOnImpl(bool defer_commits) const override;
-  void FinishAllRenderingOnImpl(CompletionEvent* completion) override;
-  void SetVisibleOnImpl(bool visible) override;
-  void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override;
-  void FinishGLOnImpl(CompletionEvent* completion) override;
-  void MainFrameWillHappenOnImplForTesting(
-      CompletionEvent* completion,
-      bool* main_frame_will_happen) override;
-  void SetNeedsCommitOnImpl() override;
-  void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override;
-  void BeginMainFrameAbortedOnImpl(
-      CommitEarlyOutReason reason,
-      base::TimeTicks main_thread_start_time) override;
-  void StartCommitOnImpl(CompletionEvent* completion,
-                         LayerTreeHost* layer_tree_host,
-                         base::TimeTicks main_thread_start_time,
-                         bool hold_commit_for_activation) override;
-  void InitializeImplOnImpl(CompletionEvent* completion,
-                            LayerTreeHost* layer_tree_host) override;
-  void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override;
-
-  // Returns |true| if the request was actually sent, |false| if one was
-  // already outstanding.
-  bool SendCommitRequestToImplThreadIfNeeded(
-      CommitPipelineStage required_stage);
-
-  // Called on impl thread.
-  struct SchedulerStateRequest;
-
-  DrawResult DrawSwapInternal(bool forced_draw);
-
-  TaskRunnerProvider* task_runner_provider_;
-
-  // Use accessors instead of this variable directly.
-  MainThreadOnly main_thread_only_vars_unsafe_;
-  MainThreadOnly& main();
-
-  // Use accessors instead of this variable directly.
-  BlockedMainCommitOnly main_thread_blocked_commit_vars_unsafe_;
-  BlockedMainCommitOnly& blocked_main_commit();
-
-  // Use accessors instead of this variable directly.
-  CompositorThreadOnly compositor_thread_vars_unsafe_;
-  CompositorThreadOnly& impl();
-
-  // TODO(khushalsagar): Remove this. Temporary variable to hold the channel.
-  scoped_ptr<ThreadedChannel> threaded_channel_;
-
-  base::WeakPtr<ThreadProxy> main_thread_weak_ptr_;
-  base::WeakPtr<ThreadProxy> impl_thread_weak_ptr_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThreadProxy);
-};
-
-}  // namespace cc
-
-#endif  // CC_TREES_THREAD_PROXY_H_
diff --git a/cc/trees/threaded_channel.cc b/cc/trees/threaded_channel.cc
index 37ed58f7..3d2eb33 100644
--- a/cc/trees/threaded_channel.cc
+++ b/cc/trees/threaded_channel.cc
@@ -7,222 +7,312 @@
 #include "base/bind.h"
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
+#include "cc/trees/layer_tree_host.h"
 
 namespace cc {
 
-scoped_ptr<ThreadedChannel> ThreadedChannel::Create(
-    ThreadProxy* thread_proxy,
-    TaskRunnerProvider* task_runner_provider) {
-  return make_scoped_ptr(
-      new ThreadedChannel(thread_proxy, task_runner_provider));
+ThreadedChannel::ThreadedChannel(ProxyMain* proxy_main,
+                                 TaskRunnerProvider* task_runner_provider)
+    : task_runner_provider_(task_runner_provider),
+      main_thread_only_vars_unsafe_(proxy_main),
+      compositor_thread_vars_unsafe_(
+          main()
+              .proxy_main_weak_factory.GetWeakPtr()) {
+  DCHECK(IsMainThread());
 }
 
-ThreadedChannel::ThreadedChannel(ThreadProxy* thread_proxy,
-                                 TaskRunnerProvider* task_runner_provider)
-    : proxy_main_(thread_proxy),
-      proxy_impl_(thread_proxy),
-      task_runner_provider_(task_runner_provider) {}
+ThreadedChannel::~ThreadedChannel() {
+  TRACE_EVENT0("cc", "ThreadChannel::~ThreadChannel");
+  DCHECK(IsMainThread());
+  DCHECK(!IsInitialized());
+}
 
 void ThreadedChannel::SetThrottleFrameProductionOnImpl(bool throttle) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyImpl::SetThrottleFrameProductionOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), throttle));
+                            proxy_impl_weak_ptr_, throttle));
 }
 
 void ThreadedChannel::UpdateTopControlsStateOnImpl(TopControlsState constraints,
                                                    TopControlsState current,
                                                    bool animate) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE,
-      base::Bind(&ProxyImpl::UpdateTopControlsStateOnImpl,
-                 proxy_impl_->GetImplWeakPtr(), constraints, current, animate));
+      base::Bind(&ProxyImpl::UpdateTopControlsStateOnImpl, proxy_impl_weak_ptr_,
+                 constraints, current, animate));
 }
 
 void ThreadedChannel::InitializeOutputSurfaceOnImpl(
     OutputSurface* output_surface) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyImpl::InitializeOutputSurfaceOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), output_surface));
+                            proxy_impl_weak_ptr_, output_surface));
 }
 
 void ThreadedChannel::MainThreadHasStoppedFlingingOnImpl() {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyImpl::MainThreadHasStoppedFlingingOnImpl,
-                            proxy_impl_->GetImplWeakPtr()));
+                            proxy_impl_weak_ptr_));
 }
 
 void ThreadedChannel::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyImpl::SetInputThrottledUntilCommitOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), is_throttled));
+                            proxy_impl_weak_ptr_, is_throttled));
 }
 
 void ThreadedChannel::SetDeferCommitsOnImpl(bool defer_commits) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyImpl::SetDeferCommitsOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), defer_commits));
-}
-
-void ThreadedChannel::FinishAllRenderingOnImpl(CompletionEvent* completion) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::FinishAllRenderingOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), completion));
+                            proxy_impl_weak_ptr_, defer_commits));
 }
 
 void ThreadedChannel::SetNeedsCommitOnImpl() {
-  ImplThreadTaskRunner()->PostTask(FROM_HERE,
-                                   base::Bind(&ProxyImpl::SetNeedsCommitOnImpl,
-                                              proxy_impl_->GetImplWeakPtr()));
+  DCHECK(IsMainThread());
+  ImplThreadTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(&ProxyImpl::SetNeedsCommitOnImpl, proxy_impl_weak_ptr_));
 }
 
 void ThreadedChannel::BeginMainFrameAbortedOnImpl(
     CommitEarlyOutReason reason,
     base::TimeTicks main_thread_start_time) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), reason,
-                            main_thread_start_time));
+      FROM_HERE,
+      base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, proxy_impl_weak_ptr_,
+                 reason, main_thread_start_time));
 }
 
 void ThreadedChannel::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyImpl::SetNeedsRedrawOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), damage_rect));
+                            proxy_impl_weak_ptr_, damage_rect));
+}
+
+void ThreadedChannel::SetVisibleOnImpl(bool visible) {
+  DCHECK(IsMainThread());
+  ImplThreadTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(&ProxyImpl::SetVisibleOnImpl, proxy_impl_weak_ptr_, visible));
+}
+
+void ThreadedChannel::FinishAllRenderingOnImpl(CompletionEvent* completion) {
+  DCHECK(IsMainThread());
+  ImplThreadTaskRunner()->PostTask(
+      FROM_HERE, base::Bind(&ProxyImpl::FinishAllRenderingOnImpl,
+                            proxy_impl_weak_ptr_, completion));
+}
+
+void ThreadedChannel::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
+  DCHECK(IsMainThread());
+  ImplThreadTaskRunner()->PostTask(
+      FROM_HERE, base::Bind(&ProxyImpl::ReleaseOutputSurfaceOnImpl,
+                            proxy_impl_weak_ptr_, completion));
+}
+
+void ThreadedChannel::MainFrameWillHappenOnImplForTesting(
+    CompletionEvent* completion,
+    bool* main_frame_will_happen) {
+  DCHECK(IsMainThread());
+  ImplThreadTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(&ProxyImpl::MainFrameWillHappenOnImplForTesting,
+                 proxy_impl_weak_ptr_, completion, main_frame_will_happen));
 }
 
 void ThreadedChannel::StartCommitOnImpl(CompletionEvent* completion,
                                         LayerTreeHost* layer_tree_host,
                                         base::TimeTicks main_thread_start_time,
                                         bool hold_commit_for_activation) {
+  DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
-      FROM_HERE,
-      base::Bind(&ProxyImpl::StartCommitOnImpl, proxy_impl_->GetImplWeakPtr(),
-                 completion, layer_tree_host, main_thread_start_time,
-                 hold_commit_for_activation));
+      FROM_HERE, base::Bind(&ProxyImpl::StartCommitOnImpl, proxy_impl_weak_ptr_,
+                            completion, layer_tree_host, main_thread_start_time,
+                            hold_commit_for_activation));
 }
 
-void ThreadedChannel::InitializeImplOnImpl(CompletionEvent* completion,
-                                           LayerTreeHost* layer_tree_host) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE,
-      base::Bind(&ProxyImpl::InitializeImplOnImpl,
-                 base::Unretained(proxy_impl_), completion, layer_tree_host));
+void ThreadedChannel::SynchronouslyInitializeImpl(
+    LayerTreeHost* layer_tree_host,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  TRACE_EVENT0("cc", "ThreadChannel::SynchronouslyInitializeImpl");
+  DCHECK(IsMainThread());
+  {
+    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+    CompletionEvent completion;
+    ImplThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::Bind(&ThreadedChannel::InitializeImplOnImpl,
+                   base::Unretained(this), &completion, layer_tree_host,
+                   base::Passed(&external_begin_frame_source)));
+    completion.Wait();
+  }
+  main().initialized = true;
 }
 
-void ThreadedChannel::LayerTreeHostClosedOnImpl(CompletionEvent* completion) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::LayerTreeHostClosedOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), completion));
-  proxy_impl_ = nullptr;
-}
+void ThreadedChannel::SynchronouslyCloseImpl() {
+  TRACE_EVENT0("cc", "ThreadChannel::~SynchronouslyCloseImpl");
+  DCHECK(IsMainThread());
 
-void ThreadedChannel::SetVisibleOnImpl(bool visible) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::SetVisibleOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), visible));
-}
-
-void ThreadedChannel::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::ReleaseOutputSurfaceOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), completion));
-}
-
-void ThreadedChannel::FinishGLOnImpl(CompletionEvent* completion) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::FinishGLOnImpl,
-                            proxy_impl_->GetImplWeakPtr(), completion));
-}
-
-void ThreadedChannel::MainFrameWillHappenOnImplForTesting(
-    CompletionEvent* completion,
-    bool* main_frame_will_happen) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyImpl::MainFrameWillHappenOnImplForTesting,
-                            proxy_impl_->GetImplWeakPtr(), completion,
-                            main_frame_will_happen));
+  // Synchronously finishes pending GL operations and deletes the impl.
+  // The two steps are done as separate post tasks, so that tasks posted
+  // by the GL implementation due to the Finish can be executed by the
+  // renderer before shutting it down.
+  {
+    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+    CompletionEvent completion;
+    ImplThreadTaskRunner()->PostTask(
+        FROM_HERE, base::Bind(&ProxyImpl::FinishGLOnImpl, proxy_impl_weak_ptr_,
+                              &completion));
+    completion.Wait();
+  }
+  {
+    DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+    CompletionEvent completion;
+    ImplThreadTaskRunner()->PostTask(
+        FROM_HERE, base::Bind(&ThreadedChannel::CloseImplOnImpl,
+                              base::Unretained(this), &completion));
+    completion.Wait();
+  }
+  main().proxy_main_weak_factory.InvalidateWeakPtrs();
+  main().initialized = false;
 }
 
 void ThreadedChannel::DidCompleteSwapBuffers() {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyMain::DidCompleteSwapBuffers,
-                            proxy_main_->GetMainWeakPtr()));
+                            impl().proxy_main_weak_ptr));
 }
 
 void ThreadedChannel::SetRendererCapabilitiesMainCopy(
     const RendererCapabilities& capabilities) {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&ProxyMain::SetRendererCapabilitiesMainCopy,
-                            proxy_main_->GetMainWeakPtr(), capabilities));
+      FROM_HERE, base::Bind(&ProxyMain::SetRendererCapabilities,
+                            impl().proxy_main_weak_ptr, capabilities));
 }
 
 void ThreadedChannel::BeginMainFrameNotExpectedSoon() {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyMain::BeginMainFrameNotExpectedSoon,
-                            proxy_main_->GetMainWeakPtr()));
+                            impl().proxy_main_weak_ptr));
 }
 
 void ThreadedChannel::DidCommitAndDrawFrame() {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(FROM_HERE,
                                    base::Bind(&ProxyMain::DidCommitAndDrawFrame,
-                                              proxy_main_->GetMainWeakPtr()));
+                                              impl().proxy_main_weak_ptr));
 }
 
 void ThreadedChannel::SetAnimationEvents(
     scoped_ptr<AnimationEventsVector> queue) {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
-      FROM_HERE,
-      base::Bind(&ProxyMain::SetAnimationEvents, proxy_main_->GetMainWeakPtr(),
-                 base::Passed(&queue)));
+      FROM_HERE, base::Bind(&ProxyMain::SetAnimationEvents,
+                            impl().proxy_main_weak_ptr, base::Passed(&queue)));
 }
 
 void ThreadedChannel::DidLoseOutputSurface() {
-  MainThreadTaskRunner()->PostTask(FROM_HERE,
-                                   base::Bind(&ProxyMain::DidLoseOutputSurface,
-                                              proxy_main_->GetMainWeakPtr()));
+  DCHECK(IsImplThread());
+  MainThreadTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(&ProxyMain::DidLoseOutputSurface, impl().proxy_main_weak_ptr));
 }
 
 void ThreadedChannel::RequestNewOutputSurface() {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyMain::RequestNewOutputSurface,
-                            proxy_main_->GetMainWeakPtr()));
+                            impl().proxy_main_weak_ptr));
 }
 
 void ThreadedChannel::DidInitializeOutputSurface(
     bool success,
     const RendererCapabilities& capabilities) {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
-      FROM_HERE,
-      base::Bind(&ProxyMain::DidInitializeOutputSurface,
-                 proxy_main_->GetMainWeakPtr(), success, capabilities));
+      FROM_HERE, base::Bind(&ProxyMain::DidInitializeOutputSurface,
+                            impl().proxy_main_weak_ptr, success, capabilities));
 }
 
 void ThreadedChannel::DidCompletePageScaleAnimation() {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyMain::DidCompletePageScaleAnimation,
-                            proxy_main_->GetMainWeakPtr()));
+                            impl().proxy_main_weak_ptr));
 }
 
 void ThreadedChannel::PostFrameTimingEventsOnMain(
     scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
     scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
       FROM_HERE, base::Bind(&ProxyMain::PostFrameTimingEventsOnMain,
-                            proxy_main_->GetMainWeakPtr(),
+                            impl().proxy_main_weak_ptr,
                             base::Passed(std::move(composite_events)),
                             base::Passed(std::move(main_frame_events))));
 }
 
 void ThreadedChannel::BeginMainFrame(
     scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+  DCHECK(IsImplThread());
   MainThreadTaskRunner()->PostTask(
       FROM_HERE,
-      base::Bind(&ProxyMain::BeginMainFrame, proxy_main_->GetMainWeakPtr(),
+      base::Bind(&ProxyMain::BeginMainFrame, impl().proxy_main_weak_ptr,
                  base::Passed(&begin_main_frame_state)));
 }
 
-ThreadedChannel::~ThreadedChannel() {
-  TRACE_EVENT0("cc", "ThreadChannel::~ThreadChannel");
+ProxyImpl* ThreadedChannel::GetProxyImplForTesting() const {
+  return impl().proxy_impl.get();
+}
+
+scoped_ptr<ProxyImpl> ThreadedChannel::CreateProxyImpl(
+    ChannelImpl* channel_impl,
+    LayerTreeHost* layer_tree_host,
+    TaskRunnerProvider* task_runner_provider,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  DCHECK(IsImplThread());
+  return ProxyImpl::Create(channel_impl, layer_tree_host, task_runner_provider,
+                           std::move(external_begin_frame_source));
+}
+
+void ThreadedChannel::InitializeImplOnImpl(
+    CompletionEvent* completion,
+    LayerTreeHost* layer_tree_host,
+    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+  DCHECK(IsImplThread());
+  impl().proxy_impl =
+      CreateProxyImpl(this, layer_tree_host, task_runner_provider_,
+                      std::move(external_begin_frame_source));
+  impl().proxy_impl_weak_factory = make_scoped_ptr(
+      new base::WeakPtrFactory<ProxyImpl>(impl().proxy_impl.get()));
+  proxy_impl_weak_ptr_ = impl().proxy_impl_weak_factory->GetWeakPtr();
+  completion->Signal();
+}
+
+void ThreadedChannel::CloseImplOnImpl(CompletionEvent* completion) {
+  DCHECK(IsImplThread());
+
+  // We must destroy the factory and ensure that the ProxyImpl weak pointers are
+  // invalidated before destroying proxy_impl.
+  impl().proxy_impl_weak_factory.reset();
+
+  impl().proxy_impl.reset();
+  completion->Signal();
+}
+
+bool ThreadedChannel::IsInitialized() const {
+  return main().initialized;
 }
 
 base::SingleThreadTaskRunner* ThreadedChannel::MainThreadTaskRunner() const {
@@ -233,4 +323,49 @@
   return task_runner_provider_->ImplThreadTaskRunner();
 }
 
+bool ThreadedChannel::IsMainThread() const {
+  return task_runner_provider_->IsMainThread();
+}
+
+bool ThreadedChannel::IsImplThread() const {
+  return task_runner_provider_->IsImplThread();
+}
+
+ThreadedChannel::MainThreadOnly& ThreadedChannel::main() {
+  DCHECK(task_runner_provider_->IsMainThread());
+  return main_thread_only_vars_unsafe_;
+}
+
+const ThreadedChannel::MainThreadOnly& ThreadedChannel::main() const {
+  DCHECK(task_runner_provider_->IsMainThread());
+  return main_thread_only_vars_unsafe_;
+}
+
+ThreadedChannel::CompositorThreadOnly& ThreadedChannel::impl() {
+  DCHECK(task_runner_provider_->IsImplThread());
+  return compositor_thread_vars_unsafe_;
+}
+
+const ThreadedChannel::CompositorThreadOnly& ThreadedChannel::impl() const {
+  DCHECK(task_runner_provider_->IsImplThread());
+  return compositor_thread_vars_unsafe_;
+}
+
+ThreadedChannel::MainThreadOnly::MainThreadOnly(ProxyMain* proxy_main)
+    : proxy_main_weak_factory(proxy_main), initialized(false) {}
+
+ThreadedChannel::MainThreadOnly::~MainThreadOnly() {}
+
+ThreadedChannel::CompositorThreadOnly::CompositorThreadOnly(
+    base::WeakPtr<ProxyMain> proxy_main_weak_ptr)
+    : proxy_main_weak_ptr(proxy_main_weak_ptr) {}
+
+ThreadedChannel::CompositorThreadOnly::~CompositorThreadOnly() {}
+
+scoped_ptr<ThreadedChannel> ThreadedChannel::Create(
+    ProxyMain* proxy_main,
+    TaskRunnerProvider* task_runner_provider) {
+  return make_scoped_ptr(new ThreadedChannel(proxy_main, task_runner_provider));
+}
+
 }  // namespace cc
diff --git a/cc/trees/threaded_channel.h b/cc/trees/threaded_channel.h
index ca7fc04..5d10f4af 100644
--- a/cc/trees/threaded_channel.h
+++ b/cc/trees/threaded_channel.h
@@ -7,13 +7,13 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "cc/base/cc_export.h"
 #include "cc/trees/channel_impl.h"
 #include "cc/trees/channel_main.h"
 #include "cc/trees/proxy_common.h"
 #include "cc/trees/proxy_impl.h"
 #include "cc/trees/proxy_main.h"
-#include "cc/trees/thread_proxy.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -22,9 +22,9 @@
 namespace cc {
 class ChannelImpl;
 class ChannelMain;
+class LayerTreeHost;
 class ProxyImpl;
 class ProxyMain;
-class ThreadProxy;
 
 // An implementation of ChannelMain and ChannelImpl that sends commands between
 // ProxyMain and ProxyImpl across thread boundaries.
@@ -39,8 +39,8 @@
 //        ProxyMain->Start()          |
 //               |              ThreadedChannel
 // ---------------------------------------------------------------------------
-//  ChannelMain::InitializeImpl ---PostTask---> ThreadedChannel::
-//                                                   InitializeImplOnImplThread
+//  ChannelMain::SynchronouslyInitializeImpl ---PostTask---> ThreadedChannel::
+//                                                    InitializeImplOnImpl
 //                                                          |
 //                                                   ProxyImpl::Create
 //                                                          |
@@ -56,20 +56,27 @@
 // ProxyMain->RequestNewOutputSurface()<----PostTask--------
 //              .
 //              .
-// ProxyMain->LayerTreeHostClosed
+// ProxyMain->Stop()
 //              |
 // ---------------------------------------------------------------------------
-// ChannelMain::SetLayerTreeClosedOnImpl---PostTask---> ProxyImpl->
-//                                                        SetLayerTreeClosed
+// ChannelMain::SynchronouslyCloseImpl ---PostTask---> ThreadedChannel::
+//                                                      CloseImplOnImpl
 // ----------------------------------------------------------------------------
+//
+// ThreadedChannel is created and destroyed on the main thread but can be
+// called from main or impl thread. It is safe for the Threadedchannel to be
+// called on the impl thread because:
+// 1) The only impl-threaded callers of ThreadedChannel are the ThreadedChannel
+// itself and ProxyImpl which is created and owned by the ThreadedChannel.
+// 2) ThreadedChannel blocks the main thread in
+// ThreadedChannel::SynchronouslyCloseImpl to wait for the impl-thread teardown
+// to complete, so there is no risk of any queued tasks calling it on the impl
+// thread after it has been deleted on the main thread.
 
 class CC_EXPORT ThreadedChannel : public ChannelMain, public ChannelImpl {
  public:
   static scoped_ptr<ThreadedChannel> Create(
-      // TODO(khushalsagar): Make this ProxyMain* and write the initialization
-      // sequence. Currently ThreadProxy implements both so we pass the pointer
-      // and set ProxyImpl.
-      ThreadProxy* thread_proxy,
+      ProxyMain* proxy_main,
       TaskRunnerProvider* task_runner_provider);
 
   ~ThreadedChannel() override;
@@ -93,7 +100,6 @@
   // Blocking calls to ProxyImpl
   void FinishAllRenderingOnImpl(CompletionEvent* completion) override;
   void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override;
-  void FinishGLOnImpl(CompletionEvent* completion) override;
   void MainFrameWillHappenOnImplForTesting(
       CompletionEvent* completion,
       bool* main_frame_will_happen) override;
@@ -101,9 +107,10 @@
                          LayerTreeHost* layer_tree_host,
                          base::TimeTicks main_thread_start_time,
                          bool hold_commit_for_activation) override;
-  void InitializeImplOnImpl(CompletionEvent* completion,
-                            LayerTreeHost* layer_tree_host) override;
-  void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override;
+  void SynchronouslyInitializeImpl(
+      LayerTreeHost* layer_tree_host,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source) override;
+  void SynchronouslyCloseImpl() override;
 
   // ChannelImpl Implementation
   void DidCompleteSwapBuffers() override;
@@ -125,23 +132,84 @@
   void BeginMainFrame(
       scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) override;
 
+  // Should be called on impl thread only.
+  ProxyImpl* GetProxyImplForTesting() const;
+
  protected:
-  ThreadedChannel(ThreadProxy* thread_proxy,
+  ThreadedChannel(ProxyMain* proxy_main,
                   TaskRunnerProvider* task_runner_provider);
 
+  // Virtual for testing.
+  virtual scoped_ptr<ProxyImpl> CreateProxyImpl(
+      ChannelImpl* channel_impl,
+      LayerTreeHost* layer_tree_host,
+      TaskRunnerProvider* task_runner_provider,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
  private:
+  // The members of this struct should be accessed on the main thread only.
+  struct MainThreadOnly {
+    explicit MainThreadOnly(ProxyMain* proxy_main);
+    ~MainThreadOnly();
+
+    base::WeakPtrFactory<ProxyMain> proxy_main_weak_factory;
+    bool initialized;
+  };
+
+  // The members of this struct should be accessed on the impl thread only.
+  struct CompositorThreadOnly {
+    explicit CompositorThreadOnly(base::WeakPtr<ProxyMain> proxy_main_weak_ptr);
+    ~CompositorThreadOnly();
+
+    scoped_ptr<ProxyImpl> proxy_impl;
+
+    // We use a scoped_ptr for the weak ptr factory here since the factory is
+    // created after ProxyImpl is created in InitializeImplOnImpl. Since the
+    // weak ptrs are needed only by the ThreadedChannel to safely post tasks on
+    // ProxyImpl to be run on the impl thread, we avoid creating it in ProxyImpl
+    // and ensure that it is destroyed before ProxyImpl during the impl-thread
+    // tear down in CloseImplOnImpl.
+    scoped_ptr<base::WeakPtrFactory<ProxyImpl>> proxy_impl_weak_factory;
+
+    // Used on the impl thread to queue calls to ProxyMain to be run on the main
+    // thread. Since the weak pointer is invalidated after the impl-thread tear
+    // down in SynchronouslyCloseImpl, this ensures that any tasks posted to
+    // ProxyMain from the impl thread are abandoned after the impl side has been
+    // destroyed.
+    base::WeakPtr<ProxyMain> proxy_main_weak_ptr;
+  };
+
+  // Called on impl thread.
+  void InitializeImplOnImpl(
+      CompletionEvent* completion,
+      LayerTreeHost* layer_tree_host,
+      scoped_ptr<BeginFrameSource> external_begin_frame_source);
+  void CloseImplOnImpl(CompletionEvent* completion);
+
+  bool IsInitialized() const;
+
   base::SingleThreadTaskRunner* MainThreadTaskRunner() const;
   base::SingleThreadTaskRunner* ImplThreadTaskRunner() const;
-
-  ProxyMain* proxy_main_;
-
-  ProxyImpl* proxy_impl_;
+  bool IsMainThread() const;
+  bool IsImplThread() const;
 
   TaskRunnerProvider* task_runner_provider_;
 
-  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+  MainThreadOnly& main();
+  const MainThreadOnly& main() const;
 
-  scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
+  CompositorThreadOnly& impl();
+  const CompositorThreadOnly& impl() const;
+
+  // Use accessors instead of this variable directly.
+  MainThreadOnly main_thread_only_vars_unsafe_;
+
+  // Use accessors instead of this variable directly.
+  CompositorThreadOnly compositor_thread_vars_unsafe_;
+
+  // Used on the main thread to safely queue calls to ProxyImpl to be run on the
+  // impl thread.
+  base::WeakPtr<ProxyImpl> proxy_impl_weak_ptr_;
 
   DISALLOW_COPY_AND_ASSIGN(ThreadedChannel);
 };
diff --git a/cc/trees/threaded_channel_unittest.cc b/cc/trees/threaded_channel_unittest.cc
index 152ff59..17350d84 100644
--- a/cc/trees/threaded_channel_unittest.cc
+++ b/cc/trees/threaded_channel_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 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.
 
@@ -13,13 +13,12 @@
 // The ThreadedChannel tests are run only for threaded and direct mode.
 class ThreadedChannelTest : public LayerTreeTest {
  protected:
-  ThreadedChannelTest() : thread_proxy_(nullptr), calls_received_(0) {}
+  ThreadedChannelTest() : calls_received_(0) {}
 
   ~ThreadedChannelTest() override {}
 
   void BeginTest() override {
     DCHECK(HasImplThread());
-    thread_proxy_ = static_cast<ThreadProxy*>(proxy());
     BeginChannelTest();
   };
   virtual void BeginChannelTest() {}
@@ -36,9 +35,6 @@
 
   void AfterTest() override {}
 
-  // TODO(khushalsagar): Remove this once ProxyImpl is added to the
-  // LayerTreeTest.
-  ThreadProxy* thread_proxy_;
   int calls_received_;
 
  private:
@@ -47,8 +43,6 @@
 
 class ThreadedChannelTestInitializationAndShutdown
     : public ThreadedChannelTest {
-  void InitializeImplOnImpl() override { calls_received_++; }
-
   void SetVisibleOnImpl(bool visible) override { calls_received_++; }
 
   void ReceivedRequestNewOutputSurface() override { calls_received_++; }
@@ -69,10 +63,9 @@
     EndTest();
   }
 
-  void WillCloseLayerTreeHostOnImpl() override { calls_received_++; }
   void FinishGLOnImpl() override { calls_received_++; }
 
-  void AfterTest() override { EXPECT_EQ(8, calls_received_); }
+  void AfterTest() override { EXPECT_EQ(6, calls_received_); }
 };
 
 MULTI_THREAD_DIRECT_RENDERER_TEST_F(
@@ -246,7 +239,7 @@
   void BeginChannelTest() override { PostOnImplThread(); }
 
   void StartTestOnImplThread() override {
-    thread_proxy_->SendBeginMainFrameNotExpectedSoon();
+    GetProxyImplForTest()->SendBeginMainFrameNotExpectedSoon();
   }
 
   void ReceivedBeginMainFrameNotExpectedSoon() override {
@@ -266,7 +259,7 @@
   void StartTestOnImplThread() override {
     scoped_ptr<AnimationEventsVector> events(
         make_scoped_ptr(new AnimationEventsVector));
-    thread_proxy_->PostAnimationEventsToMainThreadOnImplThread(
+    GetProxyImplForTest()->PostAnimationEventsToMainThreadOnImplThread(
         std::move(events));
   }
 
@@ -284,7 +277,7 @@
   void BeginChannelTest() override { PostOnImplThread(); }
 
   void StartTestOnImplThread() override {
-    thread_proxy_->DidLoseOutputSurfaceOnImplThread();
+    GetProxyImplForTest()->DidLoseOutputSurfaceOnImplThread();
   }
 
   void ReceivedDidLoseOutputSurface() override {
@@ -301,7 +294,7 @@
   void BeginChannelTest() override { PostOnImplThread(); }
 
   void StartTestOnImplThread() override {
-    thread_proxy_->DidCompletePageScaleAnimationOnImplThread();
+    GetProxyImplForTest()->DidCompletePageScaleAnimationOnImplThread();
   }
 
   void ReceivedDidCompletePageScaleAnimation() override {