diff --git a/DEPS b/DEPS
index ece0a0b..88a7ebe5 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '57bc1e7bc804be4779dd09409046f62c4d43e3cd',
+  'skia_revision': '7f9c29a887106ab3babe0ec423a3bcae87ae4788',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'c2b0acd4835d90ee4c9a60659cf25d3dece5e7f3',
+  'v8_revision': '68f430ce82eef2be84afb42cc7e70572ac10a23c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/ash/tooltips/tooltip_controller_unittest.cc b/ash/tooltips/tooltip_controller_unittest.cc
index 3807957..02fdb02 100644
--- a/ash/tooltips/tooltip_controller_unittest.cc
+++ b/ash/tooltips/tooltip_controller_unittest.cc
@@ -109,20 +109,21 @@
                                 view->bounds().CenterPoint());
   base::string16 expected_tooltip = base::ASCIIToUTF16("Tooltip Text");
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
+  // Mouse event triggers tooltip update so it becomes visible.
   EXPECT_TRUE(helper_->IsTooltipVisible());
 
-  // Hide the cursor and check again.
+  // Disable mouse event which hides the cursor and check again.
   ash::Shell::GetInstance()->cursor_manager()->DisableMouseEvents();
-  helper_->FireTooltipTimer();
+  RunAllPendingInMessageLoop();
+  EXPECT_FALSE(ash::Shell::GetInstance()->cursor_manager()->IsCursorVisible());
+  helper_->UpdateIfRequired();
   EXPECT_FALSE(helper_->IsTooltipVisible());
 
-  // Show the cursor and re-check.
-  RunAllPendingInMessageLoop();
+  // Enable mouse event which shows the cursor and re-check.
   ash::Shell::GetInstance()->cursor_manager()->EnableMouseEvents();
   RunAllPendingInMessageLoop();
-  helper_->FireTooltipTimer();
+  EXPECT_TRUE(ash::Shell::GetInstance()->cursor_manager()->IsCursorVisible());
+  helper_->UpdateIfRequired();
   EXPECT_TRUE(helper_->IsTooltipVisible());
 }
 
@@ -147,7 +148,6 @@
   ui::test::EventGenerator generator(root_windows[1]);
   generator.MoveMouseRelativeTo(widget2->GetNativeView(),
                                 view2->bounds().CenterPoint());
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
 
   // Get rid of secondary display. This destroy's the tooltip's aura window. If
@@ -161,7 +161,6 @@
   ui::test::EventGenerator generator1(root_windows[0]);
   generator1.MoveMouseRelativeTo(widget1->GetNativeView(),
                                  view1->bounds().CenterPoint());
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
 }
 
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc
index 970a7d4..14f35658 100644
--- a/base/task_scheduler/scheduler_worker.cc
+++ b/base/task_scheduler/scheduler_worker.cc
@@ -216,6 +216,9 @@
 
 void SchedulerWorker::WakeUp() {
   AutoSchedulerLock auto_lock(thread_lock_);
+
+  DCHECK(!should_exit_for_testing_.IsSet());
+
   if (!thread_)
     CreateThreadAssertSynchronized();
 
@@ -227,17 +230,21 @@
   DCHECK(!should_exit_for_testing_.IsSet());
   should_exit_for_testing_.Set();
 
-  WakeUp();
+  std::unique_ptr<Thread> thread;
 
-  // Normally holding a lock and joining is dangerous. However, since this is
-  // only for testing, we're okay since the only scenario that could impact this
-  // is a call to Detach, which is disallowed by having the delegate always
-  // return false for the CanDetach call.
-  AutoSchedulerLock auto_lock(thread_lock_);
-  if (thread_)
-    thread_->Join();
+  {
+    AutoSchedulerLock auto_lock(thread_lock_);
 
-  thread_.reset();
+    if (thread_) {
+      // Make sure the thread is awake. It will see that
+      // |should_exit_for_testing_| is set and exit shortly after.
+      thread_->WakeUp();
+      thread = std::move(thread_);
+    }
+  }
+
+  if (thread)
+    thread->Join();
 }
 
 bool SchedulerWorker::ThreadAliveForTesting() const {
@@ -256,8 +263,14 @@
 }
 
 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::Detach() {
-  DCHECK(!should_exit_for_testing_.IsSet()) << "Worker was already joined";
   AutoSchedulerLock auto_lock(thread_lock_);
+
+  // Do not detach if the thread is being joined.
+  if (!thread_) {
+    DCHECK(should_exit_for_testing_.IsSet());
+    return nullptr;
+  }
+
   // If a wakeup is pending, then a WakeUp() came in while we were deciding to
   // detach. This means we can't go away anymore since we would break the
   // guarantee that we call GetWork() after a successful wakeup.
diff --git a/base/task_scheduler/scheduler_worker.h b/base/task_scheduler/scheduler_worker.h
index f75d45f..87fd8ed 100644
--- a/base/task_scheduler/scheduler_worker.h
+++ b/base/task_scheduler/scheduler_worker.h
@@ -76,8 +76,6 @@
     // - The next WakeUp() could be more costly due to new thread creation.
     // - The worker will take this as a signal that it can detach, but it is not
     //   obligated to do so.
-    // This MUST return false if SchedulerWorker::JoinForTesting() is in
-    // progress.
     virtual bool CanDetach(SchedulerWorker* worker) = 0;
 
     // Called by a thread before it detaches. This method is not allowed to
@@ -117,6 +115,10 @@
 
   // Joins this SchedulerWorker. If a Task is already running, it will be
   // allowed to complete its execution. This can only be called once.
+  //
+  // Note: A thread that detaches before JoinForTesting() is called may still be
+  // running after JoinForTesting() returns. However, it can't run tasks after
+  // JoinForTesting() returns.
   void JoinForTesting();
 
   // Returns true if the worker is alive.
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h
index 4693d63..2468b52 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl.h
+++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -97,12 +97,10 @@
   // allowed to complete their execution. This can only be called once.
   void JoinForTesting();
 
-  // Disallows worker thread detachment. If the suggested reclaim time is not
-  // TimeDelta::Max(), then the test should call this before the detach code can
-  // run. The safest place to do this is before the a set of work is dispatched
-  // (the worker pool is idle and steady state) or before the last
-  // synchronization point for all workers (all threads are busy and can't be
-  // reclaimed).
+  // Disallows worker detachment. If the suggested reclaim time is not
+  // TimeDelta::Max(), the test must call this before JoinForTesting() to reduce
+  // the chance of thread detachment during the process of joining all of the
+  // threads, and as a result, threads running after JoinForTesting().
   void DisallowWorkerDetachmentForTesting();
 
   // Returns the number of workers alive in this worker pool. The value may
diff --git a/base/task_scheduler/task_scheduler.h b/base/task_scheduler/task_scheduler.h
index 5d9344b..a73929c 100644
--- a/base/task_scheduler/task_scheduler.h
+++ b/base/task_scheduler/task_scheduler.h
@@ -38,6 +38,9 @@
   using WorkerPoolIndexForTraitsCallback =
       Callback<size_t(const TaskTraits& traits)>;
 
+  // Destroying a TaskScheduler is not allowed in production; it is always
+  // leaked. In tests, it should only be destroyed after JoinForTesting() has
+  // returned.
   virtual ~TaskScheduler() = default;
 
   // Posts |task| with a |delay| and specific |traits|. |delay| can be zero.
@@ -85,6 +88,10 @@
   // other threads during the call. Returns immediately when shutdown completes.
   virtual void FlushForTesting() = 0;
 
+  // Joins all threads. Tasks that are already running are allowed to complete
+  // their execution. This can only be called once.
+  virtual void JoinForTesting() = 0;
+
   // CreateAndSetSimpleTaskScheduler(), CreateAndSetDefaultTaskScheduler(), and
   // SetInstance() register a TaskScheduler to handle tasks posted through the
   // post_task.h API for this process. The registered TaskScheduler will only be
diff --git a/base/task_scheduler/task_scheduler_impl.cc b/base/task_scheduler/task_scheduler_impl.cc
index 827caae..f727c8c3 100644
--- a/base/task_scheduler/task_scheduler_impl.cc
+++ b/base/task_scheduler/task_scheduler_impl.cc
@@ -94,6 +94,8 @@
   DCHECK(!join_for_testing_returned_.IsSet());
 #endif
   for (const auto& worker_pool : worker_pools_)
+    worker_pool->DisallowWorkerDetachmentForTesting();
+  for (const auto& worker_pool : worker_pools_)
     worker_pool->JoinForTesting();
   service_thread_.Stop();
 #if DCHECK_IS_ON()
diff --git a/base/task_scheduler/task_scheduler_impl.h b/base/task_scheduler/task_scheduler_impl.h
index 3e6cfdb..7a083c6 100644
--- a/base/task_scheduler/task_scheduler_impl.h
+++ b/base/task_scheduler/task_scheduler_impl.h
@@ -44,9 +44,6 @@
       const WorkerPoolIndexForTraitsCallback&
           worker_pool_index_for_traits_callback);
 
-  // Destroying a TaskSchedulerImpl is not allowed in production; it is always
-  // leaked. In tests, it can only be destroyed after JoinForTesting() has
-  // returned.
   ~TaskSchedulerImpl() override;
 
   // TaskScheduler:
@@ -63,10 +60,7 @@
   std::vector<const HistogramBase*> GetHistograms() const override;
   void Shutdown() override;
   void FlushForTesting() override;
-
-  // Joins all threads. Tasks that are already running are allowed to complete
-  // their execution. This can only be called once.
-  void JoinForTesting();
+  void JoinForTesting() override;
 
  private:
   explicit TaskSchedulerImpl(const WorkerPoolIndexForTraitsCallback&
diff --git a/base/test/scoped_task_scheduler.cc b/base/test/scoped_task_scheduler.cc
index a57802c3..f068a199 100644
--- a/base/test/scoped_task_scheduler.cc
+++ b/base/test/scoped_task_scheduler.cc
@@ -53,6 +53,7 @@
   std::vector<const HistogramBase*> GetHistograms() const override;
   void Shutdown() override;
   void FlushForTesting() override;
+  void JoinForTesting() override;
 
   // Posts |task| to this TaskScheduler with |sequence_token|. Returns true on
   // success.
@@ -168,6 +169,10 @@
   NOTREACHED();
 }
 
+void TestTaskScheduler::JoinForTesting() {
+  // TestTaskScheduler doesn't create threads so this does nothing.
+}
+
 bool TestTaskScheduler::PostTask(std::unique_ptr<internal::Task> task,
                                  const SequenceToken& sequence_token) {
   DCHECK(task);
@@ -252,6 +257,10 @@
 ScopedTaskScheduler::~ScopedTaskScheduler() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK_EQ(task_scheduler_, TaskScheduler::GetInstance());
+
+  // Per contract, call JoinForTesting() before deleting the TaskScheduler.
+  TaskScheduler::GetInstance()->JoinForTesting();
+
   TaskScheduler::SetInstance(nullptr);
 }
 
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index 6e20339..5f9c9bfd 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -19,7 +19,6 @@
 #include "base/synchronization/lock.h"
 #include "base/task_scheduler/scheduler_worker_pool_params.h"
 #include "base/task_scheduler/task_scheduler.h"
-#include "base/task_scheduler/task_scheduler_impl.h"
 #include "base/test/sequenced_task_runner_test_template.h"
 #include "base/test/sequenced_worker_pool_owner.h"
 #include "base/test/task_runner_test_template.h"
@@ -296,8 +295,7 @@
   // Destroys and unregisters the registered TaskScheduler, if any.
   void DeleteTaskScheduler() {
     if (TaskScheduler::GetInstance()) {
-      static_cast<internal::TaskSchedulerImpl*>(TaskScheduler::GetInstance())
-          ->JoinForTesting();
+      TaskScheduler::GetInstance()->JoinForTesting();
       TaskScheduler::SetInstance(nullptr);
     }
   }
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 13b4506..e9e809a 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -99,7 +99,8 @@
     # memory consumption and link times unsustainable (crbug.com/630074).
     # Clang on windows does not have this issue.
     symbol_level = 1
-  } else if (!is_linux || is_debug || is_official_build || is_chromecast) {
+  } else if ((!is_nacl && !is_linux) || is_debug || is_official_build ||
+             is_chromecast) {
     # Linux is slowed by having symbols as part of the target binary, whereas
     # Mac and Windows have them separate, so in Release Linux, default them off,
     # but keep them on for Official builds and Chromecast builds.
diff --git a/build/toolchain/nacl/BUILD.gn b/build/toolchain/nacl/BUILD.gn
index 78748bd..89e642e 100644
--- a/build/toolchain/nacl/BUILD.gn
+++ b/build/toolchain/nacl/BUILD.gn
@@ -222,10 +222,6 @@
     toolchain_args = {
       current_cpu = toolchain_cpu
       is_clang = true
-
-      # Always build the IRT with full debugging symbols, regardless of
-      # how Chromium itself is being built (or other NaCl executables).
-      symbol_level = 2
     }
 
     # TODO(ncbray): depend on link script
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 911fe486..3a5f4d8 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -452,14 +452,13 @@
     "trees/latency_info_swap_promise_monitor.h",
     "trees/layer_tree.cc",
     "trees/layer_tree.h",
+    "trees/layer_tree_host.cc",
     "trees/layer_tree_host.h",
     "trees/layer_tree_host_client.h",
     "trees/layer_tree_host_common.cc",
     "trees/layer_tree_host_common.h",
     "trees/layer_tree_host_impl.cc",
     "trees/layer_tree_host_impl.h",
-    "trees/layer_tree_host_in_process.cc",
-    "trees/layer_tree_host_in_process.h",
     "trees/layer_tree_host_single_thread_client.h",
     "trees/layer_tree_impl.cc",
     "trees/layer_tree_impl.h",
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index d47561b0..28689cbd 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -86,7 +86,7 @@
 
 class MockLayerTree : public LayerTree {
  public:
-  MockLayerTree(LayerTreeHostInProcess::InitParams* params,
+  MockLayerTree(LayerTreeHost::InitParams* params,
                 LayerTreeHost* layer_tree_host)
       : LayerTree(params->mutator_host, layer_tree_host) {}
   ~MockLayerTree() override {}
@@ -94,11 +94,11 @@
   MOCK_METHOD0(SetNeedsFullTreeSync, void());
 };
 
-class MockLayerTreeHost : public LayerTreeHostInProcess {
+class MockLayerTreeHost : public LayerTreeHost {
  public:
   MockLayerTreeHost(LayerTreeHostSingleThreadClient* single_thread_client,
-                    LayerTreeHostInProcess::InitParams* params)
-      : LayerTreeHostInProcess(
+                    LayerTreeHost::InitParams* params)
+      : LayerTreeHost(
             params,
             CompositorMode::SINGLE_THREADED,
             base::MakeUnique<StrictMock<MockLayerTree>>(params, this)) {
@@ -129,7 +129,7 @@
   void SetUp() override {
     animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
-    LayerTreeHostInProcess::InitParams params;
+    LayerTreeHost::InitParams params;
     params.client = &fake_client_;
     params.settings = &settings_;
     params.task_graph_runner = &task_graph_runner_;
@@ -1039,15 +1039,14 @@
 
   std::unique_ptr<LayerTreeHost> Create(LayerTreeSettings settings,
                                         MutatorHost* mutator_host) {
-    LayerTreeHostInProcess::InitParams params;
+    LayerTreeHost::InitParams params;
     params.client = &client_;
     params.task_graph_runner = &task_graph_runner_;
     params.settings = &settings;
     params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
     params.mutator_host = mutator_host;
 
-    return LayerTreeHostInProcess::CreateSingleThreaded(&single_thread_client_,
-                                                        &params);
+    return LayerTreeHost::CreateSingleThreaded(&single_thread_client_, &params);
   }
 
  private:
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 76d8ec9..a4199c4b 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -302,22 +302,21 @@
 
   auto animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
-  LayerTreeHostInProcess::InitParams params;
+  LayerTreeHost::InitParams params;
   params.client = &host_client1;
   params.settings = &settings;
   params.task_graph_runner = &task_graph_runner;
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.mutator_host = animation_host.get();
   std::unique_ptr<LayerTreeHost> host1 =
-      LayerTreeHostInProcess::CreateSingleThreaded(&single_thread_client,
-                                                   &params);
+      LayerTreeHost::CreateSingleThreaded(&single_thread_client, &params);
   host1->SetVisible(true);
   host_client1.SetLayerTreeHost(host1.get());
 
   auto animation_host2 = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
   // TODO(sad): InitParams will be movable.
-  LayerTreeHostInProcess::InitParams params2;
+  LayerTreeHost::InitParams params2;
   params2.client = &host_client1;
   params2.settings = &settings;
   params2.task_graph_runner = &task_graph_runner;
@@ -325,8 +324,7 @@
   params2.client = &host_client2;
   params2.mutator_host = animation_host2.get();
   std::unique_ptr<LayerTreeHost> host2 =
-      LayerTreeHostInProcess::CreateSingleThreaded(&single_thread_client,
-                                                   &params2);
+      LayerTreeHost::CreateSingleThreaded(&single_thread_client, &params2);
   host2->SetVisible(true);
   host_client2.SetLayerTreeHost(host2.get());
 
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 13cfbd8f..82a29c4 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -114,7 +114,7 @@
 
     animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
-    LayerTreeHostInProcess::InitParams params;
+    LayerTreeHost::InitParams params;
     params.client = &fake_client_;
     params.settings = &layer_tree_settings_;
     params.task_graph_runner = &task_graph_runner_;
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 7d10bf7e..f0a6802 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -38,7 +38,7 @@
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/blocking_task_runner.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -65,13 +65,13 @@
                         gpu::CommandBufferId::FromUnsafeValue(0x123), value);
 }
 
-class MockLayerTreeHost : public LayerTreeHostInProcess {
+class MockLayerTreeHost : public LayerTreeHost {
  public:
   static std::unique_ptr<MockLayerTreeHost> Create(
       FakeLayerTreeHostClient* client,
       TaskGraphRunner* task_graph_runner,
       MutatorHost* mutator_host) {
-    LayerTreeHostInProcess::InitParams params;
+    LayerTreeHost::InitParams params;
     params.client = client;
     params.task_graph_runner = task_graph_runner;
     params.mutator_host = mutator_host;
@@ -87,8 +87,8 @@
   MOCK_METHOD0(StopRateLimiter, void());
 
  private:
-  explicit MockLayerTreeHost(LayerTreeHostInProcess::InitParams* params)
-      : LayerTreeHostInProcess(params, CompositorMode::SINGLE_THREADED) {
+  explicit MockLayerTreeHost(LayerTreeHost::InitParams* params)
+      : LayerTreeHost(params, CompositorMode::SINGLE_THREADED) {
     InitializeSingleThreaded(&single_thread_client_,
                              base::ThreadTaskRunnerHandle::Get());
   }
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc
index 8a859f66..f574632 100644
--- a/cc/surfaces/surface_factory.cc
+++ b/cc/surfaces/surface_factory.cc
@@ -67,7 +67,7 @@
     gfx::Size frame_size;
     // CompositorFrames may not be populated with a RenderPass in unit tests.
     if (!frame.render_pass_list.empty())
-      frame_size = frame.render_pass_list[0]->output_rect.size();
+      frame_size = frame.render_pass_list.back()->output_rect.size();
     manager_->SurfaceCreated(SurfaceInfo(
         surface->surface_id(), frame.metadata.device_scale_factor, frame_size));
   }
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index 8099815..6deff8b 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -87,6 +87,7 @@
   void OnSurfaceCreated(const SurfaceInfo& surface_info) override {
     EXPECT_EQ(kArbitraryFrameSinkId, surface_info.id().frame_sink_id());
     last_created_surface_id_ = surface_info.id();
+    last_surface_info_ = surface_info;
   }
 
   void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
@@ -155,6 +156,7 @@
   std::unique_ptr<SurfaceFactory> factory_;
   LocalFrameId local_frame_id_;
   SurfaceId last_created_surface_id_;
+  SurfaceInfo last_surface_info_;
 
   // This is the sync token submitted with the frame. It should never be
   // returned to the client.
@@ -669,5 +671,28 @@
   EXPECT_TRUE(called3);
 }
 
+// Check whether the SurfaceInfo object is created and populated correctly
+// after the frame submission.
+TEST_F(SurfaceFactoryTest, SurfaceInfo) {
+  CompositorFrame frame;
+
+  auto render_pass = RenderPass::Create();
+  render_pass->SetNew(1, gfx::Rect(5, 6), gfx::Rect(), gfx::Transform());
+  frame.render_pass_list.push_back(std::move(render_pass));
+
+  render_pass = RenderPass::Create();
+  render_pass->SetNew(2, gfx::Rect(7, 8), gfx::Rect(), gfx::Transform());
+  frame.render_pass_list.push_back(std::move(render_pass));
+
+  frame.metadata.device_scale_factor = 2.5f;
+
+  factory_->SubmitCompositorFrame(local_frame_id_, std::move(frame),
+                                  SurfaceFactory::DrawCallback());
+  SurfaceId expected_surface_id(factory_->frame_sink_id(), local_frame_id_);
+  EXPECT_EQ(expected_surface_id, last_surface_info_.id());
+  EXPECT_EQ(2.5f, last_surface_info_.device_scale_factor());
+  EXPECT_EQ(gfx::Size(7, 8), last_surface_info_.size_in_pixels());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/surfaces/surface_reference_owner.h b/cc/surfaces/surface_reference_owner.h
index 78614f7..8aa791c 100644
--- a/cc/surfaces/surface_reference_owner.h
+++ b/cc/surfaces/surface_reference_owner.h
@@ -13,6 +13,8 @@
 // SurfaceReferenceFactory::CreateReference as the reference owner.
 class SurfaceReferenceOwner {
  public:
+  virtual ~SurfaceReferenceOwner() {}
+
   virtual SurfaceSequenceGenerator* GetSurfaceSequenceGenerator() = 0;
 };
 
diff --git a/cc/test/fake_layer_tree_host.cc b/cc/test/fake_layer_tree_host.cc
index 6143a46..d15255e 100644
--- a/cc/test/fake_layer_tree_host.cc
+++ b/cc/test/fake_layer_tree_host.cc
@@ -27,9 +27,9 @@
 }  // namespace
 
 FakeLayerTreeHost::FakeLayerTreeHost(FakeLayerTreeHostClient* client,
-                                     LayerTreeHostInProcess::InitParams* params,
+                                     LayerTreeHost::InitParams* params,
                                      CompositorMode mode)
-    : LayerTreeHostInProcess(
+    : LayerTreeHost(
           params,
           mode,
           base::MakeUnique<FakeLayerTree>(params->mutator_host, this)),
@@ -70,7 +70,7 @@
     MutatorHost* mutator_host,
     const LayerTreeSettings& settings,
     CompositorMode mode) {
-  LayerTreeHostInProcess::InitParams params;
+  LayerTreeHost::InitParams params;
   params.client = client;
   params.settings = &settings;
   params.task_graph_runner = task_graph_runner;
diff --git a/cc/test/fake_layer_tree_host.h b/cc/test/fake_layer_tree_host.h
index 81e498ea..2aa30c6 100644
--- a/cc/test/fake_layer_tree_host.h
+++ b/cc/test/fake_layer_tree_host.h
@@ -9,7 +9,7 @@
 #include "cc/test/fake_impl_task_runner_provider.h"
 #include "cc/test/fake_layer_tree_host_client.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/tree_synchronizer.h"
 
@@ -18,7 +18,7 @@
 class MutatorHost;
 class TestTaskGraphRunner;
 
-class FakeLayerTreeHost : public LayerTreeHostInProcess {
+class FakeLayerTreeHost : public LayerTreeHost {
  public:
   static std::unique_ptr<FakeLayerTreeHost> Create(
       FakeLayerTreeHostClient* client,
@@ -65,14 +65,14 @@
   LayerTreeImpl* active_tree() { return host_impl_.active_tree(); }
   LayerTreeImpl* pending_tree() { return host_impl_.pending_tree(); }
 
-  using LayerTreeHostInProcess::ScheduleMicroBenchmark;
-  using LayerTreeHostInProcess::SendMessageToMicroBenchmark;
-  using LayerTreeHostInProcess::InitializeSingleThreaded;
-  using LayerTreeHostInProcess::InitializeForTesting;
-  using LayerTreeHostInProcess::RecordGpuRasterizationHistogram;
-  using LayerTreeHostInProcess::SetUIResourceManagerForTesting;
+  using LayerTreeHost::ScheduleMicroBenchmark;
+  using LayerTreeHost::SendMessageToMicroBenchmark;
+  using LayerTreeHost::InitializeSingleThreaded;
+  using LayerTreeHost::InitializeForTesting;
+  using LayerTreeHost::RecordGpuRasterizationHistogram;
+  using LayerTreeHost::SetUIResourceManagerForTesting;
 
-  void UpdateLayers() { LayerTreeHostInProcess::UpdateLayers(); }
+  void UpdateLayers() { LayerTreeHost::UpdateLayers(); }
 
   MicroBenchmarkController* GetMicroBenchmarkController() {
     return &micro_benchmark_controller_;
@@ -82,7 +82,7 @@
   void reset_needs_commit() { needs_commit_ = false; }
 
   FakeLayerTreeHost(FakeLayerTreeHostClient* client,
-                    LayerTreeHostInProcess::InitParams* params,
+                    LayerTreeHost::InitParams* params,
                     CompositorMode mode);
 
  private:
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 46cdf6d..149a01ba 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -332,7 +332,7 @@
 };
 
 // Adapts LayerTreeHost for test. Injects LayerTreeHostImplForTesting.
-class LayerTreeHostForTesting : public LayerTreeHostInProcess {
+class LayerTreeHostForTesting : public LayerTreeHost {
  public:
   static std::unique_ptr<LayerTreeHostForTesting> Create(
       TestHooks* test_hooks,
@@ -344,7 +344,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
       MutatorHost* mutator_host) {
-    LayerTreeHostInProcess::InitParams params;
+    LayerTreeHost::InitParams params;
     params.client = client;
     params.task_graph_runner = task_graph_runner;
     params.settings = &settings;
@@ -386,22 +386,22 @@
   void SetNeedsCommit() override {
     if (!test_started_)
       return;
-    LayerTreeHostInProcess::SetNeedsCommit();
+    LayerTreeHost::SetNeedsCommit();
   }
 
   void SetNeedsUpdateLayers() override {
     if (!test_started_)
       return;
-    LayerTreeHostInProcess::SetNeedsUpdateLayers();
+    LayerTreeHost::SetNeedsUpdateLayers();
   }
 
   void set_test_started(bool started) { test_started_ = started; }
 
  private:
   LayerTreeHostForTesting(TestHooks* test_hooks,
-                          LayerTreeHostInProcess::InitParams* params,
+                          LayerTreeHost::InitParams* params,
                           CompositorMode mode)
-      : LayerTreeHostInProcess(params, mode),
+      : LayerTreeHost(params, mode),
         test_hooks_(test_hooks),
         test_started_(false) {}
 
@@ -594,13 +594,9 @@
 
   animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
-  std::unique_ptr<LayerTreeHostForTesting> layer_tree_host_for_testing =
-      LayerTreeHostForTesting::Create(
-          this, mode_, client_.get(), client_.get(), task_graph_runner_.get(),
-          settings_, main_task_runner, impl_task_runner, animation_host_.get());
-  layer_tree_host_in_process_ = layer_tree_host_for_testing.get();
-  layer_tree_host_ = std::move(layer_tree_host_for_testing);
-
+  layer_tree_host_ = LayerTreeHostForTesting::Create(
+      this, mode_, client_.get(), client_.get(), task_graph_runner_.get(),
+      settings_, main_task_runner, impl_task_runner, animation_host_.get());
   ASSERT_TRUE(layer_tree_host_);
 
   main_task_runner_ =
@@ -631,8 +627,8 @@
 
   // Allow commits to happen once BeginTest() has had a chance to post tasks
   // so that those tasks will happen before the first commit.
-  if (layer_tree_host_in_process_) {
-    static_cast<LayerTreeHostForTesting*>(layer_tree_host_in_process_)
+  if (layer_tree_host_) {
+    static_cast<LayerTreeHostForTesting*>(layer_tree_host_.get())
         ->set_test_started(true);
   }
 }
@@ -658,10 +654,10 @@
 
 void LayerTreeTest::RealEndTest() {
   // TODO(mithro): Make this method only end when not inside an impl frame.
-  bool main_frame_will_happen = layer_tree_host_in_process_
-                                    ? layer_tree_host_in_process_->proxy()
-                                          ->MainFrameWillHappenForTesting()
-                                    : false;
+  bool main_frame_will_happen =
+      layer_tree_host_
+          ? layer_tree_host_->proxy()->MainFrameWillHappenForTesting()
+          : false;
 
   if (main_frame_will_happen && !timed_out_) {
     main_task_runner_->PostTask(
@@ -820,7 +816,6 @@
   if (layer_tree_host_ && layer_tree_host_->GetLayerTree()->root_layer())
     layer_tree_host_->GetLayerTree()->root_layer()->SetLayerTreeHost(NULL);
   layer_tree_host_ = nullptr;
-  layer_tree_host_in_process_ = nullptr;
 }
 
 TaskRunnerProvider* LayerTreeTest::task_runner_provider() const {
@@ -839,15 +834,8 @@
   return layer_tree_host_.get();
 }
 
-LayerTreeHostInProcess* LayerTreeTest::layer_tree_host_in_process() {
-  DCHECK(task_runner_provider()->IsMainThread() ||
-         task_runner_provider()->IsMainThreadBlocked());
-  return layer_tree_host_in_process_;
-}
-
 Proxy* LayerTreeTest::proxy() {
-  return layer_tree_host_in_process() ? layer_tree_host_in_process()->proxy()
-                                      : NULL;
+  return layer_tree_host() ? layer_tree_host()->proxy() : NULL;
 }
 
 }  // namespace cc
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index b9a5090..fbe9996f 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -12,8 +12,8 @@
 #include "cc/test/test_hooks.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/compositor_mode.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_host_impl.h"
-#include "cc/trees/layer_tree_host_in_process.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -122,7 +122,6 @@
   bool TestEnded() const { return ended_; }
 
   LayerTreeHost* layer_tree_host();
-  LayerTreeHostInProcess* layer_tree_host_in_process();
   LayerTree* layer_tree() { return layer_tree_host()->GetLayerTree(); }
   SharedBitmapManager* shared_bitmap_manager() const {
     return shared_bitmap_manager_.get();
@@ -173,7 +172,6 @@
   std::unique_ptr<LayerTreeHostClientForTesting> client_;
   std::unique_ptr<LayerTreeHost> layer_tree_host_;
   std::unique_ptr<AnimationHost> animation_host_;
-  LayerTreeHostInProcess* layer_tree_host_in_process_;
 
   bool beginning_ = false;
   bool end_when_begin_returns_ = false;
diff --git a/cc/trees/layer_tree_host_in_process.cc b/cc/trees/layer_tree_host.cc
similarity index 83%
rename from cc/trees/layer_tree_host_in_process.cc
rename to cc/trees/layer_tree_host.cc
index 22bee761..b849f50 100644
--- a/cc/trees/layer_tree_host_in_process.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -61,43 +61,43 @@
 
 namespace cc {
 
-LayerTreeHostInProcess::InitParams::InitParams() {}
+LayerTreeHost::InitParams::InitParams() {}
 
-LayerTreeHostInProcess::InitParams::~InitParams() {}
+LayerTreeHost::InitParams::~InitParams() {}
 
-std::unique_ptr<LayerTreeHostInProcess> LayerTreeHostInProcess::CreateThreaded(
+std::unique_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
     scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
     InitParams* params) {
   DCHECK(params->main_task_runner.get());
   DCHECK(impl_task_runner.get());
   DCHECK(params->settings);
-  std::unique_ptr<LayerTreeHostInProcess> layer_tree_host(
-      new LayerTreeHostInProcess(params, CompositorMode::THREADED));
+  std::unique_ptr<LayerTreeHost> layer_tree_host(
+      new LayerTreeHost(params, CompositorMode::THREADED));
   layer_tree_host->InitializeThreaded(params->main_task_runner,
                                       impl_task_runner);
   return layer_tree_host;
 }
 
-std::unique_ptr<LayerTreeHostInProcess>
-LayerTreeHostInProcess::CreateSingleThreaded(
+std::unique_ptr<LayerTreeHost>
+LayerTreeHost::CreateSingleThreaded(
     LayerTreeHostSingleThreadClient* single_thread_client,
     InitParams* params) {
   DCHECK(params->settings);
-  std::unique_ptr<LayerTreeHostInProcess> layer_tree_host(
-      new LayerTreeHostInProcess(params, CompositorMode::SINGLE_THREADED));
+  std::unique_ptr<LayerTreeHost> layer_tree_host(
+      new LayerTreeHost(params, CompositorMode::SINGLE_THREADED));
   layer_tree_host->InitializeSingleThreaded(single_thread_client,
                                             params->main_task_runner);
   return layer_tree_host;
 }
 
-LayerTreeHostInProcess::LayerTreeHostInProcess(InitParams* params,
+LayerTreeHost::LayerTreeHost(InitParams* params,
                                                CompositorMode mode)
-    : LayerTreeHostInProcess(
+    : LayerTreeHost(
           params,
           mode,
           base::MakeUnique<LayerTree>(params->mutator_host, this)) {}
 
-LayerTreeHostInProcess::LayerTreeHostInProcess(
+LayerTreeHost::LayerTreeHost(
     InitParams* params,
     CompositorMode mode,
     std::unique_ptr<LayerTree> layer_tree)
@@ -125,7 +125,7 @@
       debug_state_.RecordRenderingStats());
 }
 
-void LayerTreeHostInProcess::InitializeThreaded(
+void LayerTreeHost::InitializeThreaded(
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
   task_runner_provider_ =
@@ -135,7 +135,7 @@
   InitializeProxy(std::move(proxy_main));
 }
 
-void LayerTreeHostInProcess::InitializeSingleThreaded(
+void LayerTreeHost::InitializeSingleThreaded(
     LayerTreeHostSingleThreadClient* single_thread_client,
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
   task_runner_provider_ = TaskRunnerProvider::Create(main_task_runner, nullptr);
@@ -143,25 +143,25 @@
                                             task_runner_provider_.get()));
 }
 
-void LayerTreeHostInProcess::InitializeForTesting(
+void LayerTreeHost::InitializeForTesting(
     std::unique_ptr<TaskRunnerProvider> task_runner_provider,
     std::unique_ptr<Proxy> proxy_for_testing) {
   task_runner_provider_ = std::move(task_runner_provider);
   InitializeProxy(std::move(proxy_for_testing));
 }
 
-void LayerTreeHostInProcess::SetTaskRunnerProviderForTesting(
+void LayerTreeHost::SetTaskRunnerProviderForTesting(
     std::unique_ptr<TaskRunnerProvider> task_runner_provider) {
   DCHECK(!task_runner_provider_);
   task_runner_provider_ = std::move(task_runner_provider);
 }
 
-void LayerTreeHostInProcess::SetUIResourceManagerForTesting(
+void LayerTreeHost::SetUIResourceManagerForTesting(
     std::unique_ptr<UIResourceManager> ui_resource_manager) {
   ui_resource_manager_ = std::move(ui_resource_manager);
 }
 
-void LayerTreeHostInProcess::InitializeProxy(std::unique_ptr<Proxy> proxy) {
+void LayerTreeHost::InitializeProxy(std::unique_ptr<Proxy> proxy) {
   TRACE_EVENT0("cc", "LayerTreeHostInProcess::InitializeForReal");
   DCHECK(task_runner_provider_);
 
@@ -172,7 +172,7 @@
       proxy_->SupportsImplScrolling());
 }
 
-LayerTreeHostInProcess::~LayerTreeHostInProcess() {
+LayerTreeHost::~LayerTreeHost() {
   // Track when we're inside a main frame to see if compositor is being
   // destroyed midway which causes a crash. crbug.com/654672
   CHECK(!inside_main_frame_);
@@ -190,81 +190,81 @@
   }
 }
 
-int LayerTreeHostInProcess::GetId() const {
+int LayerTreeHost::GetId() const {
   return id_;
 }
 
-int LayerTreeHostInProcess::SourceFrameNumber() const {
+int LayerTreeHost::SourceFrameNumber() const {
   return source_frame_number_;
 }
 
-LayerTree* LayerTreeHostInProcess::GetLayerTree() {
+LayerTree* LayerTreeHost::GetLayerTree() {
   return layer_tree_.get();
 }
 
-const LayerTree* LayerTreeHostInProcess::GetLayerTree() const {
+const LayerTree* LayerTreeHost::GetLayerTree() const {
   return layer_tree_.get();
 }
 
-UIResourceManager* LayerTreeHostInProcess::GetUIResourceManager() const {
+UIResourceManager* LayerTreeHost::GetUIResourceManager() const {
   return ui_resource_manager_.get();
 }
 
-TaskRunnerProvider* LayerTreeHostInProcess::GetTaskRunnerProvider() const {
+TaskRunnerProvider* LayerTreeHost::GetTaskRunnerProvider() const {
   return task_runner_provider_.get();
 }
 
-SwapPromiseManager* LayerTreeHostInProcess::GetSwapPromiseManager() {
+SwapPromiseManager* LayerTreeHost::GetSwapPromiseManager() {
   return &swap_promise_manager_;
 }
 
-const LayerTreeSettings& LayerTreeHostInProcess::GetSettings() const {
+const LayerTreeSettings& LayerTreeHost::GetSettings() const {
   return settings_;
 }
 
-void LayerTreeHostInProcess::SetFrameSinkId(const FrameSinkId& frame_sink_id) {
+void LayerTreeHost::SetFrameSinkId(const FrameSinkId& frame_sink_id) {
   surface_sequence_generator_.set_frame_sink_id(frame_sink_id);
 }
 
-void LayerTreeHostInProcess::QueueSwapPromise(
+void LayerTreeHost::QueueSwapPromise(
     std::unique_ptr<SwapPromise> swap_promise) {
   swap_promise_manager_.QueueSwapPromise(std::move(swap_promise));
 }
 
 SurfaceSequenceGenerator*
-LayerTreeHostInProcess::GetSurfaceSequenceGenerator() {
+LayerTreeHost::GetSurfaceSequenceGenerator() {
   return &surface_sequence_generator_;
 }
 
-void LayerTreeHostInProcess::WillBeginMainFrame() {
+void LayerTreeHost::WillBeginMainFrame() {
   inside_main_frame_ = true;
   devtools_instrumentation::WillBeginMainThreadFrame(GetId(),
                                                      SourceFrameNumber());
   client_->WillBeginMainFrame();
 }
 
-void LayerTreeHostInProcess::DidBeginMainFrame() {
+void LayerTreeHost::DidBeginMainFrame() {
   inside_main_frame_ = false;
   client_->DidBeginMainFrame();
 }
 
-void LayerTreeHostInProcess::BeginMainFrameNotExpectedSoon() {
+void LayerTreeHost::BeginMainFrameNotExpectedSoon() {
   client_->BeginMainFrameNotExpectedSoon();
 }
 
-void LayerTreeHostInProcess::BeginMainFrame(const BeginFrameArgs& args) {
+void LayerTreeHost::BeginMainFrame(const BeginFrameArgs& args) {
   client_->BeginMainFrame(args);
 }
 
-void LayerTreeHostInProcess::DidStopFlinging() {
+void LayerTreeHost::DidStopFlinging() {
   proxy_->MainThreadHasStoppedFlinging();
 }
 
-const LayerTreeDebugState& LayerTreeHostInProcess::GetDebugState() const {
+const LayerTreeDebugState& LayerTreeHost::GetDebugState() const {
   return debug_state_;
 }
 
-void LayerTreeHostInProcess::RequestMainFrameUpdate() {
+void LayerTreeHost::RequestMainFrameUpdate() {
   client_->UpdateLayerTreeHost();
 }
 
@@ -273,7 +273,7 @@
 // code that is logically a main thread operation, e.g. deletion of a Layer,
 // should be delayed until the LayerTreeHostInProcess::CommitComplete, which
 // will run after the commit, but on the main thread.
-void LayerTreeHostInProcess::FinishCommitOnImplThread(
+void LayerTreeHost::FinishCommitOnImplThread(
     LayerTreeHostImpl* host_impl) {
   DCHECK(task_runner_provider_->IsImplThread());
 
@@ -344,14 +344,14 @@
   layer_tree_->property_trees()->ResetAllChangeTracking();
 }
 
-void LayerTreeHostInProcess::WillCommit() {
+void LayerTreeHost::WillCommit() {
   swap_promise_manager_.WillCommit();
   client_->WillCommit();
 }
 
-void LayerTreeHostInProcess::UpdateHudLayer() {}
+void LayerTreeHost::UpdateHudLayer() {}
 
-void LayerTreeHostInProcess::CommitComplete() {
+void LayerTreeHost::CommitComplete() {
   source_frame_number_++;
   client_->DidCommit();
   if (did_complete_scale_animation_) {
@@ -360,7 +360,7 @@
   }
 }
 
-void LayerTreeHostInProcess::SetCompositorFrameSink(
+void LayerTreeHost::SetCompositorFrameSink(
     std::unique_ptr<CompositorFrameSink> surface) {
   TRACE_EVENT0("cc", "LayerTreeHostInProcess::SetCompositorFrameSink");
   DCHECK(surface);
@@ -371,7 +371,7 @@
 }
 
 std::unique_ptr<CompositorFrameSink>
-LayerTreeHostInProcess::ReleaseCompositorFrameSink() {
+LayerTreeHost::ReleaseCompositorFrameSink() {
   DCHECK(!visible_);
 
   DidLoseCompositorFrameSink();
@@ -379,17 +379,17 @@
   return std::move(current_compositor_frame_sink_);
 }
 
-void LayerTreeHostInProcess::RequestNewCompositorFrameSink() {
+void LayerTreeHost::RequestNewCompositorFrameSink() {
   client_->RequestNewCompositorFrameSink();
 }
 
-void LayerTreeHostInProcess::DidInitializeCompositorFrameSink() {
+void LayerTreeHost::DidInitializeCompositorFrameSink() {
   DCHECK(new_compositor_frame_sink_);
   current_compositor_frame_sink_ = std::move(new_compositor_frame_sink_);
   client_->DidInitializeCompositorFrameSink();
 }
 
-void LayerTreeHostInProcess::DidFailToInitializeCompositorFrameSink() {
+void LayerTreeHost::DidFailToInitializeCompositorFrameSink() {
   DCHECK(new_compositor_frame_sink_);
   // Note: It is safe to drop all output surface references here as
   // LayerTreeHostImpl will not keep a pointer to either the old or
@@ -400,7 +400,7 @@
 }
 
 std::unique_ptr<LayerTreeHostImpl>
-LayerTreeHostInProcess::CreateLayerTreeHostImpl(
+LayerTreeHost::CreateLayerTreeHostImpl(
     LayerTreeHostImplClient* client) {
   DCHECK(task_runner_provider_->IsImplThread());
 
@@ -420,62 +420,62 @@
   return host_impl;
 }
 
-void LayerTreeHostInProcess::DidLoseCompositorFrameSink() {
+void LayerTreeHost::DidLoseCompositorFrameSink() {
   TRACE_EVENT0("cc", "LayerTreeHostInProcess::DidLoseCompositorFrameSink");
   DCHECK(task_runner_provider_->IsMainThread());
   SetNeedsCommit();
 }
 
-void LayerTreeHostInProcess::SetDeferCommits(bool defer_commits) {
+void LayerTreeHost::SetDeferCommits(bool defer_commits) {
   proxy_->SetDeferCommits(defer_commits);
 }
 
 DISABLE_CFI_PERF
-void LayerTreeHostInProcess::SetNeedsAnimate() {
+void LayerTreeHost::SetNeedsAnimate() {
   proxy_->SetNeedsAnimate();
   swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
 }
 
 DISABLE_CFI_PERF
-void LayerTreeHostInProcess::SetNeedsUpdateLayers() {
+void LayerTreeHost::SetNeedsUpdateLayers() {
   proxy_->SetNeedsUpdateLayers();
   swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
 }
 
-void LayerTreeHostInProcess::SetNeedsCommit() {
+void LayerTreeHost::SetNeedsCommit() {
   proxy_->SetNeedsCommit();
   swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
 }
 
-void LayerTreeHostInProcess::SetNeedsRecalculateRasterScales() {
+void LayerTreeHost::SetNeedsRecalculateRasterScales() {
   next_commit_forces_recalculate_raster_scales_ = true;
   proxy_->SetNeedsCommit();
 }
 
-void LayerTreeHostInProcess::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
+void LayerTreeHost::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
   proxy_->SetNeedsRedraw(damage_rect);
 }
 
-bool LayerTreeHostInProcess::CommitRequested() const {
+bool LayerTreeHost::CommitRequested() const {
   return proxy_->CommitRequested();
 }
 
-void LayerTreeHostInProcess::SetNextCommitWaitsForActivation() {
+void LayerTreeHost::SetNextCommitWaitsForActivation() {
   proxy_->SetNextCommitWaitsForActivation();
 }
 
-void LayerTreeHostInProcess::SetNextCommitForcesRedraw() {
+void LayerTreeHost::SetNextCommitForcesRedraw() {
   next_commit_forces_redraw_ = true;
   proxy_->SetNeedsUpdateLayers();
 }
 
-void LayerTreeHostInProcess::SetAnimationEvents(
+void LayerTreeHost::SetAnimationEvents(
     std::unique_ptr<MutatorEvents> events) {
   DCHECK(task_runner_provider_->IsMainThread());
   layer_tree_->mutator_host()->SetAnimationEvents(std::move(events));
 }
 
-void LayerTreeHostInProcess::SetDebugState(
+void LayerTreeHost::SetDebugState(
     const LayerTreeDebugState& debug_state) {
   LayerTreeDebugState new_debug_state =
       LayerTreeDebugState::Unite(settings_.initial_debug_state, debug_state);
@@ -491,12 +491,12 @@
   SetNeedsCommit();
 }
 
-void LayerTreeHostInProcess::ResetGpuRasterizationTracking() {
+void LayerTreeHost::ResetGpuRasterizationTracking() {
   content_is_suitable_for_gpu_rasterization_ = true;
   gpu_rasterization_histogram_recorded_ = false;
 }
 
-void LayerTreeHostInProcess::SetHasGpuRasterizationTrigger(bool has_trigger) {
+void LayerTreeHost::SetHasGpuRasterizationTrigger(bool has_trigger) {
   if (has_trigger == has_gpu_rasterization_trigger_)
     return;
 
@@ -506,7 +506,7 @@
       TRACE_EVENT_SCOPE_THREAD, "has_trigger", has_gpu_rasterization_trigger_);
 }
 
-void LayerTreeHostInProcess::ApplyPageScaleDeltaFromImplSide(
+void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(
     float page_scale_delta) {
   DCHECK(CommitRequested());
   if (page_scale_delta == 1.f)
@@ -515,22 +515,22 @@
   layer_tree_->SetPageScaleFromImplSide(page_scale);
 }
 
-void LayerTreeHostInProcess::SetVisible(bool visible) {
+void LayerTreeHost::SetVisible(bool visible) {
   if (visible_ == visible)
     return;
   visible_ = visible;
   proxy_->SetVisible(visible);
 }
 
-bool LayerTreeHostInProcess::IsVisible() const {
+bool LayerTreeHost::IsVisible() const {
   return visible_;
 }
 
-void LayerTreeHostInProcess::NotifyInputThrottledUntilCommit() {
+void LayerTreeHost::NotifyInputThrottledUntilCommit() {
   proxy_->NotifyInputThrottledUntilCommit();
 }
 
-void LayerTreeHostInProcess::LayoutAndUpdateLayers() {
+void LayerTreeHost::LayoutAndUpdateLayers() {
   DCHECK(IsSingleThreaded());
   // This function is only valid when not using the scheduler.
   DCHECK(!settings_.single_thread_proxy_scheduler);
@@ -538,7 +538,7 @@
   UpdateLayers();
 }
 
-void LayerTreeHostInProcess::Composite(base::TimeTicks frame_begin_time) {
+void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
   DCHECK(IsSingleThreaded());
   // This function is only valid when not using the scheduler.
   DCHECK(!settings_.single_thread_proxy_scheduler);
@@ -561,7 +561,7 @@
   return 4;
 }
 
-bool LayerTreeHostInProcess::UpdateLayers() {
+bool LayerTreeHost::UpdateLayers() {
   if (!layer_tree_->root_layer()) {
     layer_tree_->property_trees()->clear();
     return false;
@@ -584,11 +584,11 @@
   return result || next_commit_forces_redraw_;
 }
 
-void LayerTreeHostInProcess::DidCompletePageScaleAnimation() {
+void LayerTreeHost::DidCompletePageScaleAnimation() {
   did_complete_scale_animation_ = true;
 }
 
-void LayerTreeHostInProcess::RecordGpuRasterizationHistogram() {
+void LayerTreeHost::RecordGpuRasterizationHistogram() {
   // Gpu rasterization is only supported for Renderer compositors.
   // Checking for IsSingleThreaded() to exclude Browser compositors.
   if (gpu_rasterization_histogram_recorded_ || IsSingleThreaded())
@@ -614,7 +614,7 @@
   gpu_rasterization_histogram_recorded_ = true;
 }
 
-bool LayerTreeHostInProcess::DoUpdateLayers(Layer* root_layer) {
+bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) {
   TRACE_EVENT1("cc", "LayerTreeHostInProcess::DoUpdateLayers",
                "source_frame_number", SourceFrameNumber());
 
@@ -693,7 +693,7 @@
   return did_paint_content;
 }
 
-void LayerTreeHostInProcess::ApplyViewportDeltas(ScrollAndScaleSet* info) {
+void LayerTreeHost::ApplyViewportDeltas(ScrollAndScaleSet* info) {
   gfx::Vector2dF inner_viewport_scroll_delta;
   if (info->inner_viewport_scroll.layer_id != Layer::INVALID_ID)
     inner_viewport_scroll_delta = info->inner_viewport_scroll.scroll_delta;
@@ -724,7 +724,7 @@
   SetNeedsUpdateLayers();
 }
 
-void LayerTreeHostInProcess::ApplyScrollAndScale(ScrollAndScaleSet* info) {
+void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) {
   for (auto& swap_promise : info->swap_promises) {
     TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
                            TRACE_ID_DONT_MANGLE(swap_promise->TraceId()),
@@ -756,12 +756,12 @@
   ApplyViewportDeltas(info);
 }
 
-const base::WeakPtr<InputHandler>& LayerTreeHostInProcess::GetInputHandler()
+const base::WeakPtr<InputHandler>& LayerTreeHost::GetInputHandler()
     const {
   return input_handler_weak_ptr_;
 }
 
-void LayerTreeHostInProcess::UpdateBrowserControlsState(
+void LayerTreeHost::UpdateBrowserControlsState(
     BrowserControlsState constraints,
     BrowserControlsState current,
     bool animate) {
@@ -770,7 +770,7 @@
   proxy_->UpdateBrowserControlsState(constraints, current, animate);
 }
 
-void LayerTreeHostInProcess::AnimateLayers(base::TimeTicks monotonic_time) {
+void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) {
   MutatorHost* mutator_host = layer_tree_->mutator_host();
   std::unique_ptr<MutatorEvents> events = mutator_host->CreateEvents();
 
@@ -781,7 +781,7 @@
     layer_tree_->property_trees()->needs_rebuild = true;
 }
 
-int LayerTreeHostInProcess::ScheduleMicroBenchmark(
+int LayerTreeHost::ScheduleMicroBenchmark(
     const std::string& benchmark_name,
     std::unique_ptr<base::Value> value,
     const MicroBenchmark::DoneCallback& callback) {
@@ -789,24 +789,24 @@
                                                  std::move(value), callback);
 }
 
-bool LayerTreeHostInProcess::SendMessageToMicroBenchmark(
+bool LayerTreeHost::SendMessageToMicroBenchmark(
     int id,
     std::unique_ptr<base::Value> value) {
   return micro_benchmark_controller_.SendMessage(id, std::move(value));
 }
 
-void LayerTreeHostInProcess::SetLayerTreeMutator(
+void LayerTreeHost::SetLayerTreeMutator(
     std::unique_ptr<LayerTreeMutator> mutator) {
   proxy_->SetMutator(std::move(mutator));
 }
 
-bool LayerTreeHostInProcess::IsSingleThreaded() const {
+bool LayerTreeHost::IsSingleThreaded() const {
   DCHECK(compositor_mode_ != CompositorMode::SINGLE_THREADED ||
          !task_runner_provider_->HasImplThread());
   return compositor_mode_ == CompositorMode::SINGLE_THREADED;
 }
 
-bool LayerTreeHostInProcess::IsThreaded() const {
+bool LayerTreeHost::IsThreaded() const {
   DCHECK(compositor_mode_ != CompositorMode::THREADED ||
          task_runner_provider_->HasImplThread());
   return compositor_mode_ == CompositorMode::THREADED;
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index f7aade64..7beade4 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -1,94 +1,138 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// 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_LAYER_TREE_HOST_H_
 #define CC_TREES_LAYER_TREE_HOST_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/cancelable_callback.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
 #include "cc/base/cc_export.h"
 #include "cc/debug/micro_benchmark.h"
+#include "cc/debug/micro_benchmark_controller.h"
 #include "cc/input/browser_controls_state.h"
+#include "cc/input/event_listener_properties.h"
+#include "cc/input/input_handler.h"
+#include "cc/input/layer_selection_bound.h"
+#include "cc/input/scrollbar.h"
+#include "cc/layers/layer_collections.h"
+#include "cc/layers/layer_list_iterator.h"
+#include "cc/output/compositor_frame_sink.h"
+#include "cc/output/swap_promise.h"
+#include "cc/resources/resource_format.h"
 #include "cc/surfaces/surface_reference_owner.h"
-
-namespace base {
-class TimeTicks;
-}  // namespace base
-
-namespace gfx {
-class Rect;
-}  // namespace gfx
+#include "cc/surfaces/surface_sequence_generator.h"
+#include "cc/trees/compositor_mode.h"
+#include "cc/trees/layer_tree.h"
+#include "cc/trees/layer_tree_host_client.h"
+#include "cc/trees/layer_tree_settings.h"
+#include "cc/trees/proxy.h"
+#include "cc/trees/swap_promise_manager.h"
+#include "cc/trees/target_property.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/rect.h"
 
 namespace cc {
-class FrameSinkId;
-class InputHandler;
-class LayerTree;
-class LayerTreeDebugState;
+class MutatorEvents;
+class Layer;
+class LayerTreeHostClient;
+class LayerTreeHostImpl;
+class LayerTreeHostImplClient;
+class LayerTreeHostSingleThreadClient;
 class LayerTreeMutator;
-class LayerTreeSettings;
-class CompositorFrameSink;
-class SwapPromise;
-class SwapPromiseManager;
-class TaskRunnerProvider;
+class MutatorHost;
+class RenderingStatsInstrumentation;
+class TaskGraphRunner;
 class UIResourceManager;
+struct RenderingStats;
+struct ScrollAndScaleSet;
 
-// This encapsulates the API for any embedder to use cc. The
-// LayerTreeHostInProcess provides the implementation where the compositor
-// thread components of this host run within the same process. Use
-// LayerTreeHostInProcess::CreateThreaded/CreateSingleThread to get either.
 class CC_EXPORT LayerTreeHost
     : public NON_EXPORTED_BASE(SurfaceReferenceOwner) {
  public:
-  virtual ~LayerTreeHost() {}
+  // TODO(sad): InitParams should be a movable type so that it can be
+  // std::move()d to the Create* functions.
+  struct CC_EXPORT InitParams {
+    LayerTreeHostClient* client = nullptr;
+    TaskGraphRunner* task_graph_runner = nullptr;
+    LayerTreeSettings const* settings = nullptr;
+    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner;
+    MutatorHost* mutator_host = nullptr;
+    scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner;
+
+    InitParams();
+    ~InitParams();
+  };
+
+  static std::unique_ptr<LayerTreeHost> CreateThreaded(
+      scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
+      InitParams* params);
+
+  static std::unique_ptr<LayerTreeHost> CreateSingleThreaded(
+      LayerTreeHostSingleThreadClient* single_thread_client,
+      InitParams* params);
+
+  ~LayerTreeHost() override;
 
   // Returns the process global unique identifier for this LayerTreeHost.
-  virtual int GetId() const = 0;
+  int GetId() const;
 
   // The current source frame number. This is incremented for each main frame
   // update(commit) pushed to the compositor thread.
-  virtual int SourceFrameNumber() const = 0;
+  int SourceFrameNumber() const;
 
   // Returns the LayerTree that holds the main frame state pushed to the
   // LayerTreeImpl on commit.
-  virtual LayerTree* GetLayerTree() = 0;
-  virtual const LayerTree* GetLayerTree() const = 0;
+  LayerTree* GetLayerTree();
+  const LayerTree* GetLayerTree() const;
 
   // Returns the UIResourceManager used to create UIResources for
   // UIResourceLayers pushed to the LayerTree.
-  virtual UIResourceManager* GetUIResourceManager() const = 0;
+  UIResourceManager* GetUIResourceManager() const;
 
   // Returns the TaskRunnerProvider used to access the main and compositor
   // thread task runners.
-  virtual TaskRunnerProvider* GetTaskRunnerProvider() const = 0;
+  TaskRunnerProvider* GetTaskRunnerProvider() const;
 
   // Returns the settings used by this host.
-  virtual const LayerTreeSettings& GetSettings() const = 0;
+  const LayerTreeSettings& GetSettings() const;
 
   // Sets the client id used to generate the SurfaceId that uniquely identifies
   // the Surfaces produced by this compositor.
-  virtual void SetFrameSinkId(const FrameSinkId& frame_sink_id) = 0;
+  void SetFrameSinkId(const FrameSinkId& frame_sink_id);
 
   // Sets the LayerTreeMutator interface used to directly mutate the compositor
   // state on the compositor thread. (Compositor-Worker)
-  virtual void SetLayerTreeMutator(
-      std::unique_ptr<LayerTreeMutator> mutator) = 0;
+  void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator);
 
   // Call this function when you expect there to be a swap buffer.
   // See swap_promise.h for how to use SwapPromise.
-  virtual void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise) = 0;
+  void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise);
 
   // Returns the SwapPromiseManager used to create SwapPromiseMonitors for this
   // host.
-  virtual SwapPromiseManager* GetSwapPromiseManager() = 0;
+  SwapPromiseManager* GetSwapPromiseManager();
 
   // Sets whether the content is suitable to use Gpu Rasterization.
-  virtual void SetHasGpuRasterizationTrigger(bool has_trigger) = 0;
+  void SetHasGpuRasterizationTrigger(bool has_trigger);
 
   // Visibility and CompositorFrameSink -------------------------------
 
-  virtual void SetVisible(bool visible) = 0;
-  virtual bool IsVisible() const = 0;
+  void SetVisible(bool visible);
+  bool IsVisible() const;
 
   // Called in response to an CompositorFrameSink request made to the client
   // using LayerTreeHostClient::RequestNewCompositorFrameSink. The client will
@@ -96,12 +140,12 @@
   // DidInitializaCompositorFrameSink or DidFailToInitializeCompositorFrameSink.
   // The request is completed when the host successfully initializes an
   // CompositorFrameSink.
-  virtual void SetCompositorFrameSink(
-      std::unique_ptr<CompositorFrameSink> compositor_frame_sink) = 0;
+  void SetCompositorFrameSink(
+      std::unique_ptr<CompositorFrameSink> compositor_frame_sink);
 
   // Forces the host to immediately release all references to the
   // CompositorFrameSink, if any. Can be safely called any time.
-  virtual std::unique_ptr<CompositorFrameSink> ReleaseCompositorFrameSink() = 0;
+  std::unique_ptr<CompositorFrameSink> ReleaseCompositorFrameSink();
 
   // Frame Scheduling (main and compositor frames) requests -------
 
@@ -109,90 +153,244 @@
   // for instance in the case of RequestAnimationFrame from blink to ensure the
   // main frame update is run on the next tick without pre-emptively forcing a
   // full commit synchronization or layer updates.
-  virtual void SetNeedsAnimate() = 0;
+  void SetNeedsAnimate();
 
   // Requests a main frame update and also ensure that the host pulls layer
   // updates from the client, even if no content might have changed, without
   // forcing a full commit synchronization.
-  virtual void SetNeedsUpdateLayers() = 0;
+  virtual void SetNeedsUpdateLayers();
 
   // Requests that the next main frame update performs a full commit
   // synchronization.
-  virtual void SetNeedsCommit() = 0;
+  virtual void SetNeedsCommit();
 
   // Requests that the next frame re-chooses crisp raster scales for all layers.
-  virtual void SetNeedsRecalculateRasterScales() = 0;
+  void SetNeedsRecalculateRasterScales();
 
   // Returns true if a main frame with commit synchronization has been
   // requested.
-  virtual bool CommitRequested() const = 0;
+  bool CommitRequested() const;
 
   // Enables/disables the compositor from requesting main frame updates from the
   // client.
-  virtual void SetDeferCommits(bool defer_commits) = 0;
+  void SetDeferCommits(bool defer_commits);
 
   // Synchronously performs a main frame update and layer updates. Used only in
   // single threaded mode when the compositor's internal scheduling is disabled.
-  virtual void LayoutAndUpdateLayers() = 0;
+  void LayoutAndUpdateLayers();
 
   // Synchronously performs a complete main frame update, commit and compositor
   // frame. Used only in single threaded mode when the compositor's internal
   // scheduling is disabled.
-  virtual void Composite(base::TimeTicks frame_begin_time) = 0;
+  void Composite(base::TimeTicks frame_begin_time);
 
   // Requests a redraw (compositor frame) for the given rect.
-  virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0;
+  void SetNeedsRedrawRect(const gfx::Rect& damage_rect);
 
   // Requests a main frame (including layer updates) and ensures that this main
   // frame results in a redraw for the complete viewport when producing the
   // CompositorFrame.
-  virtual void SetNextCommitForcesRedraw() = 0;
+  void SetNextCommitForcesRedraw();
 
   // Input Handling ---------------------------------------------
 
   // Notifies the compositor that input from the browser is being throttled till
   // the next commit. The compositor will prioritize activation of the pending
   // tree so a commit can be performed.
-  virtual void NotifyInputThrottledUntilCommit() = 0;
+  void NotifyInputThrottledUntilCommit();
 
   // Sets the state of the browser controls. (Used for URL bar animations on
   // android).
-  virtual void UpdateBrowserControlsState(BrowserControlsState constraints,
-                                          BrowserControlsState current,
-                                          bool animate) = 0;
+  void UpdateBrowserControlsState(BrowserControlsState constraints,
+                                  BrowserControlsState current,
+                                  bool animate);
 
   // Returns a reference to the InputHandler used to respond to input events on
   // the compositor thread.
-  virtual const base::WeakPtr<InputHandler>& GetInputHandler() const = 0;
+  const base::WeakPtr<InputHandler>& GetInputHandler() const;
 
   // Informs the compositor that an active fling gesture being processed on the
   // main thread has been finished.
-  virtual void DidStopFlinging() = 0;
+  void DidStopFlinging();
 
   // Debugging and benchmarks ---------------------------------
-  virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0;
-  virtual const LayerTreeDebugState& GetDebugState() const = 0;
+  void SetDebugState(const LayerTreeDebugState& debug_state);
+  const LayerTreeDebugState& GetDebugState() const;
 
   // Returns the id of the benchmark on success, 0 otherwise.
-  virtual int ScheduleMicroBenchmark(
-      const std::string& benchmark_name,
-      std::unique_ptr<base::Value> value,
-      const MicroBenchmark::DoneCallback& callback) = 0;
+  int ScheduleMicroBenchmark(const std::string& benchmark_name,
+                             std::unique_ptr<base::Value> value,
+                             const MicroBenchmark::DoneCallback& callback);
 
   // Returns true if the message was successfully delivered and handled.
-  virtual bool SendMessageToMicroBenchmark(
-      int id,
-      std::unique_ptr<base::Value> value) = 0;
+  bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value);
 
   // When the main thread informs the impl thread that it is ready to commit,
   // generally it would remain blocked till the main thread state is copied to
   // the pending tree. Calling this would ensure that the main thread remains
   // blocked till the pending tree is activated.
-  virtual void SetNextCommitWaitsForActivation() = 0;
+  void SetNextCommitWaitsForActivation();
 
   // The LayerTreeHost tracks whether the content is suitable for Gpu raster.
   // Calling this will reset it back to not suitable state.
-  virtual void ResetGpuRasterizationTracking() = 0;
+  void ResetGpuRasterizationTracking();
+
+  // SurfaceReferenceOwner implementation.
+  SurfaceSequenceGenerator* GetSurfaceSequenceGenerator() override;
+
+  // LayerTreeHostInProcess interface to Proxy.
+  void WillBeginMainFrame();
+  void DidBeginMainFrame();
+  void BeginMainFrame(const BeginFrameArgs& args);
+  void BeginMainFrameNotExpectedSoon();
+  void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
+  void RequestMainFrameUpdate();
+  void FinishCommitOnImplThread(LayerTreeHostImpl* host_impl);
+  void WillCommit();
+  void CommitComplete();
+  void RequestNewCompositorFrameSink();
+  void DidInitializeCompositorFrameSink();
+  void DidFailToInitializeCompositorFrameSink();
+  virtual std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl(
+      LayerTreeHostImplClient* client);
+  void DidLoseCompositorFrameSink();
+  void DidCommitAndDrawFrame() { client_->DidCommitAndDrawFrame(); }
+  void DidReceiveCompositorFrameAck() {
+    client_->DidReceiveCompositorFrameAck();
+  }
+  bool UpdateLayers();
+  // Called when the compositor completed page scale animation.
+  void DidCompletePageScaleAnimation();
+  void ApplyScrollAndScale(ScrollAndScaleSet* info);
+
+  LayerTreeHostClient* client() { return client_; }
+
+  bool gpu_rasterization_histogram_recorded() const {
+    return gpu_rasterization_histogram_recorded_;
+  }
+
+  void CollectRenderingStats(RenderingStats* stats) const;
+
+  RenderingStatsInstrumentation* rendering_stats_instrumentation() const {
+    return rendering_stats_instrumentation_.get();
+  }
+
+  void SetAnimationEvents(std::unique_ptr<MutatorEvents> events);
+
+  bool has_gpu_rasterization_trigger() const {
+    return has_gpu_rasterization_trigger_;
+  }
+
+  Proxy* proxy() const { return proxy_.get(); }
+
+  bool IsSingleThreaded() const;
+  bool IsThreaded() const;
+
+ protected:
+  // Allow tests to inject the LayerTree.
+  LayerTreeHost(InitParams* params,
+                CompositorMode mode,
+                std::unique_ptr<LayerTree> layer_tree);
+  LayerTreeHost(InitParams* params, CompositorMode mode);
+
+  void InitializeThreaded(
+      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
+  void InitializeSingleThreaded(
+      LayerTreeHostSingleThreadClient* single_thread_client,
+      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+  void InitializeForTesting(
+      std::unique_ptr<TaskRunnerProvider> task_runner_provider,
+      std::unique_ptr<Proxy> proxy_for_testing);
+  void SetTaskRunnerProviderForTesting(
+      std::unique_ptr<TaskRunnerProvider> task_runner_provider);
+  void SetUIResourceManagerForTesting(
+      std::unique_ptr<UIResourceManager> ui_resource_manager);
+
+  // task_graph_runner() returns a valid value only until the LayerTreeHostImpl
+  // is created in CreateLayerTreeHostImpl().
+  TaskGraphRunner* task_graph_runner() const { return task_graph_runner_; }
+
+  void OnCommitForSwapPromises();
+
+  void RecordGpuRasterizationHistogram();
+
+  MicroBenchmarkController micro_benchmark_controller_;
+
+  std::unique_ptr<LayerTree> layer_tree_;
+
+  base::WeakPtr<InputHandler> input_handler_weak_ptr_;
+
+ private:
+  friend class LayerTreeHostSerializationTest;
+
+  // This is the number of consecutive frames in which we want the content to be
+  // suitable for GPU rasterization before re-enabling it.
+  enum { kNumFramesToConsiderBeforeGpuRasterization = 60 };
+
+  void ApplyViewportDeltas(ScrollAndScaleSet* info);
+  void ApplyPageScaleDeltaFromImplSide(float page_scale_delta);
+  void InitializeProxy(std::unique_ptr<Proxy> proxy);
+
+  bool DoUpdateLayers(Layer* root_layer);
+  void UpdateHudLayer();
+
+  bool AnimateLayersRecursive(Layer* current, base::TimeTicks time);
+
+  void CalculateLCDTextMetricsCallback(Layer* layer);
+
+  void SetPropertyTreesNeedRebuild();
+
+  const CompositorMode compositor_mode_;
+
+  std::unique_ptr<UIResourceManager> ui_resource_manager_;
+
+  LayerTreeHostClient* client_;
+  std::unique_ptr<Proxy> proxy_;
+  std::unique_ptr<TaskRunnerProvider> task_runner_provider_;
+
+  int source_frame_number_;
+  std::unique_ptr<RenderingStatsInstrumentation>
+      rendering_stats_instrumentation_;
+
+  SwapPromiseManager swap_promise_manager_;
+
+  // |current_compositor_frame_sink_| can't be updated until we've successfully
+  // initialized a new CompositorFrameSink. |new_compositor_frame_sink_|
+  // contains the new CompositorFrameSink that is currently being initialized.
+  // If initialization is successful then |new_compositor_frame_sink_| replaces
+  // |current_compositor_frame_sink_|.
+  std::unique_ptr<CompositorFrameSink> new_compositor_frame_sink_;
+  std::unique_ptr<CompositorFrameSink> current_compositor_frame_sink_;
+
+  const LayerTreeSettings settings_;
+  LayerTreeDebugState debug_state_;
+
+  bool visible_;
+
+  bool has_gpu_rasterization_trigger_;
+  bool content_is_suitable_for_gpu_rasterization_;
+  bool gpu_rasterization_histogram_recorded_;
+
+  // If set, then page scale animation has completed, but the client hasn't been
+  // notified about it yet.
+  bool did_complete_scale_animation_;
+
+  int id_;
+  bool next_commit_forces_redraw_ = false;
+  bool next_commit_forces_recalculate_raster_scales_ = false;
+  // Track when we're inside a main frame to see if compositor is being
+  // destroyed midway which causes a crash. crbug.com/654672
+  bool inside_main_frame_ = false;
+
+  TaskGraphRunner* task_graph_runner_;
+
+  SurfaceSequenceGenerator surface_sequence_generator_;
+  uint32_t num_consecutive_frames_suitable_for_gpu_ = 0;
+
+  scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
 };
 
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_in_process.h b/cc/trees/layer_tree_host_in_process.h
deleted file mode 100644
index b4fd8af6..0000000
--- a/cc/trees/layer_tree_host_in_process.h
+++ /dev/null
@@ -1,291 +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_LAYER_TREE_HOST_IN_PROCESS_H_
-#define CC_TREES_LAYER_TREE_HOST_IN_PROCESS_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-#include <memory>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "base/cancelable_callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "cc/base/cc_export.h"
-#include "cc/debug/micro_benchmark.h"
-#include "cc/debug/micro_benchmark_controller.h"
-#include "cc/input/browser_controls_state.h"
-#include "cc/input/event_listener_properties.h"
-#include "cc/input/input_handler.h"
-#include "cc/input/layer_selection_bound.h"
-#include "cc/input/scrollbar.h"
-#include "cc/layers/layer_collections.h"
-#include "cc/layers/layer_list_iterator.h"
-#include "cc/output/compositor_frame_sink.h"
-#include "cc/output/swap_promise.h"
-#include "cc/resources/resource_format.h"
-#include "cc/surfaces/surface_sequence_generator.h"
-#include "cc/trees/compositor_mode.h"
-#include "cc/trees/layer_tree.h"
-#include "cc/trees/layer_tree_host.h"
-#include "cc/trees/layer_tree_host_client.h"
-#include "cc/trees/layer_tree_settings.h"
-#include "cc/trees/proxy.h"
-#include "cc/trees/swap_promise_manager.h"
-#include "cc/trees/target_property.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace cc {
-class MutatorEvents;
-class Layer;
-class LayerTreeHostClient;
-class LayerTreeHostImpl;
-class LayerTreeHostImplClient;
-class LayerTreeHostSingleThreadClient;
-class LayerTreeMutator;
-class MutatorHost;
-class RenderingStatsInstrumentation;
-class TaskGraphRunner;
-struct RenderingStats;
-struct ScrollAndScaleSet;
-
-class CC_EXPORT LayerTreeHostInProcess : public LayerTreeHost {
- public:
-  // TODO(sad): InitParams should be a movable type so that it can be
-  // std::move()d to the Create* functions.
-  struct CC_EXPORT InitParams {
-    LayerTreeHostClient* client = nullptr;
-    TaskGraphRunner* task_graph_runner = nullptr;
-    LayerTreeSettings const* settings = nullptr;
-    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner;
-    MutatorHost* mutator_host = nullptr;
-    scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner;
-
-    InitParams();
-    ~InitParams();
-  };
-
-  static std::unique_ptr<LayerTreeHostInProcess> CreateThreaded(
-      scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
-      InitParams* params);
-
-  static std::unique_ptr<LayerTreeHostInProcess> CreateSingleThreaded(
-      LayerTreeHostSingleThreadClient* single_thread_client,
-      InitParams* params);
-
-  ~LayerTreeHostInProcess() override;
-
-  // LayerTreeHost implementation.
-  int GetId() const override;
-  int SourceFrameNumber() const override;
-  LayerTree* GetLayerTree() override;
-  const LayerTree* GetLayerTree() const override;
-  UIResourceManager* GetUIResourceManager() const override;
-  TaskRunnerProvider* GetTaskRunnerProvider() const override;
-  const LayerTreeSettings& GetSettings() const override;
-  void SetFrameSinkId(const FrameSinkId& frame_sink_id) override;
-  void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator) override;
-  void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise) override;
-  SwapPromiseManager* GetSwapPromiseManager() override;
-  void SetHasGpuRasterizationTrigger(bool has_trigger) override;
-  void SetVisible(bool visible) override;
-  bool IsVisible() const override;
-  void SetCompositorFrameSink(
-      std::unique_ptr<CompositorFrameSink> compositor_frame_sink) override;
-  std::unique_ptr<CompositorFrameSink> ReleaseCompositorFrameSink() override;
-  void SetNeedsAnimate() override;
-  void SetNeedsUpdateLayers() override;
-  void SetNeedsCommit() override;
-  void SetNeedsRecalculateRasterScales() override;
-  bool CommitRequested() const override;
-  void SetDeferCommits(bool defer_commits) override;
-  void LayoutAndUpdateLayers() override;
-  void Composite(base::TimeTicks frame_begin_time) override;
-  void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override;
-  void SetNextCommitForcesRedraw() override;
-  void NotifyInputThrottledUntilCommit() override;
-  void UpdateBrowserControlsState(BrowserControlsState constraints,
-                                  BrowserControlsState current,
-                                  bool animate) override;
-  const base::WeakPtr<InputHandler>& GetInputHandler() const override;
-  void DidStopFlinging() override;
-  void SetDebugState(const LayerTreeDebugState& debug_state) override;
-  const LayerTreeDebugState& GetDebugState() const override;
-  int ScheduleMicroBenchmark(
-      const std::string& benchmark_name,
-      std::unique_ptr<base::Value> value,
-      const MicroBenchmark::DoneCallback& callback) override;
-  bool SendMessageToMicroBenchmark(int id,
-                                   std::unique_ptr<base::Value> value) override;
-  SurfaceSequenceGenerator* GetSurfaceSequenceGenerator() override;
-  void SetNextCommitWaitsForActivation() override;
-  void ResetGpuRasterizationTracking() override;
-
-  // LayerTreeHostInProcess interface to Proxy.
-  void WillBeginMainFrame();
-  void DidBeginMainFrame();
-  void BeginMainFrame(const BeginFrameArgs& args);
-  void BeginMainFrameNotExpectedSoon();
-  void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
-  void RequestMainFrameUpdate();
-  void FinishCommitOnImplThread(LayerTreeHostImpl* host_impl);
-  void WillCommit();
-  void CommitComplete();
-  void RequestNewCompositorFrameSink();
-  void DidInitializeCompositorFrameSink();
-  void DidFailToInitializeCompositorFrameSink();
-  virtual std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl(
-      LayerTreeHostImplClient* client);
-  void DidLoseCompositorFrameSink();
-  void DidCommitAndDrawFrame() { client_->DidCommitAndDrawFrame(); }
-  void DidReceiveCompositorFrameAck() {
-    client_->DidReceiveCompositorFrameAck();
-  }
-  bool UpdateLayers();
-  // Called when the compositor completed page scale animation.
-  void DidCompletePageScaleAnimation();
-  void ApplyScrollAndScale(ScrollAndScaleSet* info);
-
-  LayerTreeHostClient* client() { return client_; }
-
-  bool gpu_rasterization_histogram_recorded() const {
-    return gpu_rasterization_histogram_recorded_;
-  }
-
-  void CollectRenderingStats(RenderingStats* stats) const;
-
-  RenderingStatsInstrumentation* rendering_stats_instrumentation() const {
-    return rendering_stats_instrumentation_.get();
-  }
-
-  void SetAnimationEvents(std::unique_ptr<MutatorEvents> events);
-
-  bool has_gpu_rasterization_trigger() const {
-    return has_gpu_rasterization_trigger_;
-  }
-
-  Proxy* proxy() const { return proxy_.get(); }
-
-  bool IsSingleThreaded() const;
-  bool IsThreaded() const;
-
- protected:
-  // Allow tests to inject the LayerTree.
-  LayerTreeHostInProcess(InitParams* params,
-                         CompositorMode mode,
-                         std::unique_ptr<LayerTree> layer_tree);
-  LayerTreeHostInProcess(InitParams* params, CompositorMode mode);
-
-  void InitializeThreaded(
-      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner);
-  void InitializeSingleThreaded(
-      LayerTreeHostSingleThreadClient* single_thread_client,
-      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
-  void InitializeForTesting(
-      std::unique_ptr<TaskRunnerProvider> task_runner_provider,
-      std::unique_ptr<Proxy> proxy_for_testing);
-  void SetTaskRunnerProviderForTesting(
-      std::unique_ptr<TaskRunnerProvider> task_runner_provider);
-  void SetUIResourceManagerForTesting(
-      std::unique_ptr<UIResourceManager> ui_resource_manager);
-
-  // task_graph_runner() returns a valid value only until the LayerTreeHostImpl
-  // is created in CreateLayerTreeHostImpl().
-  TaskGraphRunner* task_graph_runner() const { return task_graph_runner_; }
-
-  void OnCommitForSwapPromises();
-
-  void RecordGpuRasterizationHistogram();
-
-  MicroBenchmarkController micro_benchmark_controller_;
-
-  std::unique_ptr<LayerTree> layer_tree_;
-
-  base::WeakPtr<InputHandler> input_handler_weak_ptr_;
-
- private:
-  friend class LayerTreeHostSerializationTest;
-
-  // This is the number of consecutive frames in which we want the content to be
-  // suitable for GPU rasterization before re-enabling it.
-  enum { kNumFramesToConsiderBeforeGpuRasterization = 60 };
-
-  void ApplyViewportDeltas(ScrollAndScaleSet* info);
-  void ApplyPageScaleDeltaFromImplSide(float page_scale_delta);
-  void InitializeProxy(std::unique_ptr<Proxy> proxy);
-
-  bool DoUpdateLayers(Layer* root_layer);
-  void UpdateHudLayer();
-
-  bool AnimateLayersRecursive(Layer* current, base::TimeTicks time);
-
-  void CalculateLCDTextMetricsCallback(Layer* layer);
-
-  void SetPropertyTreesNeedRebuild();
-
-  const CompositorMode compositor_mode_;
-
-  std::unique_ptr<UIResourceManager> ui_resource_manager_;
-
-  LayerTreeHostClient* client_;
-  std::unique_ptr<Proxy> proxy_;
-  std::unique_ptr<TaskRunnerProvider> task_runner_provider_;
-
-  int source_frame_number_;
-  std::unique_ptr<RenderingStatsInstrumentation>
-      rendering_stats_instrumentation_;
-
-  SwapPromiseManager swap_promise_manager_;
-
-  // |current_compositor_frame_sink_| can't be updated until we've successfully
-  // initialized a new CompositorFrameSink. |new_compositor_frame_sink_|
-  // contains the new CompositorFrameSink that is currently being initialized.
-  // If initialization is successful then |new_compositor_frame_sink_| replaces
-  // |current_compositor_frame_sink_|.
-  std::unique_ptr<CompositorFrameSink> new_compositor_frame_sink_;
-  std::unique_ptr<CompositorFrameSink> current_compositor_frame_sink_;
-
-  const LayerTreeSettings settings_;
-  LayerTreeDebugState debug_state_;
-
-  bool visible_;
-
-  bool has_gpu_rasterization_trigger_;
-  bool content_is_suitable_for_gpu_rasterization_;
-  bool gpu_rasterization_histogram_recorded_;
-
-  // If set, then page scale animation has completed, but the client hasn't been
-  // notified about it yet.
-  bool did_complete_scale_animation_;
-
-  int id_;
-  bool next_commit_forces_redraw_ = false;
-  bool next_commit_forces_recalculate_raster_scales_ = false;
-  // Track when we're inside a main frame to see if compositor is being
-  // destroyed midway which causes a crash. crbug.com/654672
-  bool inside_main_frame_ = false;
-
-  TaskGraphRunner* task_graph_runner_;
-
-  SurfaceSequenceGenerator surface_sequence_generator_;
-  uint32_t num_consecutive_frames_suitable_for_gpu_ = 0;
-
-  scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerTreeHostInProcess);
-};
-
-}  // namespace cc
-
-#endif  // CC_TREES_LAYER_TREE_HOST_IN_PROCESS_H_
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 4128e8a..0d8dec3 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -5187,11 +5187,11 @@
 
   void BeginTest() override {
     // Verify default value.
-    EXPECT_FALSE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // Setting gpu rasterization trigger does not enable gpu rasterization.
     layer_tree_host()->SetHasGpuRasterizationTrigger(true);
-    EXPECT_TRUE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     PostSetNeedsCommitToMainThread();
   }
@@ -5242,7 +5242,7 @@
   void BeginTest() override {
     // Setting gpu rasterization trigger does not enable gpu rasterization.
     layer_tree_host()->SetHasGpuRasterizationTrigger(true);
-    EXPECT_TRUE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     PostSetNeedsCommitToMainThread();
   }
@@ -5297,11 +5297,11 @@
 
   void BeginTest() override {
     // Verify default value.
-    EXPECT_FALSE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // Gpu rasterization trigger is relevant.
     layer_tree_host()->SetHasGpuRasterizationTrigger(true);
-    EXPECT_TRUE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // Content-based veto is relevant as well.
     layer_->set_force_unsuitable_for_gpu_rasterization(true);
@@ -5365,11 +5365,11 @@
 
   void BeginTest() override {
     // Verify default value.
-    EXPECT_FALSE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // Gpu rasterization trigger is relevant.
     layer_tree_host()->SetHasGpuRasterizationTrigger(true);
-    EXPECT_TRUE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // Content-based veto is relevant as well.
     layer_->set_force_unsuitable_for_gpu_rasterization(true);
@@ -5448,11 +5448,11 @@
 
   void BeginTest() override {
     // Verify default value.
-    EXPECT_FALSE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // With gpu rasterization forced, gpu rasterization trigger is irrelevant.
     layer_tree_host()->SetHasGpuRasterizationTrigger(true);
-    EXPECT_TRUE(layer_tree_host_in_process()->has_gpu_rasterization_trigger());
+    EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger());
 
     // Content-based veto is irrelevant as well.
     layer_->set_force_unsuitable_for_gpu_rasterization(true);
@@ -5867,7 +5867,7 @@
   void BeginMainFrame(const BeginFrameArgs& args) override {
     EXPECT_EQ(nullptr, layer_tree()->root_layer());
 
-    layer_tree_host_in_process()->ApplyScrollAndScale(&info_);
+    layer_tree_host()->ApplyScrollAndScale(&info_);
     EndTest();
   }
 
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index 2d1b3c8..e1977a44 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1647,9 +1647,8 @@
                               TargetProperty::Type target_property,
                               int group) override {
     called_animation_started_ = true;
-    layer_tree_host_in_process()->AnimateLayers(
-        base::TimeTicks::FromInternalValue(
-            std::numeric_limits<int64_t>::max()));
+    layer_tree_host()->AnimateLayers(base::TimeTicks::FromInternalValue(
+        std::numeric_limits<int64_t>::max()));
     PostSetNeedsCommitToMainThread();
   }
 
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index f02e66da..37d98c1 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1318,15 +1318,14 @@
 
   auto animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
-  LayerTreeHostInProcess::InitParams params;
+  LayerTreeHost::InitParams params;
   params.client = &layer_tree_host_client;
   params.task_graph_runner = &task_graph_runner;
   params.settings = &settings;
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.mutator_host = animation_host.get();
-  std::unique_ptr<LayerTreeHostInProcess> layer_tree_host =
-      LayerTreeHostInProcess::CreateThreaded(impl_thread.task_runner(),
-                                             &params);
+  std::unique_ptr<LayerTreeHost> layer_tree_host =
+      LayerTreeHost::CreateThreaded(impl_thread.task_runner(), &params);
 
   ThreadCheckingInputHandlerClient input_handler_client(
       impl_thread.task_runner().get(), &received_stop_flinging);
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index 63e0968..0a8620e 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -19,7 +19,7 @@
 #include "cc/output/context_provider.h"
 #include "cc/scheduler/compositor_timing_history.h"
 #include "cc/scheduler/delay_based_time_source.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/proxy_main.h"
@@ -38,7 +38,7 @@
 }  // namespace
 
 ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
-                     LayerTreeHostInProcess* layer_tree_host,
+                     LayerTreeHost* layer_tree_host,
                      TaskRunnerProvider* task_runner_provider)
     : layer_tree_host_id_(layer_tree_host->GetId()),
       commit_completion_waits_for_activation_(false),
@@ -225,7 +225,7 @@
 
 void ProxyImpl::NotifyReadyToCommitOnImpl(
     CompletionEvent* completion,
-    LayerTreeHostInProcess* layer_tree_host,
+    LayerTreeHost* layer_tree_host,
     base::TimeTicks main_thread_start_time,
     bool hold_commit_for_activation) {
   TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToCommitOnImpl");
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index fdabbbd3..0aab6133 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -16,7 +16,7 @@
 #include "cc/trees/layer_tree_host_impl.h"
 
 namespace cc {
-class LayerTreeHostInProcess;
+class LayerTreeHost;
 class ProxyMain;
 
 // This class aggregates all the interactions that the main side of the
@@ -26,7 +26,7 @@
                             public NON_EXPORTED_BASE(SchedulerClient) {
  public:
   ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
-            LayerTreeHostInProcess* layer_tree_host,
+            LayerTreeHost* layer_tree_host,
             TaskRunnerProvider* task_runner_provider);
   ~ProxyImpl() override;
 
@@ -49,7 +49,7 @@
   void ReleaseCompositorFrameSinkOnImpl(CompletionEvent* completion);
   void FinishGLOnImpl(CompletionEvent* completion);
   void NotifyReadyToCommitOnImpl(CompletionEvent* completion,
-                                 LayerTreeHostInProcess* layer_tree_host,
+                                 LayerTreeHost* layer_tree_host,
                                  base::TimeTicks main_thread_start_time,
                                  bool hold_commit_for_activation);
 
@@ -62,7 +62,7 @@
   struct BlockedMainCommitOnly {
     BlockedMainCommitOnly();
     ~BlockedMainCommitOnly();
-    LayerTreeHostInProcess* layer_tree_host;
+    LayerTreeHost* layer_tree_host;
   };
 
   // LayerTreeHostImplClient implementation
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 15948f0e..bab54a09 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -18,14 +18,14 @@
 #include "cc/output/swap_promise.h"
 #include "cc/resources/ui_resource_manager.h"
 #include "cc/trees/blocking_task_runner.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/proxy_impl.h"
 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
 
 namespace cc {
 
-ProxyMain::ProxyMain(LayerTreeHostInProcess* layer_tree_host,
+ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
                      TaskRunnerProvider* task_runner_provider)
     : layer_tree_host_(layer_tree_host),
       task_runner_provider_(task_runner_provider),
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index 5ebf396..29f4880 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -16,7 +16,7 @@
 class MutatorEvents;
 class CompletionEvent;
 class CompositorFrameSink;
-class LayerTreeHostInProcess;
+class LayerTreeHost;
 class LayerTreeMutator;
 class ProxyImpl;
 
@@ -25,7 +25,7 @@
 // The class is created and lives on the main thread.
 class CC_EXPORT ProxyMain : public Proxy {
  public:
-  ProxyMain(LayerTreeHostInProcess* layer_tree_host,
+  ProxyMain(LayerTreeHost* layer_tree_host,
             TaskRunnerProvider* task_runner_provider);
 
   ~ProxyMain() override;
@@ -98,7 +98,7 @@
   void InitializeOnImplThread(CompletionEvent* completion_event);
   void DestroyProxyImplOnImplThread(CompletionEvent* completion_event);
 
-  LayerTreeHostInProcess* layer_tree_host_;
+  LayerTreeHost* layer_tree_host_;
 
   TaskRunnerProvider* task_runner_provider_;
 
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 8d743563..7aa7cfc 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -18,8 +18,8 @@
 #include "cc/scheduler/compositor_timing_history.h"
 #include "cc/scheduler/delay_based_time_source.h"
 #include "cc/scheduler/scheduler.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_host_common.h"
-#include "cc/trees/layer_tree_host_in_process.h"
 #include "cc/trees/layer_tree_host_single_thread_client.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/mutator_host.h"
@@ -28,14 +28,14 @@
 namespace cc {
 
 std::unique_ptr<Proxy> SingleThreadProxy::Create(
-    LayerTreeHostInProcess* layer_tree_host,
+    LayerTreeHost* layer_tree_host,
     LayerTreeHostSingleThreadClient* client,
     TaskRunnerProvider* task_runner_provider) {
   return base::WrapUnique(
       new SingleThreadProxy(layer_tree_host, client, task_runner_provider));
 }
 
-SingleThreadProxy::SingleThreadProxy(LayerTreeHostInProcess* layer_tree_host,
+SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
                                      LayerTreeHostSingleThreadClient* client,
                                      TaskRunnerProvider* task_runner_provider)
     : layer_tree_host_(layer_tree_host),
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index eb49421..fbdd70e 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -21,7 +21,7 @@
 
 class MutatorEvents;
 class BeginFrameSource;
-class LayerTreeHostInProcess;
+class LayerTreeHost;
 class LayerTreeHostSingleThreadClient;
 
 class CC_EXPORT SingleThreadProxy : public Proxy,
@@ -29,7 +29,7 @@
                                     public SchedulerClient {
  public:
   static std::unique_ptr<Proxy> Create(
-      LayerTreeHostInProcess* layer_tree_host,
+      LayerTreeHost* layer_tree_host,
       LayerTreeHostSingleThreadClient* client,
       TaskRunnerProvider* task_runner_provider_);
   ~SingleThreadProxy() override;
@@ -102,7 +102,7 @@
   void CompositeImmediately(base::TimeTicks frame_begin_time);
 
  protected:
-  SingleThreadProxy(LayerTreeHostInProcess* layer_tree_host,
+  SingleThreadProxy(LayerTreeHost* layer_tree_host,
                     LayerTreeHostSingleThreadClient* client,
                     TaskRunnerProvider* task_runner_provider);
 
@@ -120,7 +120,7 @@
   void ScheduleRequestNewCompositorFrameSink();
 
   // Accessed on main thread only.
-  LayerTreeHostInProcess* layer_tree_host_;
+  LayerTreeHost* layer_tree_host_;
   LayerTreeHostSingleThreadClient* single_thread_client_;
 
   TaskRunnerProvider* task_runner_provider_;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
index d8c54711..c92e632 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
@@ -106,7 +106,7 @@
             public boolean queueIdle() {
                 Runnable currentTask = mDeferredTasks.poll();
                 if (currentTask == null) {
-                    if (mDeferredStartupInitializedForApp) {
+                    if (mDeferredStartupInitializedForApp && !mDeferredStartupCompletedForApp) {
                         mDeferredStartupCompletedForApp = true;
                         recordDeferredStartupStats();
                     }
@@ -137,7 +137,6 @@
                 "UMA.Debug.EnableCrashUpload.DeferredStartUpCompleteTime",
                 SystemClock.uptimeMillis() - UmaUtils.getForegroundStartTime(),
                 TimeUnit.MILLISECONDS);
-        LocaleManager.getInstance().recordStartupMetrics();
     }
 
     /**
@@ -219,6 +218,13 @@
             }
         });
 
+        mDeferredTasks.add(new Runnable() {
+            @Override
+            public void run() {
+                LocaleManager.getInstance().recordStartupMetrics();
+            }
+        });
+
         final ChromeApplication application = (ChromeApplication) mAppContext;
 
         mDeferredTasks.add(new Runnable() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java
index c15c5d4..2a73e5b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java
@@ -88,12 +88,13 @@
      * Get the instance of the evaluation bridge.
      * @param profile The profile used to get bridge.
      * @param useEvaluationScheduler True if using the evaluation scheduler instead of the
-     * GCMNetworkManager one.
+     *                               GCMNetworkManager one.
+     * @param useBackgroundLoader True if using background loader. False for prerenderer.
      */
     public static OfflinePageEvaluationBridge getForProfile(
-            Profile profile, boolean useEvaluationScheduler) {
+            Profile profile, boolean useEvaluationScheduler, boolean useBackgroundLoader) {
         ThreadUtils.assertOnUiThread();
-        return nativeGetBridgeForProfile(profile, useEvaluationScheduler);
+        return nativeGetBridgeForProfile(profile, useEvaluationScheduler, useBackgroundLoader);
     }
 
     private static final String TAG = "OPEvalBridge";
@@ -275,7 +276,7 @@
     }
 
     private static native OfflinePageEvaluationBridge nativeGetBridgeForProfile(
-            Profile profile, boolean useEvaluationScheduler);
+            Profile profile, boolean useEvaluationScheduler, boolean useBackgroundLoader);
 
     private native void nativeGetAllPages(long nativeOfflinePageEvaluationBridge,
             List<OfflinePageItem> offlinePages, final Callback<List<OfflinePageItem>> callback);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
index bfee387..ffaa92df 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
@@ -14,6 +14,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Manual;
 import org.chromium.base.test.util.TimeoutScale;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -44,8 +45,9 @@
  * Tests OfflinePageBridge.SavePageLater over a batch of urls.
  * Tests against a list of top EM urls, try to call SavePageLater on each of the url. It also
  * record metrics (failure rate, time elapsed etc.) by writing metrics to a file on external
- * storage.
- * */
+ * storage. This will always use prerenderer.
+ */
+@CommandLineFlags.Add({"disable-features=BackgroundLoader"})
 public class OfflinePageSavePageLaterEvaluationTest
         extends ChromeActivityTestCaseBase<ChromeActivity> {
     /**
@@ -97,6 +99,7 @@
     private boolean mIsUserRequested;
     private boolean mUseTestScheduler;
     private int mScheduleBatchSize;
+    private boolean mUseBackgroundLoader;
 
     private LongSparseArray<RequestMetadata> mRequestMetadata;
 
@@ -216,15 +219,17 @@
      * Initializes the evaluation bridge which will be used.
      * @param useCustomScheduler True if customized scheduler (the one with immediate scheduling)
      *                           will be used. False otherwise.
+     * @param useBackgroundLoader True if use background loader. False if use prerenderer.
      */
-    private void initializeBridgeForProfile(final boolean useTestingScheduler)
-            throws InterruptedException {
+    private void initializeBridgeForProfile(final boolean useTestingScheduler,
+            final boolean useBackgroundLoader) throws InterruptedException {
         final Semaphore semaphore = new Semaphore(0);
         ThreadUtils.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 Profile profile = Profile.getLastUsedProfile();
-                mBridge = OfflinePageEvaluationBridge.getForProfile(profile, useTestingScheduler);
+                mBridge = OfflinePageEvaluationBridge.getForProfile(
+                        profile, useTestingScheduler, useBackgroundLoader);
                 if (mBridge == null) {
                     fail("OfflinePageEvaluationBridge initialization failed!");
                     return;
@@ -250,8 +255,10 @@
      * Set up the input/output, bridge and observer we're going to use.
      * @param useCustomScheduler True if customized scheduler (the one with immediate scheduling)
      *                           will be used. False otherwise.
+     * @param useBackgroundLoader True if use background loader. False if use prerenderer.
      */
-    protected void setUpIOAndBridge(final boolean useCustomScheduler) throws InterruptedException {
+    protected void setUpIOAndBridge(final boolean useCustomScheduler,
+            final boolean useBackgroundLoader) throws InterruptedException {
         try {
             getUrlListFromInputFile(INPUT_FILE_PATH);
         } catch (IOException e) {
@@ -264,7 +271,7 @@
             mScheduleBatchSize = mUrls.size();
         }
 
-        initializeBridgeForProfile(useCustomScheduler);
+        initializeBridgeForProfile(useCustomScheduler, useBackgroundLoader);
         mObserver = new OfflinePageEvaluationObserver() {
             public void savePageRequestAdded(SavePageRequest request) {
                 RequestMetadata metadata = new RequestMetadata();
@@ -485,6 +492,8 @@
             mIsUserRequested = Boolean.parseBoolean(properties.getProperty("IsUserRequested"));
             mUseTestScheduler = Boolean.parseBoolean(properties.getProperty("UseTestScheduler"));
             mScheduleBatchSize = Integer.parseInt(properties.getProperty("ScheduleBatchSize"));
+            mUseBackgroundLoader =
+                    Boolean.parseBoolean(properties.getProperty("UseBackgroundLoader"));
         } catch (FileNotFoundException e) {
             Log.e(TAG, e.getMessage(), e);
             fail(String.format(
@@ -509,7 +518,18 @@
     @TimeoutScale(4)
     public void testFailureRate() throws IOException, InterruptedException {
         parseConfigFile();
-        setUpIOAndBridge(mUseTestScheduler);
+        setUpIOAndBridge(mUseTestScheduler, mUseBackgroundLoader);
         processUrls(mUrls);
     }
+
+    /**
+     * Runs testFailureRate with background loader enabled.
+     */
+    @Manual
+    @TimeoutScale(4)
+    @CommandLineFlags.Add({"enable-features=BackgroundLoader"})
+    @CommandLineFlags.Remove({"disable-features=BackgroundLoader"})
+    public void testBackgroundLoaderFailureRate() throws IOException, InterruptedException {
+        testFailureRate();
+    }
 }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index cd54fcc..1b7d34b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4143,6 +4143,10 @@
     "//url/mojo:url_mojom_origin__generator",
   ]
 
+  if (use_vulcanize) {
+    deps += [ "//chrome/browser/resources/md_downloads:vulcanize" ]
+  }
+
   if (safe_browsing_mode > 0) {
     deps +=
         [ "//chrome/browser/resources/safe_browsing:make_file_types_protobuf" ]
diff --git a/chrome/browser/android/offline_pages/evaluation/evaluation_test_scheduler.cc b/chrome/browser/android/offline_pages/evaluation/evaluation_test_scheduler.cc
index 8aadb93..e782d7f 100644
--- a/chrome/browser/android/offline_pages/evaluation/evaluation_test_scheduler.cc
+++ b/chrome/browser/android/offline_pages/evaluation/evaluation_test_scheduler.cc
@@ -37,13 +37,21 @@
         RequestCoordinatorFactory::GetInstance()->GetForBrowserContext(profile);
     // TODO(romax) Maybe get current real condition.
     DeviceConditions device_conditions(
-        true, 0, net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
+        true, 0, net::NetworkChangeNotifier::GetConnectionType());
     coordinator->StartImmediateProcessing(device_conditions,
                                           base::Bind(&ProcessingDoneCallback));
   }
 }
 
 void StartProcessing() {
+  // If there's no network connection then try in 2 seconds.
+  if (net::NetworkChangeNotifier::GetConnectionType() ==
+      net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE) {
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE, base::Bind(&StartProcessing),
+        base::TimeDelta::FromSeconds(2));
+    return;
+  }
   Profile* profile = ProfileManager::GetLastUsedProfile();
   RequestCoordinator* coordinator =
       RequestCoordinatorFactory::GetInstance()->GetForBrowserContext(profile);
@@ -70,9 +78,19 @@
 
 void EvaluationTestScheduler::BackupSchedule(
     const TriggerConditions& trigger_conditions,
-    long delay_in_seconds) {}
+    long delay_in_seconds) {
+  // This method is not expected to be called in test harness. Adding a log in
+  // case we somehow get called here and need to implement the method.
+  coordinator_->GetLogger()->RecordActivity(std::string(kLogTag) +
+                                            " BackupSchedule called!");
+}
 
-void EvaluationTestScheduler::Unschedule() {}
+void EvaluationTestScheduler::Unschedule() {
+  // This method is not expected to be called in test harness. Adding a log in
+  // case we somehow get called here and need to implement the method.
+  coordinator_->GetLogger()->RecordActivity(std::string(kLogTag) +
+                                            " Unschedule called!");
+}
 
 void EvaluationTestScheduler::ImmediateScheduleCallback(bool result) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
diff --git a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc
index e6bc455..36a153d 100644
--- a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc
+++ b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.cc
@@ -8,8 +8,10 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
+#include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/sequenced_task_runner.h"
+#include "chrome/browser/android/offline_pages/background_loader_offliner.h"
 #include "chrome/browser/android/offline_pages/background_scheduler_bridge.h"
 #include "chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.h"
 #include "chrome/browser/android/offline_pages/evaluation/evaluation_test_scheduler.h"
@@ -123,53 +125,11 @@
   base::android::RunCallbackAndroid(j_callback_obj,
                                     int(removed_request_results.size()));
 }
-}  // namespace
 
-static ScopedJavaLocalRef<jobject> GetBridgeForProfile(
-    JNIEnv* env,
-    const JavaParamRef<jclass>& jcaller,
-    const JavaParamRef<jobject>& j_profile,
-    const jboolean j_use_evaluation_scheduler) {
-  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
-
-  OfflinePageModel* offline_page_model =
-      OfflinePageModelFactory::GetForBrowserContext(profile);
-
-  RequestCoordinator* request_coordinator = nullptr;
-
-  if (j_use_evaluation_scheduler) {
-    request_coordinator = static_cast<RequestCoordinator*>(
-        RequestCoordinatorFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile,
-            &OfflinePageEvaluationBridge::GetTestingRequestCoordinator));
-  } else {
-    request_coordinator =
-        RequestCoordinatorFactory::GetForBrowserContext(profile);
-  }
-
-  if (offline_page_model == nullptr || request_coordinator == nullptr)
-    return ScopedJavaLocalRef<jobject>();
-
-  OfflinePageEvaluationBridge* bridge = new OfflinePageEvaluationBridge(
-      env, profile, offline_page_model, request_coordinator);
-
-  return ScopedJavaLocalRef<jobject>(bridge->java_ref());
-}
-
-// static
-bool OfflinePageEvaluationBridge::Register(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-// static
-std::unique_ptr<KeyedService>
-OfflinePageEvaluationBridge::GetTestingRequestCoordinator(
-    content::BrowserContext* context) {
-  std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy());
-  std::unique_ptr<Offliner> prerenderer_offliner(new PrerenderingOffliner(
-      context, policy.get(),
-      OfflinePageModelFactory::GetForBrowserContext(context)));
-
+std::unique_ptr<KeyedService> GetTestingRequestCoordinator(
+    content::BrowserContext* context,
+    std::unique_ptr<OfflinerPolicy> policy,
+    std::unique_ptr<Offliner> offliner) {
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
       content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
           content::BrowserThread::GetBlockingPool()->GetSequenceToken());
@@ -189,7 +149,7 @@
   // dispatcher.
   std::unique_ptr<RequestCoordinator> request_coordinator =
       base::MakeUnique<RequestCoordinator>(
-          std::move(policy), std::move(prerenderer_offliner), std::move(queue),
+          std::move(policy), std::move(offliner), std::move(queue),
           std::move(scheduler), network_quality_estimator);
   request_coordinator->SetInternalStartProcessingCallbackForTest(
       base::Bind(&android::EvaluationTestScheduler::ImmediateScheduleCallback,
@@ -202,6 +162,72 @@
   return std::move(request_coordinator);
 }
 
+std::unique_ptr<KeyedService> GetTestPrerenderRequestCoordinator(
+    content::BrowserContext* context) {
+  std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy());
+  std::unique_ptr<Offliner> offliner(new PrerenderingOffliner(
+      context, policy.get(),
+      OfflinePageModelFactory::GetForBrowserContext(context)));
+  return GetTestingRequestCoordinator(context, std::move(policy),
+                                      std::move(offliner));
+}
+
+std::unique_ptr<KeyedService> GetTestBackgroundLoaderRequestCoordinator(
+    content::BrowserContext* context) {
+  std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy());
+  std::unique_ptr<Offliner> offliner(new BackgroundLoaderOffliner(
+      context, policy.get(),
+      OfflinePageModelFactory::GetForBrowserContext(context)));
+  return GetTestingRequestCoordinator(context, std::move(policy),
+                                      std::move(offliner));
+}
+
+RequestCoordinator* GetRequestCoordinator(Profile* profile,
+                                          bool use_evaluation_scheduler,
+                                          bool use_background_loader) {
+  if (!use_evaluation_scheduler) {
+    return RequestCoordinatorFactory::GetForBrowserContext(profile);
+  }
+  if (use_background_loader) {
+    return static_cast<RequestCoordinator*>(
+        RequestCoordinatorFactory::GetInstance()->SetTestingFactoryAndUse(
+            profile, &GetTestBackgroundLoaderRequestCoordinator));
+  }
+  return static_cast<RequestCoordinator*>(
+      RequestCoordinatorFactory::GetInstance()->SetTestingFactoryAndUse(
+          profile, &GetTestPrerenderRequestCoordinator));
+}
+}  // namespace
+
+// static
+bool OfflinePageEvaluationBridge::Register(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+static ScopedJavaLocalRef<jobject> GetBridgeForProfile(
+    JNIEnv* env,
+    const JavaParamRef<jclass>& jcaller,
+    const JavaParamRef<jobject>& j_profile,
+    const jboolean j_use_evaluation_scheduler,
+    const jboolean j_use_background_loader) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+
+  OfflinePageModel* offline_page_model =
+      OfflinePageModelFactory::GetForBrowserContext(profile);
+
+  RequestCoordinator* request_coordinator = GetRequestCoordinator(
+      profile, static_cast<bool>(j_use_evaluation_scheduler),
+      static_cast<bool>(j_use_background_loader));
+
+  if (offline_page_model == nullptr || request_coordinator == nullptr)
+    return ScopedJavaLocalRef<jobject>();
+
+  OfflinePageEvaluationBridge* bridge = new OfflinePageEvaluationBridge(
+      env, profile, offline_page_model, request_coordinator);
+
+  return ScopedJavaLocalRef<jobject>(bridge->java_ref());
+}
+
 OfflinePageEvaluationBridge::OfflinePageEvaluationBridge(
     JNIEnv* env,
     content::BrowserContext* browser_context,
diff --git a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h
index f6326174..ed92ee5 100644
--- a/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h
+++ b/chrome/browser/android/offline_pages/evaluation/offline_page_evaluation_bridge.h
@@ -30,8 +30,6 @@
                                     public OfflineEventLogger::Client {
  public:
   static bool Register(JNIEnv* env);
-  static std::unique_ptr<KeyedService> GetTestingRequestCoordinator(
-      content::BrowserContext* context);
 
   OfflinePageEvaluationBridge(JNIEnv* env,
                               content::BrowserContext* browser_context,
diff --git a/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py b/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py
index 84d9bb7..5f27311 100755
--- a/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py
+++ b/chrome/browser/android/offline_pages/evaluation/run_offline_page_evaluation_test.py
@@ -29,14 +29,19 @@
 
 DEFAULT_USER_REQUEST = True
 DEFAULT_USE_TEST_SCHEDULER = True
+DEFAULT_USE_BACKGROUND_LOADER = False
 # 0 means the batch would be the whole list of urls.
 DEFAULT_BATCH_SIZE = 0
 DEFAULT_VERBOSE = False
+PRERENDER_TEST_CMD = 'OfflinePageSavePageLaterEvaluationTest.testFailureRate'
+BACKGROUND_LOADER_CMD = 'OfflinePageSavePageLaterEvaluationTest.' \
+                        'testBackgroundLoaderFailureRate'
 CONFIG_FILENAME = 'test_config'
 CONFIG_TEMPLATE = """\
 IsUserRequested = {is_user_requested}
 UseTestScheduler = {use_test_scheduler}
 ScheduleBatchSize = {schedule_batch_size}
+UseBackgroundLoader = {use_background_loader}
 """
 
 
@@ -87,12 +92,23 @@
   parser.add_argument('build_output_dir', help='Path to build directory.')
   parser.add_argument(
       'test_urls_file', help='Path to input file with urls to be tested.')
+  parser.add_argument(
+      '--use-background-loader',
+      dest='use_background_loader',
+      action='store_true',
+      help='Use background loader instead of prerenderer.')
+  parser.add_argument(
+      '--use-prerenderer',
+      dest='use_background_loader',
+      action='store_false',
+      help='Use prerenderer instead of background loader.')
   parser.set_defaults(
       output_dir=os.path.expanduser('~/offline_eval_output'),
       user_request=DEFAULT_USER_REQUEST,
       use_test_scheduler=DEFAULT_USE_TEST_SCHEDULER,
       schedule_batch_size=DEFAULT_BATCH_SIZE,
-      verbose=DEFAULT_VERBOSE)
+      verbose=DEFAULT_VERBOSE,
+      use_background_loader=DEFAULT_USE_BACKGROUND_LOADER)
 
   # Get the arguments and several paths.
   options, extra_args = parser.parse_known_args(args)
@@ -131,7 +147,8 @@
         CONFIG_TEMPLATE.format(
             is_user_requested=options.user_request,
             use_test_scheduler=options.use_test_scheduler,
-            schedule_batch_size=options.schedule_batch_size))
+            schedule_batch_size=options.schedule_batch_size,
+            use_background_loader=options.use_background_loader))
 
   print 'Uploading config file and input file onto the device.'
   subprocess.call(
@@ -146,7 +163,8 @@
   print CONFIG_TEMPLATE.format(
       is_user_requested=options.user_request,
       use_test_scheduler=options.use_test_scheduler,
-      schedule_batch_size=options.schedule_batch_size)
+      schedule_batch_size=options.schedule_batch_size,
+      use_background_loader=options.use_background_loader)
   # Run test with timeout-scale as 20.0 and strict mode off.
   # This scale is only applied to timeouts which are defined as scalable ones
   # in the test framework (like the timeout used to decide if Chrome doesn't
@@ -158,8 +176,6 @@
   # violations when writing to files.
   test_runner_cmd = [
       test_runner_path,
-      '-f',
-      'OfflinePageSavePageLaterEvaluationTest.testFailureRate',
       '--timeout-scale',
       '20.0',
       '--strict-mode',
@@ -169,6 +185,11 @@
     test_runner_cmd += ['-v']
   if options.device_id != None:
     test_runner_cmd += ['-d', options.device_id]
+
+  if options.use_background_loader:
+    test_runner_cmd += ['-f', BACKGROUND_LOADER_CMD]
+  else:
+    test_runner_cmd += ['-f', PRERENDER_TEST_CMD]
   subprocess.call(test_runner_cmd)
 
   print 'Fetching results from device...'
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index d40c062..6710125 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -13,9 +13,6 @@
         <structure name="IDR_APP_LIST_START_PAGE_HTML" file="resources\app_list\start_page.html" flattenhtml="true" type="chrome_html" />
         <structure name="IDR_APP_LIST_START_PAGE_JS" file="resources\app_list\start_page.js" flattenhtml="true" type="chrome_html" />
       </if>
-      <if expr="not is_android and not use_vulcanize">
-        <structure name="IDR_MD_DOWNLOADS_DOWNLOADS_HTML" file="resources\md_downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
-      </if>
       <if expr="enable_extensions">
         <structure name="IDR_EXTENSIONS_HTML" file="resources\extensions\extensions.html" flattenhtml="true" type="chrome_html" />
         <structure name="IDR_MD_EXTENSIONS_EXTENSIONS_HTML" file="resources\md_extensions\extensions.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
@@ -144,10 +141,11 @@
         <include name="IDR_MD_DOWNLOADS_2X_NO_DOWNLOADS_PNG" file="resources\md_downloads\2x\no_downloads.png" type="BINDATA" />
         <if expr="use_vulcanize">
           <then>
-            <include name="IDR_MD_DOWNLOADS_CRISPER_JS" file="resources\md_downloads\crisper.js" flattenhtml="true" type="BINDATA" compress="gzip" />
-            <include name="IDR_MD_DOWNLOADS_VULCANIZED_HTML" file="resources\md_downloads\vulcanized.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+            <include name="IDR_MD_DOWNLOADS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\md_downloads\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+            <include name="IDR_MD_DOWNLOADS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\md_downloads\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
           </then>
           <else>
+            <include name="IDR_MD_DOWNLOADS_DOWNLOADS_HTML" file="resources\md_downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
             <include name="IDR_MD_DOWNLOADS_ACTION_SERVICE_HTML" file="resources\md_downloads\action_service.html" type="BINDATA" />
             <include name="IDR_MD_DOWNLOADS_ACTION_SERVICE_JS" file="resources\md_downloads\action_service.js" type="BINDATA" />
             <include name="IDR_MD_DOWNLOADS_CONSTANTS_HTML" file="resources\md_downloads\constants.html" type="BINDATA" />
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 2bc59ab..5436b5e 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -209,6 +209,8 @@
     "app_mode/kiosk_session_plugin_handler_delegate.h",
     "app_mode/startup_app_launcher.cc",
     "app_mode/startup_app_launcher.h",
+    "arc/accessibility/arc_accessibility_helper_bridge.cc",
+    "arc/accessibility/arc_accessibility_helper_bridge.h",
     "arc/arc_auth_context.cc",
     "arc/arc_auth_context.h",
     "arc/arc_auth_notification.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc
index 69f935f..90024dc5 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.cc
@@ -76,6 +76,12 @@
   registered_observers_ = true;
 }
 
+void AccessibilityHighlightManager::OnViewFocusedInArc(
+    const gfx::Rect& bounds_in_screen) {
+  focus_rect_ = bounds_in_screen;
+  UpdateFocusAndCaretHighlights();
+}
+
 void AccessibilityHighlightManager::OnMouseEvent(ui::MouseEvent* event) {
   if (event->type() == ui::ET_MOUSE_MOVED) {
     cursor_point_ = event->location();
diff --git a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h
index bb2b5e120..facbcbb 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager.h
@@ -16,6 +16,10 @@
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 
+namespace gfx {
+class Rect;
+}  // namespace gfx
+
 namespace chromeos {
 
 // Manage visual highlights that Chrome OS can draw around the focused
@@ -35,6 +39,10 @@
 
   void RegisterObservers();
 
+  // OnViewFocusedInArc is called when a view is focused in arc window and
+  // accessibility focus highlight is enabled.
+  void OnViewFocusedInArc(const gfx::Rect& bounds_in_screen);
+
  protected:
   FRIEND_TEST_ALL_PREFIXES(AccessibilityFocusRingControllerTest,
                            CursorWorksOnMultipleDisplays);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 913c2af6..6c43cf7 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -544,6 +544,11 @@
   EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_NONE);
 }
 
+void AccessibilityManager::OnViewFocusedInArc(
+    const gfx::Rect& bounds_in_screen) {
+  accessibility_highlight_manager_->OnViewFocusedInArc(bounds_in_screen);
+}
+
 bool AccessibilityManager::PlayEarcon(int sound_key, PlaySoundOption option) {
   DCHECK(sound_key < chromeos::SOUND_COUNT);
   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 3da064d05..4acbe97 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -28,6 +28,10 @@
 
 class Profile;
 
+namespace gfx {
+class Rect;
+}  // namespace gfx
+
 namespace chromeos {
 
 class AccessibilityExtensionLoader;
@@ -250,6 +254,9 @@
   // Play tick sound indicating spoken feedback will be toggled after countdown.
   bool PlaySpokenFeedbackToggleCountdown(int tick_count);
 
+  // Notify that a view is focused in arc.
+  void OnViewFocusedInArc(const gfx::Rect& bounds_in_screen);
+
   // Plays an earcon. Earcons are brief and distinctive sounds that indicate
   // when their mapped event has occurred. The sound key enums can be found in
   // chromeos/audio/chromeos_sounds.h.
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
new file mode 100644
index 0000000..6e3c1a4
--- /dev/null
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -0,0 +1,63 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h"
+
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/exo/wm_helper.h"
+#include "ui/aura/window.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace arc {
+
+ArcAccessibilityHelperBridge::ArcAccessibilityHelperBridge(
+    ArcBridgeService* bridge_service)
+    : ArcService(bridge_service), binding_(this) {
+  arc_bridge_service()->accessibility_helper()->AddObserver(this);
+}
+
+ArcAccessibilityHelperBridge::~ArcAccessibilityHelperBridge() {
+  arc_bridge_service()->accessibility_helper()->RemoveObserver(this);
+}
+
+void ArcAccessibilityHelperBridge::OnInstanceReady() {
+  auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
+      arc_bridge_service()->accessibility_helper(), Init);
+  DCHECK(instance);
+  instance->Init(binding_.CreateInterfacePtrAndBind());
+}
+
+void ArcAccessibilityHelperBridge::OnAccessibilityEvent(
+    mojom::AccessibilityEventType event_type,
+    mojom::AccessibilityNodeInfoDataPtr event_source) {
+  if (event_type != mojom::AccessibilityEventType::VIEW_FOCUSED ||
+      event_source.is_null()) {
+    return;
+  }
+
+  chromeos::AccessibilityManager* accessibility_manager =
+      chromeos::AccessibilityManager::Get();
+
+  if (!accessibility_manager ||
+      !accessibility_manager->IsFocusHighlightEnabled()) {
+    return;
+  }
+
+  exo::WMHelper* wmHelper = exo::WMHelper::GetInstance();
+
+  aura::Window* focused_window = wmHelper->GetFocusedWindow();
+  if (!focused_window)
+    return;
+
+  aura::Window* toplevel_window = focused_window->GetToplevelWindow();
+
+  gfx::Rect bounds_in_screen = gfx::ScaleToEnclosingRect(
+      event_source.get()->boundsInScreen,
+      1.0f / toplevel_window->layer()->device_scale_factor());
+
+  accessibility_manager->OnViewFocusedInArc(bounds_in_screen);
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h
new file mode 100644
index 0000000..ad4abbd
--- /dev/null
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ARC_ACCESSIBILITY_HELPER_BRIDGE_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ARC_ACCESSIBILITY_HELPER_BRIDGE_H_
+
+#include "components/arc/arc_service.h"
+#include "components/arc/common/accessibility_helper.mojom.h"
+#include "components/arc/instance_holder.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace arc {
+
+class ArcBridgeService;
+
+// ArcAccessibilityHelperBridge is an instance to receive converted Android
+// accessibility events and info via mojo interface and dispatch them to chrome
+// os components.
+class ArcAccessibilityHelperBridge
+    : public ArcService,
+      public mojom::AccessibilityHelperHost,
+      public InstanceHolder<mojom::AccessibilityHelperInstance>::Observer {
+ public:
+  explicit ArcAccessibilityHelperBridge(ArcBridgeService* bridge_service);
+  ~ArcAccessibilityHelperBridge() override;
+
+  // InstanceHolder<mojom::AccessibilityHelperInstance>::Observer overrides.
+  void OnInstanceReady() override;
+
+  // mojom::AccessibilityHelperHost overrides.
+  void OnAccessibilityEvent(
+      mojom::AccessibilityEventType event_type,
+      mojom::AccessibilityNodeInfoDataPtr event_source) override;
+
+ private:
+  mojo::Binding<mojom::AccessibilityHelperHost> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcAccessibilityHelperBridge);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ARC_ACCESSIBILITY_HELPER_BRIDGE_H_
diff --git a/chrome/browser/chromeos/arc/arc_service_launcher.cc b/chrome/browser/chromeos/arc/arc_service_launcher.cc
index 1fa45a7..a20b4d7 100644
--- a/chrome/browser/chromeos/arc/arc_service_launcher.cc
+++ b/chrome/browser/chromeos/arc/arc_service_launcher.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h"
+#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h"
 #include "chrome/browser/chromeos/arc/arc_auth_service.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h"
@@ -88,6 +89,8 @@
 
   // List in lexicographical order.
   arc_service_manager_->AddService(
+      base::MakeUnique<ArcAccessibilityHelperBridge>(arc_bridge_service));
+  arc_service_manager_->AddService(
       base::MakeUnique<ArcAudioBridge>(arc_bridge_service));
   arc_service_manager_->AddService(
       base::MakeUnique<ArcAuthService>(arc_bridge_service));
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
index 552675f..c4aad82 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
@@ -118,6 +118,7 @@
   // Send settings that need to be synced only on Android first start to
   // Android.
   void SyncInitialSettings() const;
+  void SyncFocusHighlightEnabled() const;
   void SyncFontSize() const;
   void SyncLocale() const;
   void SyncProxySettings() const;
@@ -185,16 +186,18 @@
   Profile* profile = ProfileManager::GetActiveUserProfile();
   registrar_.Init(profile->GetPrefs());
 
+  // Keep these lines ordered lexicographically.
+  AddPrefToObserve(prefs::kAccessibilityFocusHighlightEnabled);
+  AddPrefToObserve(prefs::kAccessibilitySpokenFeedbackEnabled);
+  AddPrefToObserve(prefs::kAccessibilityVirtualKeyboardEnabled);
+  AddPrefToObserve(prefs::kArcBackupRestoreEnabled);
+  AddPrefToObserve(prefs::kUse24HourClock);
   AddPrefToObserve(prefs::kWebKitDefaultFixedFontSize);
   AddPrefToObserve(prefs::kWebKitDefaultFontSize);
   AddPrefToObserve(prefs::kWebKitMinimumFontSize);
-  AddPrefToObserve(prefs::kAccessibilitySpokenFeedbackEnabled);
-  AddPrefToObserve(prefs::kUse24HourClock);
-  AddPrefToObserve(prefs::kArcBackupRestoreEnabled);
   AddPrefToObserve(proxy_config::prefs::kProxy);
   AddPrefToObserve(onc::prefs::kDeviceOpenNetworkConfiguration);
   AddPrefToObserve(onc::prefs::kOpenNetworkConfiguration);
-  AddPrefToObserve(prefs::kAccessibilityVirtualKeyboardEnabled);
 
   reporting_consent_subscription_ = CrosSettings::Get()->AddSettingsObserver(
       chromeos::kStatsReportingPref,
@@ -227,6 +230,9 @@
 }
 
 void ArcSettingsServiceImpl::SyncRuntimeSettings() const {
+  // Keep these lines ordered lexicographically.
+  SyncAccessibilityVirtualKeyboardEnabled();
+  SyncFocusHighlightEnabled();
   SyncFontSize();
   SyncLocale();
   SyncProxySettings();
@@ -234,7 +240,6 @@
   SyncSpokenFeedbackEnabled();
   SyncTimeZone();
   SyncUse24HourClock();
-  SyncAccessibilityVirtualKeyboardEnabled();
 
   const PrefService* const prefs =
       ProfileManager::GetActiveUserProfile()->GetPrefs();
@@ -273,7 +278,9 @@
 }
 
 void ArcSettingsServiceImpl::OnPrefChanged(const std::string& pref_name) const {
-  if (pref_name == prefs::kAccessibilitySpokenFeedbackEnabled) {
+  if (pref_name == prefs::kAccessibilityFocusHighlightEnabled) {
+    SyncFocusHighlightEnabled();
+  } else if (pref_name == prefs::kAccessibilitySpokenFeedbackEnabled) {
     SyncSpokenFeedbackEnabled();
   } else if (pref_name == prefs::kWebKitDefaultFixedFontSize ||
              pref_name == prefs::kWebKitDefaultFontSize ||
@@ -342,6 +349,12 @@
   SendSettingsBroadcast(action, extras);
 }
 
+void ArcSettingsServiceImpl::SyncFocusHighlightEnabled() const {
+  SendBoolPrefSettingsBroadcast(
+      prefs::kAccessibilityFocusHighlightEnabled,
+      "org.chromium.arc.intent_helper.SET_FOCUS_HIGHLIGHT_ENABLED");
+}
+
 void ArcSettingsServiceImpl::SyncSpokenFeedbackEnabled() const {
   SendBoolPrefSettingsBroadcast(
       prefs::kAccessibilitySpokenFeedbackEnabled,
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 7daaef1..325a624 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -1795,7 +1795,10 @@
 ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
 
 bool ExecuteCodeInTabFunction::HasPermission() {
-  if (Init() &&
+  if (Init() == SUCCESS &&
+      // TODO(devlin/lazyboy): Consider removing the following check as it isn't
+      // doing anything. The fallback to ExtensionFunction::HasPermission()
+      // below dictates what this function returns.
       extension_->permissions_data()->HasAPIPermissionForTab(
           execute_tab_id_, APIPermission::kTab)) {
     return true;
@@ -1803,38 +1806,40 @@
   return ExtensionFunction::HasPermission();
 }
 
-bool ExecuteCodeInTabFunction::Init() {
-  if (details_.get())
-    return true;
+ExecuteCodeFunction::InitResult ExecuteCodeInTabFunction::Init() {
+  if (init_result_)
+    return init_result_.value();
 
   // |tab_id| is optional so it's ok if it's not there.
   int tab_id = -1;
-  if (args_->GetInteger(0, &tab_id))
-    EXTENSION_FUNCTION_VALIDATE(tab_id >= 0);
+  if (args_->GetInteger(0, &tab_id) && tab_id < 0)
+    return set_init_result(VALIDATION_FAILURE);
 
   // |details| are not optional.
   base::DictionaryValue* details_value = NULL;
   if (!args_->GetDictionary(1, &details_value))
-    return false;
+    return set_init_result(VALIDATION_FAILURE);
   std::unique_ptr<InjectDetails> details(new InjectDetails());
   if (!InjectDetails::Populate(*details_value, details.get()))
-    return false;
+    return set_init_result(VALIDATION_FAILURE);
 
   // If the tab ID wasn't given then it needs to be converted to the
   // currently active tab's ID.
   if (tab_id == -1) {
     Browser* browser = chrome_details_.GetCurrentBrowser();
+    // Can happen during shutdown.
     if (!browser)
-      return false;
+      return set_init_result_error(keys::kNoCurrentWindowError);
     content::WebContents* web_contents = NULL;
+    // Can happen during shutdown.
     if (!ExtensionTabUtil::GetDefaultTab(browser, &web_contents, &tab_id))
-      return false;
+      return set_init_result_error(keys::kNoTabInBrowserWindowError);
   }
 
   execute_tab_id_ = tab_id;
   details_ = std::move(details);
   set_host_id(HostID(HostID::EXTENSIONS, extension()->id()));
-  return true;
+  return set_init_result(SUCCESS);
 }
 
 bool ExecuteCodeInTabFunction::CanExecuteScriptOnPage() {
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.h b/chrome/browser/extensions/api/tabs/tabs_api.h
index 82b5d1b..c8e4071 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.h
+++ b/chrome/browser/extensions/api/tabs/tabs_api.h
@@ -234,9 +234,8 @@
   // ExtensionFunction:
   bool HasPermission() override;
 
-  // Initialize the |execute_tab_id_| and |details_| if they haven't already
-  // been. Returns whether initialization was successful.
-  bool Init() override;
+  // Initializes |execute_tab_id_| and |details_|.
+  InitResult Init() override;
   bool CanExecuteScriptOnPage() override;
   ScriptExecutor* GetScriptExecutor() override;
   bool IsWebView() const override;
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
index 506cc94..1128010 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
+#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/browser/extensions/extension_service_test_base.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
@@ -270,4 +271,30 @@
   base::RunLoop().RunUntilIdle();
 }
 
+// Tests that non-validation failure in tabs.executeScript results in error, and
+// not bad_message.
+// Regression test for https://crbug.com/642794.
+TEST_F(TabsApiUnitTest, ExecuteScriptNoTabIsNonFatalError) {
+  // An extension with "tabs" permission.
+  scoped_refptr<const Extension> extension =
+      ExtensionBuilder()
+          .SetManifest(
+              DictionaryBuilder()
+                  .Set("name", "Extension with tabs permission")
+                  .Set("version", "1.0")
+                  .Set("manifest_version", 2)
+                  .Set("permissions", ListBuilder().Append("tabs").Build())
+                  .Build())
+          .Build();
+  scoped_refptr<TabsExecuteScriptFunction> function(
+      new TabsExecuteScriptFunction());
+  function->set_extension(extension);
+  const char* kArgs = R"(["", {"code": ""}])";
+  std::string error = extension_function_test_utils::RunFunctionAndReturnError(
+      function.get(), kArgs,
+      browser(),  // browser() doesn't have any tabs.
+      extension_function_test_utils::NONE);
+  EXPECT_EQ(tabs_constants::kNoTabInBrowserWindowError, error);
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.cc b/chrome/browser/extensions/api/tabs/tabs_constants.cc
index 8df23c8..4d60c1a 100644
--- a/chrome/browser/extensions/api/tabs/tabs_constants.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_constants.cc
@@ -81,6 +81,7 @@
     "I'm sorry. I'm afraid I can't do that.";
 const char kNoCurrentWindowError[] = "No current window";
 const char kNoLastFocusedWindowError[] = "No last-focused window";
+const char kNoTabInBrowserWindowError[] = "There is no tab in browser window.";
 const char kPerOriginOnlyInAutomaticError[] = "Can only set scope to "
     "\"per-origin\" in \"automatic\" mode.";
 const char kWindowNotFoundError[] = "No window with id: *.";
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.h b/chrome/browser/extensions/api/tabs/tabs_constants.h
index 92f6661..d4a399b 100644
--- a/chrome/browser/extensions/api/tabs/tabs_constants.h
+++ b/chrome/browser/extensions/api/tabs/tabs_constants.h
@@ -82,6 +82,7 @@
 extern const char kNoCrashBrowserError[];
 extern const char kNoCurrentWindowError[];
 extern const char kNoLastFocusedWindowError[];
+extern const char kNoTabInBrowserWindowError[];
 extern const char kPerOriginOnlyInAutomaticError[];
 extern const char kWindowNotFoundError[];
 extern const char kTabIndexNotFoundError[];
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
index d666f55..22ae267 100644
--- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
+++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -15,7 +15,6 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
@@ -363,10 +362,6 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
-  content::RenderViewHost* render_view_host() {
-    return active_contents()->GetRenderViewHost();
-  }
-
   // static
   // Adds an <input> field to a given frame by executing javascript code.
   // The input can be added as the first element or the last element of
@@ -911,9 +906,9 @@
 }
 
 // This test tracks page level focused editable element tracking using
-// RenderViewHost. In a page with multiple frames, a frame is selected and
+// WebContents. In a page with multiple frames, a frame is selected and
 // focused. Then the <input> inside frame is both focused and blurred and  and
-// in both cases the test verifies that RendeViewHost is aware whether or not a
+// in both cases the test verifies that WebContents is aware whether or not a
 // focused editable element exists on the page.
 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
                        TrackPageFocusEditableElement) {
@@ -938,17 +933,17 @@
     focus_frame(frame);
     // Focus the <input>.
     set_input_focus(frame, true);
-    EXPECT_TRUE(render_view_host()->IsFocusedElementEditable());
+    EXPECT_TRUE(active_contents()->IsFocusedElementEditable());
     // No blur <input>.
     set_input_focus(frame, false);
-    EXPECT_FALSE(render_view_host()->IsFocusedElementEditable());
+    EXPECT_FALSE(active_contents()->IsFocusedElementEditable());
   }
 }
 
 // TODO(ekaramad): Could this become a unit test instead?
 // This test focuses <input> elements on the page and verifies that
-// RenderViewHost knows about the focused editable element. Then it asks the
-// RenderViewHost to clear focused element and verifies that there is no longer
+// WebContents knows about the focused editable element. Then it asks the
+// WebContents to clear focused element and verifies that there is no longer
 // a focused editable element on the page.
 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
                        ClearFocusedElementOnPage) {
@@ -967,9 +962,9 @@
 
   for (auto* frame : frames) {
     focus_frame_and_input(frame);
-    EXPECT_TRUE(render_view_host()->IsFocusedElementEditable());
-    render_view_host()->ClearFocusedElement();
-    EXPECT_FALSE(render_view_host()->IsFocusedElementEditable());
+    EXPECT_TRUE(active_contents()->IsFocusedElementEditable());
+    active_contents()->ClearFocusedElement();
+    EXPECT_FALSE(active_contents()->IsFocusedElementEditable());
   }
 }
 
diff --git a/chrome/browser/resources/chromeos/first_run/app/main.html b/chrome/browser/resources/chromeos/first_run/app/main.html
index a8c6df8..32e52a3 100644
--- a/chrome/browser/resources/chromeos/first_run/app/main.html
+++ b/chrome/browser/resources/chromeos/first_run/app/main.html
@@ -26,14 +26,14 @@
           </div>
         </div>
       </div>
-      <h1>$i18n{greetingHeader}</h1>
+      <h1 i18n-content="greetingHeader"></h1>
       <p>
-        <span>$i18n{greetingText1}</span><br>
-        <span>$i18n{greetingText2}</span>
+        <span i18n-content="greetingText1"></span><br>
+        <span i18n-content="greetingText2"></span>
       </p>
       <div class="controls">
-        <button class="next-button custom-appearance blue-button" tabindex="0">
-          $i18n{greetingButton}
+        <button i18n-content="greetingButton"
+            class="next-button custom-appearance blue-button" tabindex="0">
         </button>
       </div>
       <include src="greeting_image_[GREETING_IMAGE].html">
diff --git a/chrome/browser/resources/chromeos/first_run/app_list_step.html b/chrome/browser/resources/chromeos/first_run/app_list_step.html
index 7cb2e4d..bdc51ce 100644
--- a/chrome/browser/resources/chromeos/first_run/app_list_step.html
+++ b/chrome/browser/resources/chromeos/first_run/app_list_step.html
@@ -1,12 +1,11 @@
 <div id="app-list" class="step bubble transparent hidden">
-  <h1>$i18n{appListHeader}</h1>
+  <h1 i18n-content="appListHeader"></h1>
   <p>
-    <span>$i18n{appListText1}</span><br>
-    <span>$i18n{appListText2}</span>
+    <span i18n-content="appListText1"></span><br>
+    <span i18n-content="appListText2"></span>
   </p>
   <div class="controls">
-    <button class="next-button custom-appearance blue-button">
-      $i18n{nextButton}
-    </button>
+    <button i18n-content="nextButton"
+        class="next-button custom-appearance blue-button"></button>
   </div>
 </div>
diff --git a/chrome/browser/resources/chromeos/first_run/help_step.html b/chrome/browser/resources/chromeos/first_run/help_step.html
index 44659862..0a9c513 100644
--- a/chrome/browser/resources/chromeos/first_run/help_step.html
+++ b/chrome/browser/resources/chromeos/first_run/help_step.html
@@ -1,14 +1,12 @@
 <div id="help" class="step bubble transparent hidden">
   <div id="completion-image"></div>
-  <h1>$i18n{helpHeader}</h1>
-  <p>$i18n{helpText1}</p>
-  <p>$i18n{helpText2}</p>
+  <h1 i18n-content="helpHeader"></h1>
+  <p i18n-content="helpText1"></p>
+  <p i18n-content="helpText2"></p>
   <div class="controls">
-    <button class="help-button custom-appearance blue-button">
-      $i18n{helpKeepExploringButton}
-    </button>
-    <button class="next-button custom-appearance white-button">
-      $i18n{helpFinishButton}
-    </button>
+    <button i18n-content="helpKeepExploringButton"
+        class="help-button custom-appearance blue-button"></button>
+    <button i18n-content="helpFinishButton"
+        class="next-button custom-appearance white-button"></button>
   </div>
 </div>
diff --git a/chrome/browser/resources/chromeos/first_run/tray_step.html b/chrome/browser/resources/chromeos/first_run/tray_step.html
index ed96e21..2b7b9e7 100644
--- a/chrome/browser/resources/chromeos/first_run/tray_step.html
+++ b/chrome/browser/resources/chromeos/first_run/tray_step.html
@@ -1,9 +1,8 @@
 <div id="tray" class="step bubble transparent hidden">
-  <h1>$i18n{trayHeader}</h1>
-  <p>$i18n{trayText}<p>
+  <h1 i18n-content="trayHeader"></h1>
+  <p i18n-content="trayText"><p>
   <div class="controls">
-    <button class="next-button custom-appearance blue-button">
-      $i18n{nextButton}
-    </button>
+    <button i18n-content="nextButton"
+        class="next-button custom-appearance blue-button"></button>
   </div>
 </div>
diff --git a/chrome/browser/resources/md_bookmarks/PRESUBMIT.py b/chrome/browser/resources/md_bookmarks/PRESUBMIT.py
new file mode 100644
index 0000000..1b816b29
--- /dev/null
+++ b/chrome/browser/resources/md_bookmarks/PRESUBMIT.py
@@ -0,0 +1,7 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+def CheckChangeOnUpload(input_api, output_api):
+  return input_api.canned_checks.CheckPatchFormatted(
+      input_api, output_api, check_js=True)
diff --git a/chrome/browser/resources/md_downloads/BUILD.gn b/chrome/browser/resources/md_downloads/BUILD.gn
new file mode 100644
index 0000000..1dc2cab
--- /dev/null
+++ b/chrome/browser/resources/md_downloads/BUILD.gn
@@ -0,0 +1,12 @@
+import("../vulcanize.gni")
+
+vulcanize("vulcanize") {
+  host = "downloads"
+  html_in_file = "downloads.html"
+  html_out_file = "vulcanized.html"
+
+  input_type = "FOLDER"
+  input = rebase_path(".", root_build_dir)
+  js_out_file = "crisper.js"
+  deps = []
+}
diff --git a/chrome/browser/resources/md_downloads/compiled_resources2.gyp b/chrome/browser/resources/md_downloads/compiled_resources2.gyp
index be6ef51..9d15a90 100644
--- a/chrome/browser/resources/md_downloads/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_downloads/compiled_resources2.gyp
@@ -64,6 +64,7 @@
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+        '<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
         '<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar',
         '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted',
         'action_service',
diff --git a/chrome/browser/resources/md_downloads/crisper.js b/chrome/browser/resources/md_downloads/crisper.js
deleted file mode 100644
index e28586a1..0000000
--- a/chrome/browser/resources/md_downloads/crisper.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2013 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.
-function assert(condition,opt_message){if(!condition){var message="Assertion failed";if(opt_message)message=message+": "+opt_message;var error=new Error(message);var global=function(){return this}();if(global.traceAssertionsForTesting)console.warn(error.stack);throw error}return condition}function assertNotReached(opt_message){assert(false,opt_message||"Unreachable code hit")}function assertInstanceof(value,type,opt_message){if(!(value instanceof type)){assertNotReached(opt_message||"Value "+value+" is not a[n] "+(type.name||typeof type))}return value}
-// Copyright 2016 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.
-function PromiseResolver(){this.resolve_;this.reject_;this.promise_=new Promise(function(resolve,reject){this.resolve_=resolve;this.reject_=reject}.bind(this))}PromiseResolver.prototype={get promise(){return this.promise_},set promise(p){assertNotReached()},get resolve(){return this.resolve_},set resolve(r){assertNotReached()},get reject(){return this.reject_},set reject(s){assertNotReached()}};
-// Copyright (c) 2012 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.
-var global=this;var WebUIListener;var cr=cr||function(){"use strict";function exportPath(name,opt_object,opt_objectToExportTo){var parts=name.split(".");var cur=opt_objectToExportTo||global;for(var part;parts.length&&(part=parts.shift());){if(!parts.length&&opt_object!==undefined){cur[part]=opt_object}else if(part in cur){cur=cur[part]}else{cur=cur[part]={}}}return cur}function dispatchPropertyChange(target,propertyName,newValue,oldValue){var e=new Event(propertyName+"Change");e.propertyName=propertyName;e.newValue=newValue;e.oldValue=oldValue;target.dispatchEvent(e)}function getAttributeName(jsName){return jsName.replace(/([A-Z])/g,"-$1").toLowerCase()}var PropertyKind={JS:"js",ATTR:"attr",BOOL_ATTR:"boolAttr"};function getGetter(name,kind){switch(kind){case PropertyKind.JS:var privateName=name+"_";return function(){return this[privateName]};case PropertyKind.ATTR:var attributeName=getAttributeName(name);return function(){return this.getAttribute(attributeName)};case PropertyKind.BOOL_ATTR:var attributeName=getAttributeName(name);return function(){return this.hasAttribute(attributeName)}}throw"not reached"}function getSetter(name,kind,opt_setHook){switch(kind){case PropertyKind.JS:var privateName=name+"_";return function(value){var oldValue=this[name];if(value!==oldValue){this[privateName]=value;if(opt_setHook)opt_setHook.call(this,value,oldValue);dispatchPropertyChange(this,name,value,oldValue)}};case PropertyKind.ATTR:var attributeName=getAttributeName(name);return function(value){var oldValue=this[name];if(value!==oldValue){if(value==undefined)this.removeAttribute(attributeName);else this.setAttribute(attributeName,value);if(opt_setHook)opt_setHook.call(this,value,oldValue);dispatchPropertyChange(this,name,value,oldValue)}};case PropertyKind.BOOL_ATTR:var attributeName=getAttributeName(name);return function(value){var oldValue=this[name];if(value!==oldValue){if(value)this.setAttribute(attributeName,name);else this.removeAttribute(attributeName);if(opt_setHook)opt_setHook.call(this,value,oldValue);dispatchPropertyChange(this,name,value,oldValue)}}}throw"not reached"}function defineProperty(obj,name,opt_kind,opt_setHook){if(typeof obj=="function")obj=obj.prototype;var kind=opt_kind||PropertyKind.JS;if(!obj.__lookupGetter__(name))obj.__defineGetter__(name,getGetter(name,kind));if(!obj.__lookupSetter__(name))obj.__defineSetter__(name,getSetter(name,kind,opt_setHook))}var uidCounter=1;function createUid(){return uidCounter++}function getUid(item){if(item.hasOwnProperty("uid"))return item.uid;return item.uid=createUid()}function dispatchSimpleEvent(target,type,opt_bubbles,opt_cancelable){var e=new Event(type,{bubbles:opt_bubbles,cancelable:opt_cancelable===undefined||opt_cancelable});return target.dispatchEvent(e)}function define(name,fun){var obj=exportPath(name);var exports=fun();for(var propertyName in exports){var propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor)Object.defineProperty(obj,propertyName,propertyDescriptor)}}function addSingletonGetter(ctor){ctor.getInstance=function(){return ctor.instance_||(ctor.instance_=new ctor)}}function makePublic(ctor,methods,opt_target){methods.forEach(function(method){ctor[method]=function(){var target=opt_target?document.getElementById(opt_target):ctor.getInstance();return target[method+"_"].apply(target,arguments)}})}var chromeSendResolverMap={};function webUIResponse(id,isSuccess,response){var resolver=chromeSendResolverMap[id];delete chromeSendResolverMap[id];if(isSuccess)resolver.resolve(response);else resolver.reject(response)}function sendWithPromise(methodName,var_args){var args=Array.prototype.slice.call(arguments,1);var promiseResolver=new PromiseResolver;var id=methodName+"_"+createUid();chromeSendResolverMap[id]=promiseResolver;chrome.send(methodName,[id].concat(args));return promiseResolver.promise}var webUIListenerMap={};function webUIListenerCallback(event,var_args){var eventListenersMap=webUIListenerMap[event];if(!eventListenersMap){return}var args=Array.prototype.slice.call(arguments,1);for(var listenerId in eventListenersMap){eventListenersMap[listenerId].apply(null,args)}}function addWebUIListener(eventName,callback){webUIListenerMap[eventName]=webUIListenerMap[eventName]||{};var uid=createUid();webUIListenerMap[eventName][uid]=callback;return{eventName:eventName,uid:uid}}function removeWebUIListener(listener){var listenerExists=webUIListenerMap[listener.eventName]&&webUIListenerMap[listener.eventName][listener.uid];if(listenerExists){delete webUIListenerMap[listener.eventName][listener.uid];return true}return false}return{addSingletonGetter:addSingletonGetter,createUid:createUid,define:define,defineProperty:defineProperty,dispatchPropertyChange:dispatchPropertyChange,dispatchSimpleEvent:dispatchSimpleEvent,exportPath:exportPath,getUid:getUid,makePublic:makePublic,PropertyKind:PropertyKind,addWebUIListener:addWebUIListener,removeWebUIListener:removeWebUIListener,sendWithPromise:sendWithPromise,webUIListenerCallback:webUIListenerCallback,webUIResponse:webUIResponse,get doc(){return document},get isMac(){return/Mac/.test(navigator.platform)},get isWindows(){return/Win/.test(navigator.platform)},get isChromeOS(){return/CrOS/.test(navigator.userAgent)},get isLinux(){return/Linux/.test(navigator.userAgent)},get isAndroid(){return/Android/.test(navigator.userAgent)},get isIOS(){return/iPad|iPhone|iPod/.test(navigator.platform)}}}();
-// Copyright (c) 2012 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.
-cr.define("cr.ui",function(){function decorate(source,constr){var elements;if(typeof source=="string")elements=cr.doc.querySelectorAll(source);else elements=[source];for(var i=0,el;el=elements[i];i++){if(!(el instanceof constr))constr.decorate(el)}}function createElementHelper(tagName,opt_bag){var doc;if(opt_bag&&opt_bag.ownerDocument)doc=opt_bag.ownerDocument;else doc=cr.doc;return doc.createElement(tagName)}function define(tagNameOrFunction){var createFunction,tagName;if(typeof tagNameOrFunction=="function"){createFunction=tagNameOrFunction;tagName=""}else{createFunction=createElementHelper;tagName=tagNameOrFunction}function f(opt_propertyBag){var el=createFunction(tagName,opt_propertyBag);f.decorate(el);for(var propertyName in opt_propertyBag){el[propertyName]=opt_propertyBag[propertyName]}return el}f.decorate=function(el){el.__proto__=f.prototype;el.decorate()};return f}function limitInputWidth(el,parentEl,min,opt_scale){el.style.width="10px";var doc=el.ownerDocument;var win=doc.defaultView;var computedStyle=win.getComputedStyle(el);var parentComputedStyle=win.getComputedStyle(parentEl);var rtl=computedStyle.direction=="rtl";var inputRect=el.getBoundingClientRect();var parentRect=parentEl.getBoundingClientRect();var startPos=rtl?parentRect.right-inputRect.right:inputRect.left-parentRect.left;var inner=parseInt(computedStyle.borderLeftWidth,10)+parseInt(computedStyle.paddingLeft,10)+parseInt(computedStyle.paddingRight,10)+parseInt(computedStyle.borderRightWidth,10);var parentPadding=rtl?parseInt(parentComputedStyle.paddingLeft,10):parseInt(parentComputedStyle.paddingRight,10);var max=parentEl.clientWidth-startPos-inner-parentPadding;if(opt_scale)max*=opt_scale;function limit(){if(el.scrollWidth>max){el.style.width=max+"px"}else{el.style.width=0;var sw=el.scrollWidth;if(sw<min){el.style.width=min+"px"}else{el.style.width=sw+"px"}}}el.addEventListener("input",limit);limit()}function toCssPx(pixels){if(!window.isFinite(pixels))console.error("Pixel value is not a number: "+pixels);return Math.round(pixels)+"px"}function swallowDoubleClick(e){var doc=e.target.ownerDocument;var counter=Math.min(1,e.detail);function swallow(e){e.stopPropagation();e.preventDefault()}function onclick(e){if(e.detail>counter){counter=e.detail;swallow(e)}else{doc.removeEventListener("dblclick",swallow,true);doc.removeEventListener("click",onclick,true)}}setTimeout(function(){doc.addEventListener("click",onclick,true);doc.addEventListener("dblclick",swallow,true)},0)}return{decorate:decorate,define:define,limitInputWidth:limitInputWidth,toCssPx:toCssPx,swallowDoubleClick:swallowDoubleClick}});
-// Copyright (c) 2012 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.
-cr.define("cr.ui",function(){function KeyboardShortcut(shortcut){var mods={};var ident="";shortcut.split("|").forEach(function(part){var partLc=part.toLowerCase();switch(partLc){case"alt":case"ctrl":case"meta":case"shift":mods[partLc+"Key"]=true;break;default:if(ident)throw Error("Invalid shortcut");ident=part}});this.ident_=ident;this.mods_=mods}KeyboardShortcut.prototype={matchesEvent:function(e){if(e.key==this.ident_){var mods=this.mods_;return["altKey","ctrlKey","metaKey","shiftKey"].every(function(k){return e[k]==!!mods[k]})}return false}};var Command=cr.ui.define("command");Command.prototype={__proto__:HTMLElement.prototype,decorate:function(){CommandManager.init(assert(this.ownerDocument));if(this.hasAttribute("shortcut"))this.shortcut=this.getAttribute("shortcut")},execute:function(opt_element){if(this.disabled)return;var doc=this.ownerDocument;if(doc.activeElement){var e=new Event("command",{bubbles:true});e.command=this;(opt_element||doc.activeElement).dispatchEvent(e)}},canExecuteChange:function(opt_node){dispatchCanExecuteEvent(this,opt_node||this.ownerDocument.activeElement)},shortcut_:"",get shortcut(){return this.shortcut_},set shortcut(shortcut){var oldShortcut=this.shortcut_;if(shortcut!==oldShortcut){this.keyboardShortcuts_=shortcut.split(/\s+/).map(function(shortcut){return new KeyboardShortcut(shortcut)});this.shortcut_=shortcut;cr.dispatchPropertyChange(this,"shortcut",this.shortcut_,oldShortcut)}},matchesEvent:function(e){if(!this.keyboardShortcuts_)return false;return this.keyboardShortcuts_.some(function(keyboardShortcut){return keyboardShortcut.matchesEvent(e)})}};cr.defineProperty(Command,"label",cr.PropertyKind.ATTR);cr.defineProperty(Command,"disabled",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"hidden",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"checked",cr.PropertyKind.BOOL_ATTR);cr.defineProperty(Command,"hideShortcutText",cr.PropertyKind.BOOL_ATTR);function dispatchCanExecuteEvent(command,target){var e=new CanExecuteEvent(command);target.dispatchEvent(e);command.disabled=!e.canExecute}var commandManagers={};function CommandManager(doc){doc.addEventListener("focus",this.handleFocus_.bind(this),true);doc.addEventListener("keydown",this.handleKeyDown_.bind(this),false)}CommandManager.init=function(doc){var uid=cr.getUid(doc);if(!(uid in commandManagers)){commandManagers[uid]=new CommandManager(doc)}};CommandManager.prototype={handleFocus_:function(e){var target=e.target;if(target.menu||target.command)return;var commands=Array.prototype.slice.call(target.ownerDocument.querySelectorAll("command"));commands.forEach(function(command){dispatchCanExecuteEvent(command,target)})},handleKeyDown_:function(e){var target=e.target;var commands=Array.prototype.slice.call(target.ownerDocument.querySelectorAll("command"));for(var i=0,command;command=commands[i];i++){if(command.matchesEvent(e)){command.canExecuteChange();if(!command.disabled){e.preventDefault();e.stopPropagation();command.execute();return}}}}};function CanExecuteEvent(command){var e=new Event("canExecute",{bubbles:true,cancelable:true});e.__proto__=CanExecuteEvent.prototype;e.command=command;return e}CanExecuteEvent.prototype={__proto__:Event.prototype,command:null,canExecute_:false,get canExecute(){return this.canExecute_},set canExecute(canExecute){this.canExecute_=!!canExecute;this.stopPropagation();this.preventDefault()}};return{Command:Command,CanExecuteEvent:CanExecuteEvent}});
-// Copyright (c) 2012 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.
-function $(id){var el=document.getElementById(id);return el?assertInstanceof(el,HTMLElement):null}function getSVGElement(id){var el=document.getElementById(id);return el?assertInstanceof(el,Element):null}function announceAccessibleMessage(msg){var element=document.createElement("div");element.setAttribute("aria-live","polite");element.style.position="fixed";element.style.left="-9999px";element.style.height="0px";element.innerText=msg;document.body.appendChild(element);window.setTimeout(function(){document.body.removeChild(element)},0)}function url(s){var s2=s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g,"\\$1");if(/\\\\$/.test(s2)){s2+=" "}return'url("'+s2+'")'}function parseQueryParams(location){var params={};var query=unescape(location.search.substring(1));var vars=query.split("&");for(var i=0;i<vars.length;i++){var pair=vars[i].split("=");params[pair[0]]=pair[1]}return params}function setQueryParam(location,key,value){var query=parseQueryParams(location);query[encodeURIComponent(key)]=encodeURIComponent(value);var newQuery="";for(var q in query){newQuery+=(newQuery?"&":"?")+q+"="+query[q]}return location.origin+location.pathname+newQuery+location.hash}function findAncestorByClass(el,className){return findAncestor(el,function(el){return el.classList&&el.classList.contains(className)})}function findAncestor(node,predicate){var last=false;while(node!=null&&!(last=predicate(node))){node=node.parentNode}return last?node:null}function swapDomNodes(a,b){var afterA=a.nextSibling;if(afterA==b){swapDomNodes(b,a);return}var aParent=a.parentNode;b.parentNode.replaceChild(a,b);aParent.insertBefore(b,afterA)}function disableTextSelectAndDrag(opt_allowSelectStart,opt_allowDragStart){document.onselectstart=function(e){if(!(opt_allowSelectStart&&opt_allowSelectStart.call(this,e)))e.preventDefault()};document.ondragstart=function(e){if(!(opt_allowDragStart&&opt_allowDragStart.call(this,e)))e.preventDefault()}}function preventDefaultOnPoundLinkClicks(){document.addEventListener("click",function(e){var anchor=findAncestor(e.target,function(el){return el.tagName=="A"});if(anchor&&anchor.getAttribute("href")=="#")e.preventDefault()})}function isRTL(){return document.documentElement.dir=="rtl"}function getRequiredElement(id){return assertInstanceof($(id),HTMLElement,"Missing required element: "+id)}function queryRequiredElement(selectors,opt_context){var element=(opt_context||document).querySelector(selectors);return assertInstanceof(element,HTMLElement,"Missing required element: "+selectors)}["click","auxclick"].forEach(function(eventName){document.addEventListener(eventName,function(e){if(e.button>1)return;if(e.defaultPrevented)return;var eventPath=e.path;var anchor=null;if(eventPath){for(var i=0;i<eventPath.length;i++){var element=eventPath[i];if(element.tagName==="A"&&element.href){anchor=element;break}}}var el=e.target;if(!anchor&&el.nodeType==Node.ELEMENT_NODE&&el.webkitMatchesSelector("A, A *")){while(el.tagName!="A"){el=el.parentElement}anchor=el}if(!anchor)return;anchor=anchor;if((anchor.protocol=="file:"||anchor.protocol=="about:")&&(e.button==0||e.button==1)){chrome.send("navigateToUrl",[anchor.href,anchor.target,e.button,e.altKey,e.ctrlKey,e.metaKey,e.shiftKey]);e.preventDefault()}})});function appendParam(url,key,value){var param=encodeURIComponent(key)+"="+encodeURIComponent(value);if(url.indexOf("?")==-1)return url+"?"+param;return url+"&"+param}function createElementWithClassName(type,className){var elm=document.createElement(type);elm.className=className;return elm}function ensureTransitionEndEvent(el,opt_timeOut){if(opt_timeOut===undefined){var style=getComputedStyle(el);opt_timeOut=parseFloat(style.transitionDuration)*1e3;opt_timeOut+=50}var fired=false;el.addEventListener("webkitTransitionEnd",function f(e){el.removeEventListener("webkitTransitionEnd",f);fired=true});window.setTimeout(function(){if(!fired)cr.dispatchSimpleEvent(el,"webkitTransitionEnd",true)},opt_timeOut)}function scrollTopForDocument(doc){return doc.documentElement.scrollTop||doc.body.scrollTop}function setScrollTopForDocument(doc,value){doc.documentElement.scrollTop=doc.body.scrollTop=value}function scrollLeftForDocument(doc){return doc.documentElement.scrollLeft||doc.body.scrollLeft}function setScrollLeftForDocument(doc,value){doc.documentElement.scrollLeft=doc.body.scrollLeft=value}function HTMLEscape(original){return original.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function elide(original,maxLength){if(original.length<=maxLength)return original;return original.substring(0,maxLength-1)+"…"}function quoteString(str){return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g,"\\$1")}function listenOnce(target,eventNames,callback){if(!Array.isArray(eventNames))eventNames=eventNames.split(/ +/);var removeAllAndCallCallback=function(event){eventNames.forEach(function(eventName){target.removeEventListener(eventName,removeAllAndCallCallback,false)});return callback(event)};eventNames.forEach(function(eventName){target.addEventListener(eventName,removeAllAndCallCallback,false)})}
-// <if expr="is_ios">
-if(!("key"in KeyboardEvent.prototype)){Object.defineProperty(KeyboardEvent.prototype,"key",{get:function(){if(this.keyCode>=48&&this.keyCode<=57)return String.fromCharCode(this.keyCode);if(this.keyCode>=65&&this.keyCode<=90){var result=String.fromCharCode(this.keyCode).toLowerCase();if(this.shiftKey)result=result.toUpperCase();return result}switch(this.keyCode){case 8:return"Backspace";case 9:return"Tab";case 13:return"Enter";case 16:return"Shift";case 17:return"Control";case 18:return"Alt";case 27:return"Escape";case 32:return" ";case 33:return"PageUp";case 34:return"PageDown";case 35:return"End";case 36:return"Home";case 37:return"ArrowLeft";case 38:return"ArrowUp";case 39:return"ArrowRight";case 40:return"ArrowDown";case 45:return"Insert";case 46:return"Delete";case 91:return"Meta";case 112:return"F1";case 113:return"F2";case 114:return"F3";case 115:return"F4";case 116:return"F5";case 117:return"F6";case 118:return"F7";case 119:return"F8";case 120:return"F9";case 121:return"F10";case 122:return"F11";case 123:return"F12";case 187:return"=";case 189:return"-";case 219:return"[";case 221:return"]"}return"Unidentified"}})}else{window.console.log("KeyboardEvent.Key polyfill not required")}
-// </if>  /* is_ios */
-function importModules(moduleNames){return new Promise(function(resolve){define(moduleNames,function(){resolve(Array.from(arguments))})})}function hasKeyModifiers(e){return!!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)}Polymer.IronResizableBehavior={properties:{_parentResizable:{type:Object,observer:"_parentResizableChanged"},_notifyingDescendant:{type:Boolean,value:false}},listeners:{"iron-request-resize-notifications":"_onIronRequestResizeNotifications"},created:function(){this._interestedResizables=[];this._boundNotifyResize=this.notifyResize.bind(this)},attached:function(){this.fire("iron-request-resize-notifications",null,{node:this,bubbles:true,cancelable:true});if(!this._parentResizable){window.addEventListener("resize",this._boundNotifyResize);this.notifyResize()}},detached:function(){if(this._parentResizable){this._parentResizable.stopResizeNotificationsFor(this)}else{window.removeEventListener("resize",this._boundNotifyResize)}this._parentResizable=null},notifyResize:function(){if(!this.isAttached){return}this._interestedResizables.forEach(function(resizable){if(this.resizerShouldNotify(resizable)){this._notifyDescendant(resizable)}},this);this._fireResize()},assignParentResizable:function(parentResizable){this._parentResizable=parentResizable},stopResizeNotificationsFor:function(target){var index=this._interestedResizables.indexOf(target);if(index>-1){this._interestedResizables.splice(index,1);this.unlisten(target,"iron-resize","_onDescendantIronResize")}},resizerShouldNotify:function(element){return true},_onDescendantIronResize:function(event){if(this._notifyingDescendant){event.stopPropagation();return}if(!Polymer.Settings.useShadow){this._fireResize()}},_fireResize:function(){this.fire("iron-resize",null,{node:this,bubbles:false})},_onIronRequestResizeNotifications:function(event){var target=event.path?event.path[0]:event.target;if(target===this){return}if(this._interestedResizables.indexOf(target)===-1){this._interestedResizables.push(target);this.listen(target,"iron-resize","_onDescendantIronResize")}target.assignParentResizable(this);this._notifyDescendant(target);event.stopPropagation()},_parentResizableChanged:function(parentResizable){if(parentResizable){window.removeEventListener("resize",this._boundNotifyResize)}},_notifyDescendant:function(descendant){if(!this.isAttached){return}this._notifyingDescendant=true;descendant.notifyResize();this._notifyingDescendant=false}};(function(){"use strict";var KEY_IDENTIFIER={"U+0008":"backspace","U+0009":"tab","U+001B":"esc","U+0020":"space","U+007F":"del"};var KEY_CODE={8:"backspace",9:"tab",13:"enter",27:"esc",33:"pageup",34:"pagedown",35:"end",36:"home",32:"space",37:"left",38:"up",39:"right",40:"down",46:"del",106:"*"};var MODIFIER_KEYS={shift:"shiftKey",ctrl:"ctrlKey",alt:"altKey",meta:"metaKey"};var KEY_CHAR=/[a-z0-9*]/;var IDENT_CHAR=/U\+/;var ARROW_KEY=/^arrow/;var SPACE_KEY=/^space(bar)?/;var ESC_KEY=/^escape$/;function transformKey(key,noSpecialChars){var validKey="";if(key){var lKey=key.toLowerCase();if(lKey===" "||SPACE_KEY.test(lKey)){validKey="space"}else if(ESC_KEY.test(lKey)){validKey="esc"}else if(lKey.length==1){if(!noSpecialChars||KEY_CHAR.test(lKey)){validKey=lKey}}else if(ARROW_KEY.test(lKey)){validKey=lKey.replace("arrow","")}else if(lKey=="multiply"){validKey="*"}else{validKey=lKey}}return validKey}function transformKeyIdentifier(keyIdent){var validKey="";if(keyIdent){if(keyIdent in KEY_IDENTIFIER){validKey=KEY_IDENTIFIER[keyIdent]}else if(IDENT_CHAR.test(keyIdent)){keyIdent=parseInt(keyIdent.replace("U+","0x"),16);validKey=String.fromCharCode(keyIdent).toLowerCase()}else{validKey=keyIdent.toLowerCase()}}return validKey}function transformKeyCode(keyCode){var validKey="";if(Number(keyCode)){if(keyCode>=65&&keyCode<=90){validKey=String.fromCharCode(32+keyCode)}else if(keyCode>=112&&keyCode<=123){validKey="f"+(keyCode-112)}else if(keyCode>=48&&keyCode<=57){validKey=String(keyCode-48)}else if(keyCode>=96&&keyCode<=105){validKey=String(keyCode-96)}else{validKey=KEY_CODE[keyCode]}}return validKey}function normalizedKeyForEvent(keyEvent,noSpecialChars){if(keyEvent.key){return transformKey(keyEvent.key,noSpecialChars)}if(keyEvent.detail&&keyEvent.detail.key){return transformKey(keyEvent.detail.key,noSpecialChars)}return transformKeyIdentifier(keyEvent.keyIdentifier)||transformKeyCode(keyEvent.keyCode)||""}function keyComboMatchesEvent(keyCombo,event){var keyEvent=normalizedKeyForEvent(event,keyCombo.hasModifiers);return keyEvent===keyCombo.key&&(!keyCombo.hasModifiers||!!event.shiftKey===!!keyCombo.shiftKey&&!!event.ctrlKey===!!keyCombo.ctrlKey&&!!event.altKey===!!keyCombo.altKey&&!!event.metaKey===!!keyCombo.metaKey)}function parseKeyComboString(keyComboString){if(keyComboString.length===1){return{combo:keyComboString,key:keyComboString,event:"keydown"}}return keyComboString.split("+").reduce(function(parsedKeyCombo,keyComboPart){var eventParts=keyComboPart.split(":");var keyName=eventParts[0];var event=eventParts[1];if(keyName in MODIFIER_KEYS){parsedKeyCombo[MODIFIER_KEYS[keyName]]=true;parsedKeyCombo.hasModifiers=true}else{parsedKeyCombo.key=keyName;parsedKeyCombo.event=event||"keydown"}return parsedKeyCombo},{combo:keyComboString.split(":").shift()})}function parseEventString(eventString){return eventString.trim().split(" ").map(function(keyComboString){return parseKeyComboString(keyComboString)})}Polymer.IronA11yKeysBehavior={properties:{keyEventTarget:{type:Object,value:function(){return this}},stopKeyboardEventPropagation:{type:Boolean,value:false},_boundKeyHandlers:{type:Array,value:function(){return[]}},_imperativeKeyBindings:{type:Object,value:function(){return{}}}},observers:["_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)"],keyBindings:{},registered:function(){this._prepKeyBindings()},attached:function(){this._listenKeyEventListeners()},detached:function(){this._unlistenKeyEventListeners()},addOwnKeyBinding:function(eventString,handlerName){this._imperativeKeyBindings[eventString]=handlerName;this._prepKeyBindings();this._resetKeyEventListeners()},removeOwnKeyBindings:function(){this._imperativeKeyBindings={};this._prepKeyBindings();this._resetKeyEventListeners()},keyboardEventMatchesKeys:function(event,eventString){var keyCombos=parseEventString(eventString);for(var i=0;i<keyCombos.length;++i){if(keyComboMatchesEvent(keyCombos[i],event)){return true}}return false},_collectKeyBindings:function(){var keyBindings=this.behaviors.map(function(behavior){return behavior.keyBindings});if(keyBindings.indexOf(this.keyBindings)===-1){keyBindings.push(this.keyBindings)}return keyBindings},_prepKeyBindings:function(){this._keyBindings={};this._collectKeyBindings().forEach(function(keyBindings){for(var eventString in keyBindings){this._addKeyBinding(eventString,keyBindings[eventString])}},this);for(var eventString in this._imperativeKeyBindings){this._addKeyBinding(eventString,this._imperativeKeyBindings[eventString])}for(var eventName in this._keyBindings){this._keyBindings[eventName].sort(function(kb1,kb2){var b1=kb1[0].hasModifiers;var b2=kb2[0].hasModifiers;return b1===b2?0:b1?-1:1})}},_addKeyBinding:function(eventString,handlerName){parseEventString(eventString).forEach(function(keyCombo){this._keyBindings[keyCombo.event]=this._keyBindings[keyCombo.event]||[];this._keyBindings[keyCombo.event].push([keyCombo,handlerName])},this)},_resetKeyEventListeners:function(){this._unlistenKeyEventListeners();if(this.isAttached){this._listenKeyEventListeners()}},_listenKeyEventListeners:function(){if(!this.keyEventTarget){return}Object.keys(this._keyBindings).forEach(function(eventName){var keyBindings=this._keyBindings[eventName];var boundKeyHandler=this._onKeyBindingEvent.bind(this,keyBindings);this._boundKeyHandlers.push([this.keyEventTarget,eventName,boundKeyHandler]);this.keyEventTarget.addEventListener(eventName,boundKeyHandler)},this)},_unlistenKeyEventListeners:function(){var keyHandlerTuple;var keyEventTarget;var eventName;var boundKeyHandler;while(this._boundKeyHandlers.length){keyHandlerTuple=this._boundKeyHandlers.pop();keyEventTarget=keyHandlerTuple[0];eventName=keyHandlerTuple[1];boundKeyHandler=keyHandlerTuple[2];keyEventTarget.removeEventListener(eventName,boundKeyHandler)}},_onKeyBindingEvent:function(keyBindings,event){if(this.stopKeyboardEventPropagation){event.stopPropagation()}if(event.defaultPrevented){return}for(var i=0;i<keyBindings.length;i++){var keyCombo=keyBindings[i][0];var handlerName=keyBindings[i][1];if(keyComboMatchesEvent(keyCombo,event)){this._triggerKeyHandler(keyCombo,handlerName,event);if(event.defaultPrevented){return}}}},_triggerKeyHandler:function(keyCombo,handlerName,keyboardEvent){var detail=Object.create(keyCombo);detail.keyboardEvent=keyboardEvent;var event=new CustomEvent(keyCombo.event,{detail:detail,cancelable:true});this[handlerName].call(this,event);if(event.defaultPrevented){keyboardEvent.preventDefault()}}}})();Polymer.IronScrollTargetBehavior={properties:{scrollTarget:{type:HTMLElement,value:function(){return this._defaultScrollTarget}}},observers:["_scrollTargetChanged(scrollTarget, isAttached)"],_shouldHaveListener:true,_scrollTargetChanged:function(scrollTarget,isAttached){var eventTarget;if(this._oldScrollTarget){this._toggleScrollListener(false,this._oldScrollTarget);this._oldScrollTarget=null}if(!isAttached){return}if(scrollTarget==="document"){this.scrollTarget=this._doc}else if(typeof scrollTarget==="string"){this.scrollTarget=this.domHost?this.domHost.$[scrollTarget]:Polymer.dom(this.ownerDocument).querySelector("#"+scrollTarget)}else if(this._isValidScrollTarget()){this._boundScrollHandler=this._boundScrollHandler||this._scrollHandler.bind(this);this._oldScrollTarget=scrollTarget;this._toggleScrollListener(this._shouldHaveListener,scrollTarget)}},_scrollHandler:function scrollHandler(){},get _defaultScrollTarget(){return this._doc},get _doc(){return this.ownerDocument.documentElement},get _scrollTop(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.pageYOffset:this.scrollTarget.scrollTop}return 0},get _scrollLeft(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.pageXOffset:this.scrollTarget.scrollLeft}return 0},set _scrollTop(top){if(this.scrollTarget===this._doc){window.scrollTo(window.pageXOffset,top)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollTop=top}},set _scrollLeft(left){if(this.scrollTarget===this._doc){window.scrollTo(left,window.pageYOffset)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollLeft=left}},scroll:function(left,top){if(this.scrollTarget===this._doc){window.scrollTo(left,top)}else if(this._isValidScrollTarget()){this.scrollTarget.scrollLeft=left;this.scrollTarget.scrollTop=top}},get _scrollTargetWidth(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.innerWidth:this.scrollTarget.offsetWidth}return 0},get _scrollTargetHeight(){if(this._isValidScrollTarget()){return this.scrollTarget===this._doc?window.innerHeight:this.scrollTarget.offsetHeight}return 0},_isValidScrollTarget:function(){return this.scrollTarget instanceof HTMLElement},_toggleScrollListener:function(yes,scrollTarget){if(!this._boundScrollHandler){return}var eventTarget=scrollTarget===this._doc?window:scrollTarget;if(yes){eventTarget.addEventListener("scroll",this._boundScrollHandler)}else{eventTarget.removeEventListener("scroll",this._boundScrollHandler)}},toggleScrollListener:function(yes){this._shouldHaveListener=yes;this._toggleScrollListener(yes,this.scrollTarget)}};(function(){var IOS=navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/);var IOS_TOUCH_SCROLLING=IOS&&IOS[1]>=8;var DEFAULT_PHYSICAL_COUNT=3;var HIDDEN_Y="-10000px";var ITEM_WIDTH=0;var ITEM_HEIGHT=1;var SECRET_TABINDEX=-100;Polymer({is:"iron-list",properties:{items:{type:Array},maxPhysicalCount:{type:Number,value:500},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},selectedAs:{type:String,value:"selected"},grid:{type:Boolean,value:false,reflectToAttribute:true},selectionEnabled:{type:Boolean,value:false},selectedItem:{type:Object,notify:true},selectedItems:{type:Object,notify:true},multiSelection:{type:Boolean,value:false}},observers:["_itemsChanged(items.*)","_selectionEnabledChanged(selectionEnabled)","_multiSelectionChanged(multiSelection)","_setOverflow(scrollTarget)"],behaviors:[Polymer.Templatizer,Polymer.IronResizableBehavior,Polymer.IronA11yKeysBehavior,Polymer.IronScrollTargetBehavior],keyBindings:{up:"_didMoveUp",down:"_didMoveDown",enter:"_didEnter"},_ratio:.5,_scrollerPaddingTop:0,_scrollPosition:0,_physicalSize:0,_physicalAverage:0,_physicalAverageCount:0,_physicalTop:0,_virtualCount:0,_physicalIndexForKey:null,_estScrollHeight:0,_scrollHeight:0,_viewportHeight:0,_viewportWidth:0,_physicalItems:null,_physicalSizes:null,_firstVisibleIndexVal:null,_lastVisibleIndexVal:null,_collection:null,_maxPages:2,_focusedItem:null,_focusedIndex:-1,_offscreenFocusedItem:null,_focusBackfillItem:null,_itemsPerRow:1,_itemWidth:0,_rowHeight:0,_templateCost:0,get _physicalBottom(){return this._physicalTop+this._physicalSize},get _scrollBottom(){return this._scrollPosition+this._viewportHeight},get _virtualEnd(){return this._virtualStart+this._physicalCount-1},get _hiddenContentSize(){var size=this.grid?this._physicalRows*this._rowHeight:this._physicalSize;return size-this._viewportHeight},get _maxScrollTop(){return this._estScrollHeight-this._viewportHeight+this._scrollerPaddingTop},_minVirtualStart:0,get _maxVirtualStart(){return Math.max(0,this._virtualCount-this._physicalCount)},_virtualStartVal:0,set _virtualStart(val){this._virtualStartVal=Math.min(this._maxVirtualStart,Math.max(this._minVirtualStart,val))},get _virtualStart(){return this._virtualStartVal||0},_physicalStartVal:0,set _physicalStart(val){this._physicalStartVal=val%this._physicalCount;if(this._physicalStartVal<0){this._physicalStartVal=this._physicalCount+this._physicalStartVal}this._physicalEnd=(this._physicalStart+this._physicalCount-1)%this._physicalCount},get _physicalStart(){return this._physicalStartVal||0},_physicalCountVal:0,set _physicalCount(val){this._physicalCountVal=val;this._physicalEnd=(this._physicalStart+this._physicalCount-1)%this._physicalCount},get _physicalCount(){return this._physicalCountVal},_physicalEnd:0,get _optPhysicalSize(){if(this.grid){return this._estRowsInView*this._rowHeight*this._maxPages}return this._viewportHeight*this._maxPages},get _isVisible(){return Boolean(this.offsetWidth||this.offsetHeight)},get firstVisibleIndex(){if(this._firstVisibleIndexVal===null){var physicalOffset=Math.floor(this._physicalTop+this._scrollerPaddingTop);this._firstVisibleIndexVal=this._iterateItems(function(pidx,vidx){physicalOffset+=this._getPhysicalSizeIncrement(pidx);if(physicalOffset>this._scrollPosition){return this.grid?vidx-vidx%this._itemsPerRow:vidx}if(this.grid&&this._virtualCount-1===vidx){return vidx-vidx%this._itemsPerRow}})||0}return this._firstVisibleIndexVal},get lastVisibleIndex(){if(this._lastVisibleIndexVal===null){if(this.grid){var lastIndex=this.firstVisibleIndex+this._estRowsInView*this._itemsPerRow-1;this._lastVisibleIndexVal=Math.min(this._virtualCount,lastIndex)}else{var physicalOffset=this._physicalTop;this._iterateItems(function(pidx,vidx){if(physicalOffset<this._scrollBottom){this._lastVisibleIndexVal=vidx}else{return true}physicalOffset+=this._getPhysicalSizeIncrement(pidx)})}}return this._lastVisibleIndexVal},get _defaultScrollTarget(){return this},get _virtualRowCount(){return Math.ceil(this._virtualCount/this._itemsPerRow)},get _estRowsInView(){return Math.ceil(this._viewportHeight/this._rowHeight)},get _physicalRows(){return Math.ceil(this._physicalCount/this._itemsPerRow)},ready:function(){this.addEventListener("focus",this._didFocus.bind(this),true)},attached:function(){if(this._physicalCount===0){this._debounceTemplate(this._render)}this.listen(this,"iron-resize","_resizeHandler")},detached:function(){this.unlisten(this,"iron-resize","_resizeHandler")},_setOverflow:function(scrollTarget){this.style.webkitOverflowScrolling=scrollTarget===this?"touch":"";this.style.overflow=scrollTarget===this?"auto":""},updateViewportBoundaries:function(){this._scrollerPaddingTop=this.scrollTarget===this?0:parseInt(window.getComputedStyle(this)["padding-top"],10);this._viewportWidth=this.$.items.offsetWidth;this._viewportHeight=this._scrollTargetHeight;this.grid&&this._updateGridMetrics()},_scrollHandler:function(){var scrollTop=Math.max(0,Math.min(this._maxScrollTop,this._scrollTop));var delta=scrollTop-this._scrollPosition;var isScrollingDown=delta>=0;this._scrollPosition=scrollTop;this._firstVisibleIndexVal=null;this._lastVisibleIndexVal=null;if(Math.abs(delta)>this._physicalSize){var idxAdjustment=Math.round(delta/this._physicalAverage)*this._itemsPerRow;this._physicalTop=this._physicalTop+delta;this._virtualStart=this._virtualStart+idxAdjustment;this._physicalStart=this._physicalStart+idxAdjustment;this._update()}else{var reusables=this._getReusables(isScrollingDown);if(isScrollingDown){this._physicalTop=reusables.physicalTop;this._virtualStart=this._virtualStart+reusables.indexes.length;this._physicalStart=this._physicalStart+reusables.indexes.length}else{this._virtualStart=this._virtualStart-reusables.indexes.length;this._physicalStart=this._physicalStart-reusables.indexes.length}if(reusables.indexes.length===0){this._increasePoolIfNeeded()}else{this._update(reusables.indexes,isScrollingDown?null:reusables.indexes)}}},_getReusables:function(fromTop){var ith,lastIth,offsetContent,physicalItemHeight;var idxs=[];var protectedOffsetContent=this._hiddenContentSize*this._ratio;var virtualStart=this._virtualStart;var virtualEnd=this._virtualEnd;var physicalCount=this._physicalCount;var physicalTop=this._physicalTop+this._scrollerPaddingTop;var scrollTop=this._scrollTop;var scrollBottom=this._scrollBottom;if(fromTop){ith=this._physicalStart;lastIth=this._physicalEnd;offsetContent=scrollTop-physicalTop}else{ith=this._physicalEnd;lastIth=this._physicalStart;offsetContent=this._physicalBottom-scrollBottom}while(true){physicalItemHeight=this._getPhysicalSizeIncrement(ith);offsetContent=offsetContent-physicalItemHeight;if(idxs.length>=physicalCount||offsetContent<=protectedOffsetContent){break}if(fromTop){if(virtualEnd+idxs.length+1>=this._virtualCount){break}if(physicalTop+physicalItemHeight>=scrollTop){break}idxs.push(ith);physicalTop=physicalTop+physicalItemHeight;ith=(ith+1)%physicalCount}else{if(virtualStart-idxs.length<=0){break}if(physicalTop+this._physicalSize-physicalItemHeight<=scrollBottom){break}idxs.push(ith);physicalTop=physicalTop-physicalItemHeight;ith=ith===0?physicalCount-1:ith-1}}return{indexes:idxs,physicalTop:physicalTop-this._scrollerPaddingTop}},_update:function(itemSet,movingUp){if(itemSet&&itemSet.length===0){return}this._manageFocus();this._assignModels(itemSet);this._updateMetrics(itemSet);if(movingUp){while(movingUp.length){var idx=movingUp.pop();this._physicalTop-=this._getPhysicalSizeIncrement(idx)}}this._positionItems();this._updateScrollerSize();this._increasePoolIfNeeded()},_createPool:function(size){var physicalItems=new Array(size);this._ensureTemplatized();for(var i=0;i<size;i++){var inst=this.stamp(null);physicalItems[i]=inst.root.querySelector("*");Polymer.dom(this).appendChild(inst.root)}return physicalItems},_increasePoolIfNeeded:function(){if(this._viewportHeight===0){return false}var self=this;var isClientFull=this._physicalBottom>=this._scrollBottom&&this._physicalTop<=this._scrollPosition;if(this._physicalSize>=this._optPhysicalSize&&isClientFull){return false}var maxPoolSize=Math.round(this._physicalCount*.5);if(!isClientFull){this._debounceTemplate(this._increasePool.bind(this,maxPoolSize));return true}this._yield(function(){self._increasePool(Math.min(maxPoolSize,Math.max(1,Math.round(50/self._templateCost))))});return true},_yield:function(cb){var g=window;var handle=g.requestIdleCallback?g.requestIdleCallback(cb):g.setTimeout(cb,16);Polymer.dom.addDebouncer({complete:function(){g.cancelIdleCallback?g.cancelIdleCallback(handle):g.clearTimeout(handle);cb()}})},_increasePool:function(missingItems){var nextPhysicalCount=Math.min(this._physicalCount+missingItems,this._virtualCount-this._virtualStart,Math.max(this.maxPhysicalCount,DEFAULT_PHYSICAL_COUNT));var prevPhysicalCount=this._physicalCount;var delta=nextPhysicalCount-prevPhysicalCount;var ts=window.performance.now();if(delta<=0){return}[].push.apply(this._physicalItems,this._createPool(delta));[].push.apply(this._physicalSizes,new Array(delta));this._physicalCount=prevPhysicalCount+delta;if(this._physicalStart>this._physicalEnd&&this._isIndexRendered(this._focusedIndex)&&this._getPhysicalIndex(this._focusedIndex)<this._physicalEnd){this._physicalStart=this._physicalStart+delta}this._update();this._templateCost=(window.performance.now()-ts)/delta},_render:function(){if(this.isAttached&&this._isVisible){if(this._physicalCount===0){this.updateViewportBoundaries();this._increasePool(DEFAULT_PHYSICAL_COUNT)}else{var reusables=this._getReusables(true);this._physicalTop=reusables.physicalTop;this._virtualStart=this._virtualStart+reusables.indexes.length;this._physicalStart=this._physicalStart+reusables.indexes.length;this._update(reusables.indexes);this._update()}}},_ensureTemplatized:function(){if(!this.ctor){var props={};props.__key__=true;props[this.as]=true;props[this.indexAs]=true;props[this.selectedAs]=true;props.tabIndex=true;this._instanceProps=props;this._userTemplate=Polymer.dom(this).querySelector("template");if(this._userTemplate){this.templatize(this._userTemplate)}else{console.warn("iron-list requires a template to be provided in light-dom")}}},_getStampedChildren:function(){return this._physicalItems},_forwardInstancePath:function(inst,path,value){if(path.indexOf(this.as+".")===0){this.notifyPath("items."+inst.__key__+"."+path.slice(this.as.length+1),value)}},_forwardParentProp:function(prop,value){if(this._physicalItems){this._physicalItems.forEach(function(item){item._templateInstance[prop]=value},this)}},_forwardParentPath:function(path,value){if(this._physicalItems){this._physicalItems.forEach(function(item){item._templateInstance.notifyPath(path,value,true)},this)}},_forwardItemPath:function(path,value){if(!this._physicalIndexForKey){return}var dot=path.indexOf(".");var key=path.substring(0,dot<0?path.length:dot);var idx=this._physicalIndexForKey[key];var offscreenItem=this._offscreenFocusedItem;var el=offscreenItem&&offscreenItem._templateInstance.__key__===key?offscreenItem:this._physicalItems[idx];if(!el||el._templateInstance.__key__!==key){return}if(dot>=0){path=this.as+"."+path.substring(dot+1);el._templateInstance.notifyPath(path,value,true)}else{var currentItem=el._templateInstance[this.as];if(Array.isArray(this.selectedItems)){for(var i=0;i<this.selectedItems.length;i++){if(this.selectedItems[i]===currentItem){this.set("selectedItems."+i,value);break}}}else if(this.selectedItem===currentItem){this.set("selectedItem",value)}el._templateInstance[this.as]=value}},_itemsChanged:function(change){if(change.path==="items"){this._virtualStart=0;this._physicalTop=0;this._virtualCount=this.items?this.items.length:0;this._collection=this.items?Polymer.Collection.get(this.items):null;this._physicalIndexForKey={};this._firstVisibleIndexVal=null;this._lastVisibleIndexVal=null;this._physicalCount=this._physicalCount||0;this._physicalItems=this._physicalItems||[];this._physicalSizes=this._physicalSizes||[];this._physicalStart=0;this._resetScrollPosition(0);this._removeFocusedItem();this._debounceTemplate(this._render)}else if(change.path==="items.splices"){this._adjustVirtualIndex(change.value.indexSplices);this._virtualCount=this.items?this.items.length:0;this._debounceTemplate(this._render)}else{this._forwardItemPath(change.path.split(".").slice(1).join("."),change.value)}},_adjustVirtualIndex:function(splices){splices.forEach(function(splice){splice.removed.forEach(this._removeItem,this);if(splice.index<this._virtualStart){var delta=Math.max(splice.addedCount-splice.removed.length,splice.index-this._virtualStart);this._virtualStart=this._virtualStart+delta;if(this._focusedIndex>=0){this._focusedIndex=this._focusedIndex+delta}}},this)},_removeItem:function(item){this.$.selector.deselect(item);if(this._focusedItem&&this._focusedItem._templateInstance[this.as]===item){this._removeFocusedItem()}},_iterateItems:function(fn,itemSet){var pidx,vidx,rtn,i;if(arguments.length===2&&itemSet){for(i=0;i<itemSet.length;i++){pidx=itemSet[i];vidx=this._computeVidx(pidx);if((rtn=fn.call(this,pidx,vidx))!=null){return rtn}}}else{pidx=this._physicalStart;vidx=this._virtualStart;for(;pidx<this._physicalCount;pidx++,vidx++){if((rtn=fn.call(this,pidx,vidx))!=null){return rtn}}for(pidx=0;pidx<this._physicalStart;pidx++,vidx++){if((rtn=fn.call(this,pidx,vidx))!=null){return rtn}}}},_computeVidx:function(pidx){if(pidx>=this._physicalStart){return this._virtualStart+(pidx-this._physicalStart)}return this._virtualStart+(this._physicalCount-this._physicalStart)+pidx},_assignModels:function(itemSet){this._iterateItems(function(pidx,vidx){var el=this._physicalItems[pidx];var inst=el._templateInstance;var item=this.items&&this.items[vidx];if(item!=null){inst[this.as]=item;inst.__key__=this._collection.getKey(item);inst[this.selectedAs]=this.$.selector.isSelected(item);inst[this.indexAs]=vidx;inst.tabIndex=this._focusedIndex===vidx?0:-1;this._physicalIndexForKey[inst.__key__]=pidx;el.removeAttribute("hidden")}else{inst.__key__=null;el.setAttribute("hidden","")}},itemSet)},_updateMetrics:function(itemSet){Polymer.dom.flush();var newPhysicalSize=0;var oldPhysicalSize=0;var prevAvgCount=this._physicalAverageCount;var prevPhysicalAvg=this._physicalAverage;this._iterateItems(function(pidx,vidx){oldPhysicalSize+=this._physicalSizes[pidx]||0;this._physicalSizes[pidx]=this._physicalItems[pidx].offsetHeight;newPhysicalSize+=this._physicalSizes[pidx];this._physicalAverageCount+=this._physicalSizes[pidx]?1:0},itemSet);if(this.grid){this._updateGridMetrics();this._physicalSize=Math.ceil(this._physicalCount/this._itemsPerRow)*this._rowHeight}else{this._physicalSize=this._physicalSize+newPhysicalSize-oldPhysicalSize}if(this._physicalAverageCount!==prevAvgCount){this._physicalAverage=Math.round((prevPhysicalAvg*prevAvgCount+newPhysicalSize)/this._physicalAverageCount)}},_updateGridMetrics:function(){this._itemWidth=this._physicalCount>0?this._physicalItems[0].getBoundingClientRect().width:200;this._rowHeight=this._physicalCount>0?this._physicalItems[0].offsetHeight:200;this._itemsPerRow=this._itemWidth?Math.floor(this._viewportWidth/this._itemWidth):this._itemsPerRow},_positionItems:function(){this._adjustScrollPosition();var y=this._physicalTop;if(this.grid){var totalItemWidth=this._itemsPerRow*this._itemWidth;var rowOffset=(this._viewportWidth-totalItemWidth)/2;this._iterateItems(function(pidx,vidx){var modulus=vidx%this._itemsPerRow;var x=Math.floor(modulus*this._itemWidth+rowOffset);this.translate3d(x+"px",y+"px",0,this._physicalItems[pidx]);if(this._shouldRenderNextRow(vidx)){y+=this._rowHeight}})}else{this._iterateItems(function(pidx,vidx){this.translate3d(0,y+"px",0,this._physicalItems[pidx]);y+=this._physicalSizes[pidx]})}},_getPhysicalSizeIncrement:function(pidx){if(!this.grid){return this._physicalSizes[pidx]}if(this._computeVidx(pidx)%this._itemsPerRow!==this._itemsPerRow-1){return 0}return this._rowHeight},_shouldRenderNextRow:function(vidx){return vidx%this._itemsPerRow===this._itemsPerRow-1},_adjustScrollPosition:function(){var deltaHeight=this._virtualStart===0?this._physicalTop:Math.min(this._scrollPosition+this._physicalTop,0);if(deltaHeight){this._physicalTop=this._physicalTop-deltaHeight;if(!IOS_TOUCH_SCROLLING&&this._physicalTop!==0){this._resetScrollPosition(this._scrollTop-deltaHeight)}}},_resetScrollPosition:function(pos){if(this.scrollTarget){this._scrollTop=pos;this._scrollPosition=this._scrollTop}},_updateScrollerSize:function(forceUpdate){if(this.grid){this._estScrollHeight=this._virtualRowCount*this._rowHeight}else{this._estScrollHeight=this._physicalBottom+Math.max(this._virtualCount-this._physicalCount-this._virtualStart,0)*this._physicalAverage}forceUpdate=forceUpdate||this._scrollHeight===0;forceUpdate=forceUpdate||this._scrollPosition>=this._estScrollHeight-this._physicalSize;forceUpdate=forceUpdate||this.grid&&this.$.items.style.height<this._estScrollHeight;if(forceUpdate||Math.abs(this._estScrollHeight-this._scrollHeight)>=this._optPhysicalSize){this.$.items.style.height=this._estScrollHeight+"px";this._scrollHeight=this._estScrollHeight}},scrollToItem:function(item){return this.scrollToIndex(this.items.indexOf(item))},scrollToIndex:function(idx){if(typeof idx!=="number"||idx<0||idx>this.items.length-1){return}Polymer.dom.flush();if(this._physicalCount===0){return}idx=Math.min(Math.max(idx,0),this._virtualCount-1);if(!this._isIndexRendered(idx)||idx>=this._maxVirtualStart){this._virtualStart=this.grid?idx-this._itemsPerRow*2:idx-1}this._manageFocus();this._assignModels();this._updateMetrics();this._physicalTop=Math.floor(this._virtualStart/this._itemsPerRow)*this._physicalAverage;var currentTopItem=this._physicalStart;var currentVirtualItem=this._virtualStart;var targetOffsetTop=0;var hiddenContentSize=this._hiddenContentSize;while(currentVirtualItem<idx&&targetOffsetTop<=hiddenContentSize){targetOffsetTop=targetOffsetTop+this._getPhysicalSizeIncrement(currentTopItem);currentTopItem=(currentTopItem+1)%this._physicalCount;currentVirtualItem++}this._updateScrollerSize(true);this._positionItems();this._resetScrollPosition(this._physicalTop+this._scrollerPaddingTop+targetOffsetTop);this._increasePoolIfNeeded();this._firstVisibleIndexVal=null;this._lastVisibleIndexVal=null},_resetAverage:function(){this._physicalAverage=0;this._physicalAverageCount=0},_resizeHandler:function(){var delta=Math.abs(this._viewportHeight-this._scrollTargetHeight);if(IOS&&delta>0&&delta<100){return}Polymer.dom.addDebouncer(this.debounce("_debounceTemplate",function(){this.updateViewportBoundaries();this._render();if(this._isVisible){this.toggleScrollListener(true);if(this._physicalCount>0){this._resetAverage();this.scrollToIndex(this.firstVisibleIndex)}}else{this.toggleScrollListener(false)}}.bind(this),1))},_getModelFromItem:function(item){var key=this._collection.getKey(item);var pidx=this._physicalIndexForKey[key];if(pidx!=null){return this._physicalItems[pidx]._templateInstance}return null},_getNormalizedItem:function(item){if(this._collection.getKey(item)===undefined){if(typeof item==="number"){item=this.items[item];if(!item){throw new RangeError("<item> not found")}return item}throw new TypeError("<item> should be a valid item")}return item},selectItem:function(item){item=this._getNormalizedItem(item);var model=this._getModelFromItem(item);if(!this.multiSelection&&this.selectedItem){this.deselectItem(this.selectedItem)}if(model){model[this.selectedAs]=true}this.$.selector.select(item);this.updateSizeForItem(item)},deselectItem:function(item){item=this._getNormalizedItem(item);var model=this._getModelFromItem(item);if(model){model[this.selectedAs]=false}this.$.selector.deselect(item);this.updateSizeForItem(item)},toggleSelectionForItem:function(item){item=this._getNormalizedItem(item);if(this.$.selector.isSelected(item)){this.deselectItem(item)}else{this.selectItem(item)}},clearSelection:function(){function unselect(item){var model=this._getModelFromItem(item);if(model){model[this.selectedAs]=false}}if(Array.isArray(this.selectedItems)){this.selectedItems.forEach(unselect,this)}else if(this.selectedItem){unselect.call(this,this.selectedItem)}this.$.selector.clearSelection()},_selectionEnabledChanged:function(selectionEnabled){var handler=selectionEnabled?this.listen:this.unlisten;handler.call(this,this,"tap","_selectionHandler")},_selectionHandler:function(e){var model=this.modelForElement(e.target);if(!model){return}var modelTabIndex,activeElTabIndex;var target=Polymer.dom(e).path[0];var activeEl=Polymer.dom(this.domHost?this.domHost.root:document).activeElement;
-
-var physicalItem=this._physicalItems[this._getPhysicalIndex(model[this.indexAs])];if(target.localName==="input"||target.localName==="button"||target.localName==="select"){return}modelTabIndex=model.tabIndex;model.tabIndex=SECRET_TABINDEX;activeElTabIndex=activeEl?activeEl.tabIndex:-1;model.tabIndex=modelTabIndex;if(activeEl&&physicalItem!==activeEl&&physicalItem.contains(activeEl)&&activeElTabIndex!==SECRET_TABINDEX){return}this.toggleSelectionForItem(model[this.as])},_multiSelectionChanged:function(multiSelection){this.clearSelection();this.$.selector.multi=multiSelection},updateSizeForItem:function(item){item=this._getNormalizedItem(item);var key=this._collection.getKey(item);var pidx=this._physicalIndexForKey[key];if(pidx!=null){this._updateMetrics([pidx]);this._positionItems()}},_manageFocus:function(){var fidx=this._focusedIndex;if(fidx>=0&&fidx<this._virtualCount){if(this._isIndexRendered(fidx)){this._restoreFocusedItem()}else{this._createFocusBackfillItem()}}else if(this._virtualCount>0&&this._physicalCount>0){this._focusedIndex=this._virtualStart;this._focusedItem=this._physicalItems[this._physicalStart]}},_isIndexRendered:function(idx){return idx>=this._virtualStart&&idx<=this._virtualEnd},_isIndexVisible:function(idx){return idx>=this.firstVisibleIndex&&idx<=this.lastVisibleIndex},_getPhysicalIndex:function(idx){return this._physicalIndexForKey[this._collection.getKey(this._getNormalizedItem(idx))]},_focusPhysicalItem:function(idx){if(idx<0||idx>=this._virtualCount){return}this._restoreFocusedItem();if(!this._isIndexRendered(idx)){this.scrollToIndex(idx)}var physicalItem=this._physicalItems[this._getPhysicalIndex(idx)];var model=physicalItem._templateInstance;var focusable;model.tabIndex=SECRET_TABINDEX;if(physicalItem.tabIndex===SECRET_TABINDEX){focusable=physicalItem}if(!focusable){focusable=Polymer.dom(physicalItem).querySelector('[tabindex="'+SECRET_TABINDEX+'"]')}model.tabIndex=0;this._focusedIndex=idx;focusable&&focusable.focus()},_removeFocusedItem:function(){if(this._offscreenFocusedItem){Polymer.dom(this).removeChild(this._offscreenFocusedItem)}this._offscreenFocusedItem=null;this._focusBackfillItem=null;this._focusedItem=null;this._focusedIndex=-1},_createFocusBackfillItem:function(){var fidx=this._focusedIndex;var pidx=this._getPhysicalIndex(fidx);if(this._offscreenFocusedItem||pidx==null||fidx<0){return}if(!this._focusBackfillItem){var stampedTemplate=this.stamp(null);this._focusBackfillItem=stampedTemplate.root.querySelector("*");Polymer.dom(this).appendChild(stampedTemplate.root)}this._offscreenFocusedItem=this._physicalItems[pidx];this._offscreenFocusedItem._templateInstance.tabIndex=0;this._physicalItems[pidx]=this._focusBackfillItem;this.translate3d(0,HIDDEN_Y,0,this._offscreenFocusedItem)},_restoreFocusedItem:function(){var pidx,fidx=this._focusedIndex;if(!this._offscreenFocusedItem||this._focusedIndex<0){return}this._assignModels();pidx=this._getPhysicalIndex(fidx);if(pidx!=null){this._focusBackfillItem=this._physicalItems[pidx];this._focusBackfillItem._templateInstance.tabIndex=-1;this._physicalItems[pidx]=this._offscreenFocusedItem;this._offscreenFocusedItem=null;this.translate3d(0,HIDDEN_Y,0,this._focusBackfillItem)}},_didFocus:function(e){var targetModel=this.modelForElement(e.target);var focusedModel=this._focusedItem?this._focusedItem._templateInstance:null;var hasOffscreenFocusedItem=this._offscreenFocusedItem!==null;var fidx=this._focusedIndex;if(!targetModel||!focusedModel){return}if(focusedModel===targetModel){if(!this._isIndexVisible(fidx)){this.scrollToIndex(fidx)}}else{this._restoreFocusedItem();focusedModel.tabIndex=-1;targetModel.tabIndex=0;fidx=targetModel[this.indexAs];this._focusedIndex=fidx;this._focusedItem=this._physicalItems[this._getPhysicalIndex(fidx)];if(hasOffscreenFocusedItem&&!this._offscreenFocusedItem){this._update()}}},_didMoveUp:function(){this._focusPhysicalItem(this._focusedIndex-1)},_didMoveDown:function(e){e.detail.keyboardEvent.preventDefault();this._focusPhysicalItem(this._focusedIndex+1)},_didEnter:function(e){this._focusPhysicalItem(this._focusedIndex);this._selectionHandler(e.detail.keyboardEvent)}})})();
-// 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.
-cr.define("downloads",function(){function chromeSendWithId(chromeSendName){return function(id){chrome.send(chromeSendName,[id])}}function ActionService(){this.searchTerms_=[]}function trim(s){return s.trim()}function truthy(value){return!!value}ActionService.splitTerms=function(searchText){return searchText.split(/"([^"]*)"/).map(trim).filter(truthy)};ActionService.prototype={cancel:chromeSendWithId("cancel"),clearAll:function(){if(loadTimeData.getBoolean("allowDeletingHistory")){chrome.send("clearAll");this.search("")}},discardDangerous:chromeSendWithId("discardDangerous"),download:function(url){var a=document.createElement("a");a.href=url;a.setAttribute("download","");a.click()},drag:chromeSendWithId("drag"),loadMore:function(){chrome.send("getDownloads",this.searchTerms_)},isSearching:function(){return this.searchTerms_.length>0},openDownloadsFolder:function(){chrome.send("openDownloadsFolderRequiringGesture")},openFile:chromeSendWithId("openFileRequiringGesture"),pause:chromeSendWithId("pause"),remove:chromeSendWithId("remove"),resume:chromeSendWithId("resume"),saveDangerous:chromeSendWithId("saveDangerousRequiringGesture"),search:function(searchText){var searchTerms=ActionService.splitTerms(searchText);var sameTerms=searchTerms.length==this.searchTerms_.length;for(var i=0;sameTerms&&i<searchTerms.length;++i){if(searchTerms[i]!=this.searchTerms_[i])sameTerms=false}if(sameTerms)return false;this.searchTerms_=searchTerms;this.loadMore();return true},show:chromeSendWithId("show"),undo:chrome.send.bind(chrome,"undo")};cr.addSingletonGetter(ActionService);return{ActionService:ActionService}});
-// 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.
-cr.define("downloads",function(){var DangerType={NOT_DANGEROUS:"NOT_DANGEROUS",DANGEROUS_FILE:"DANGEROUS_FILE",DANGEROUS_URL:"DANGEROUS_URL",DANGEROUS_CONTENT:"DANGEROUS_CONTENT",UNCOMMON_CONTENT:"UNCOMMON_CONTENT",DANGEROUS_HOST:"DANGEROUS_HOST",POTENTIALLY_UNWANTED:"POTENTIALLY_UNWANTED"};var States={IN_PROGRESS:"IN_PROGRESS",CANCELLED:"CANCELLED",COMPLETE:"COMPLETE",PAUSED:"PAUSED",DANGEROUS:"DANGEROUS",INTERRUPTED:"INTERRUPTED"};return{DangerType:DangerType,States:States}});
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-var ActionLink=document.registerElement("action-link",{prototype:{__proto__:HTMLAnchorElement.prototype,createdCallback:function(){this.tabIndex=this.disabled?-1:0;if(!this.hasAttribute("role"))this.setAttribute("role","link");this.addEventListener("keydown",function(e){if(!this.disabled&&e.key=="Enter"&&!this.href){window.setTimeout(this.click.bind(this),0)}});function preventDefault(e){e.preventDefault()}function removePreventDefault(){document.removeEventListener("selectstart",preventDefault);document.removeEventListener("mouseup",removePreventDefault)}this.addEventListener("mousedown",function(){document.addEventListener("selectstart",preventDefault);document.addEventListener("mouseup",removePreventDefault);if(document.activeElement!=this)this.classList.add("no-outline")});this.addEventListener("blur",function(){this.classList.remove("no-outline")})},set disabled(disabled){if(disabled)HTMLAnchorElement.prototype.setAttribute.call(this,"disabled","");else HTMLAnchorElement.prototype.removeAttribute.call(this,"disabled");this.tabIndex=disabled?-1:0},get disabled(){return this.hasAttribute("disabled")},setAttribute:function(attr,val){if(attr.toLowerCase()=="disabled")this.disabled=true;else HTMLAnchorElement.prototype.setAttribute.apply(this,arguments)},removeAttribute:function(attr){if(attr.toLowerCase()=="disabled")this.disabled=false;else HTMLAnchorElement.prototype.removeAttribute.apply(this,arguments)}},"extends":"a"});(function(){var metaDatas={};var metaArrays={};var singleton=null;Polymer.IronMeta=Polymer({is:"iron-meta",properties:{type:{type:String,value:"default",observer:"_typeChanged"},key:{type:String,observer:"_keyChanged"},value:{type:Object,notify:true,observer:"_valueChanged"},self:{type:Boolean,observer:"_selfChanged"},list:{type:Array,notify:true}},hostAttributes:{hidden:true},factoryImpl:function(config){if(config){for(var n in config){switch(n){case"type":case"key":case"value":this[n]=config[n];break}}}},created:function(){this._metaDatas=metaDatas;this._metaArrays=metaArrays},_keyChanged:function(key,old){this._resetRegistration(old)},_valueChanged:function(value){this._resetRegistration(this.key)},_selfChanged:function(self){if(self){this.value=this}},_typeChanged:function(type){this._unregisterKey(this.key);if(!metaDatas[type]){metaDatas[type]={}}this._metaData=metaDatas[type];if(!metaArrays[type]){metaArrays[type]=[]}this.list=metaArrays[type];this._registerKeyValue(this.key,this.value)},byKey:function(key){return this._metaData&&this._metaData[key]},_resetRegistration:function(oldKey){this._unregisterKey(oldKey);this._registerKeyValue(this.key,this.value)},_unregisterKey:function(key){this._unregister(key,this._metaData,this.list)},_registerKeyValue:function(key,value){this._register(key,value,this._metaData,this.list)},_register:function(key,value,data,list){if(key&&data&&value!==undefined){data[key]=value;list.push(value)}},_unregister:function(key,data,list){if(key&&data){if(key in data){var value=data[key];delete data[key];this.arrayDelete(list,value)}}}});Polymer.IronMeta.getIronMeta=function getIronMeta(){if(singleton===null){singleton=new Polymer.IronMeta}return singleton};Polymer.IronMetaQuery=Polymer({is:"iron-meta-query",properties:{type:{type:String,value:"default",observer:"_typeChanged"},key:{type:String,observer:"_keyChanged"},value:{type:Object,notify:true,readOnly:true},list:{type:Array,notify:true}},factoryImpl:function(config){if(config){for(var n in config){switch(n){case"type":case"key":this[n]=config[n];break}}}},created:function(){this._metaDatas=metaDatas;this._metaArrays=metaArrays},_keyChanged:function(key){this._setValue(this._metaData&&this._metaData[key])},_typeChanged:function(type){this._metaData=metaDatas[type];this.list=metaArrays[type];if(this.key){this._keyChanged(this.key)}},byKey:function(key){return this._metaData&&this._metaData[key]}})})();Polymer({is:"iron-icon",properties:{icon:{type:String,observer:"_iconChanged"},theme:{type:String,observer:"_updateIcon"},src:{type:String,observer:"_srcChanged"},_meta:{value:Polymer.Base.create("iron-meta",{type:"iconset"}),observer:"_updateIcon"}},_DEFAULT_ICONSET:"icons",_iconChanged:function(icon){var parts=(icon||"").split(":");this._iconName=parts.pop();this._iconsetName=parts.pop()||this._DEFAULT_ICONSET;this._updateIcon()},_srcChanged:function(src){this._updateIcon()},_usesIconset:function(){return this.icon||!this.src},_updateIcon:function(){if(this._usesIconset()){if(this._img&&this._img.parentNode){Polymer.dom(this.root).removeChild(this._img)}if(this._iconName===""){if(this._iconset){this._iconset.removeIcon(this)}}else if(this._iconsetName&&this._meta){this._iconset=this._meta.byKey(this._iconsetName);if(this._iconset){this._iconset.applyIcon(this,this._iconName,this.theme);this.unlisten(window,"iron-iconset-added","_updateIcon")}else{this.listen(window,"iron-iconset-added","_updateIcon")}}}else{if(this._iconset){this._iconset.removeIcon(this)}if(!this._img){this._img=document.createElement("img");this._img.style.width="100%";this._img.style.height="100%";this._img.draggable=false}this._img.src=this.src;Polymer.dom(this.root).appendChild(this._img)}}});Polymer.IronControlState={properties:{focused:{type:Boolean,value:false,notify:true,readOnly:true,reflectToAttribute:true},disabled:{type:Boolean,value:false,notify:true,observer:"_disabledChanged",reflectToAttribute:true},_oldTabIndex:{type:Number},_boundFocusBlurHandler:{type:Function,value:function(){return this._focusBlurHandler.bind(this)}}},observers:["_changedControlState(focused, disabled)"],ready:function(){this.addEventListener("focus",this._boundFocusBlurHandler,true);this.addEventListener("blur",this._boundFocusBlurHandler,true)},_focusBlurHandler:function(event){if(event.target===this){this._setFocused(event.type==="focus")}else if(!this.shadowRoot){var target=Polymer.dom(event).localTarget;if(!this.isLightDescendant(target)){this.fire(event.type,{sourceEvent:event},{node:this,bubbles:event.bubbles,cancelable:event.cancelable})}}},_disabledChanged:function(disabled,old){this.setAttribute("aria-disabled",disabled?"true":"false");this.style.pointerEvents=disabled?"none":"";if(disabled){this._oldTabIndex=this.tabIndex;this._setFocused(false);this.tabIndex=-1;this.blur()}else if(this._oldTabIndex!==undefined){this.tabIndex=this._oldTabIndex}},_changedControlState:function(){if(this._controlStateChanged){this._controlStateChanged()}}};Polymer.IronButtonStateImpl={properties:{pressed:{type:Boolean,readOnly:true,value:false,reflectToAttribute:true,observer:"_pressedChanged"},toggles:{type:Boolean,value:false,reflectToAttribute:true},active:{type:Boolean,value:false,notify:true,reflectToAttribute:true},pointerDown:{type:Boolean,readOnly:true,value:false},receivedFocusFromKeyboard:{type:Boolean,readOnly:true},ariaActiveAttribute:{type:String,value:"aria-pressed",observer:"_ariaActiveAttributeChanged"}},listeners:{down:"_downHandler",up:"_upHandler",tap:"_tapHandler"},observers:["_detectKeyboardFocus(focused)","_activeChanged(active, ariaActiveAttribute)"],keyBindings:{"enter:keydown":"_asyncClick","space:keydown":"_spaceKeyDownHandler","space:keyup":"_spaceKeyUpHandler"},_mouseEventRe:/^mouse/,_tapHandler:function(){if(this.toggles){this._userActivate(!this.active)}else{this.active=false}},_detectKeyboardFocus:function(focused){this._setReceivedFocusFromKeyboard(!this.pointerDown&&focused)},_userActivate:function(active){if(this.active!==active){this.active=active;this.fire("change")}},_downHandler:function(event){this._setPointerDown(true);this._setPressed(true);this._setReceivedFocusFromKeyboard(false)},_upHandler:function(){this._setPointerDown(false);this._setPressed(false)},_spaceKeyDownHandler:function(event){var keyboardEvent=event.detail.keyboardEvent;var target=Polymer.dom(keyboardEvent).localTarget;if(this.isLightDescendant(target))return;keyboardEvent.preventDefault();keyboardEvent.stopImmediatePropagation();this._setPressed(true)},_spaceKeyUpHandler:function(event){var keyboardEvent=event.detail.keyboardEvent;var target=Polymer.dom(keyboardEvent).localTarget;if(this.isLightDescendant(target))return;if(this.pressed){this._asyncClick()}this._setPressed(false)},_asyncClick:function(){this.async(function(){this.click()},1)},_pressedChanged:function(pressed){this._changedButtonState()},_ariaActiveAttributeChanged:function(value,oldValue){if(oldValue&&oldValue!=value&&this.hasAttribute(oldValue)){this.removeAttribute(oldValue)}},_activeChanged:function(active,ariaActiveAttribute){if(this.toggles){this.setAttribute(this.ariaActiveAttribute,active?"true":"false")}else{this.removeAttribute(this.ariaActiveAttribute)}this._changedButtonState()},_controlStateChanged:function(){if(this.disabled){this._setPressed(false)}else{this._changedButtonState()}},_changedButtonState:function(){if(this._buttonStateChanged){this._buttonStateChanged()}}};Polymer.IronButtonState=[Polymer.IronA11yKeysBehavior,Polymer.IronButtonStateImpl];(function(){var Utility={distance:function(x1,y1,x2,y2){var xDelta=x1-x2;var yDelta=y1-y2;return Math.sqrt(xDelta*xDelta+yDelta*yDelta)},now:window.performance&&window.performance.now?window.performance.now.bind(window.performance):Date.now};function ElementMetrics(element){this.element=element;this.width=this.boundingRect.width;this.height=this.boundingRect.height;this.size=Math.max(this.width,this.height)}ElementMetrics.prototype={get boundingRect(){return this.element.getBoundingClientRect()},furthestCornerDistanceFrom:function(x,y){var topLeft=Utility.distance(x,y,0,0);var topRight=Utility.distance(x,y,this.width,0);var bottomLeft=Utility.distance(x,y,0,this.height);var bottomRight=Utility.distance(x,y,this.width,this.height);return Math.max(topLeft,topRight,bottomLeft,bottomRight)}};function Ripple(element){this.element=element;this.color=window.getComputedStyle(element).color;this.wave=document.createElement("div");this.waveContainer=document.createElement("div");this.wave.style.backgroundColor=this.color;this.wave.classList.add("wave");this.waveContainer.classList.add("wave-container");Polymer.dom(this.waveContainer).appendChild(this.wave);this.resetInteractionState()}Ripple.MAX_RADIUS=300;Ripple.prototype={get recenters(){return this.element.recenters},get center(){return this.element.center},get mouseDownElapsed(){var elapsed;if(!this.mouseDownStart){return 0}elapsed=Utility.now()-this.mouseDownStart;if(this.mouseUpStart){elapsed-=this.mouseUpElapsed}return elapsed},get mouseUpElapsed(){return this.mouseUpStart?Utility.now()-this.mouseUpStart:0},get mouseDownElapsedSeconds(){return this.mouseDownElapsed/1e3},get mouseUpElapsedSeconds(){return this.mouseUpElapsed/1e3},get mouseInteractionSeconds(){return this.mouseDownElapsedSeconds+this.mouseUpElapsedSeconds},get initialOpacity(){return this.element.initialOpacity},get opacityDecayVelocity(){return this.element.opacityDecayVelocity},get radius(){var width2=this.containerMetrics.width*this.containerMetrics.width;var height2=this.containerMetrics.height*this.containerMetrics.height;var waveRadius=Math.min(Math.sqrt(width2+height2),Ripple.MAX_RADIUS)*1.1+5;var duration=1.1-.2*(waveRadius/Ripple.MAX_RADIUS);var timeNow=this.mouseInteractionSeconds/duration;var size=waveRadius*(1-Math.pow(80,-timeNow));return Math.abs(size)},get opacity(){if(!this.mouseUpStart){return this.initialOpacity}return Math.max(0,this.initialOpacity-this.mouseUpElapsedSeconds*this.opacityDecayVelocity)},get outerOpacity(){var outerOpacity=this.mouseUpElapsedSeconds*.3;var waveOpacity=this.opacity;return Math.max(0,Math.min(outerOpacity,waveOpacity))},get isOpacityFullyDecayed(){return this.opacity<.01&&this.radius>=Math.min(this.maxRadius,Ripple.MAX_RADIUS)},get isRestingAtMaxRadius(){return this.opacity>=this.initialOpacity&&this.radius>=Math.min(this.maxRadius,Ripple.MAX_RADIUS)},get isAnimationComplete(){return this.mouseUpStart?this.isOpacityFullyDecayed:this.isRestingAtMaxRadius},get translationFraction(){return Math.min(1,this.radius/this.containerMetrics.size*2/Math.sqrt(2))},get xNow(){if(this.xEnd){return this.xStart+this.translationFraction*(this.xEnd-this.xStart)}return this.xStart},get yNow(){if(this.yEnd){return this.yStart+this.translationFraction*(this.yEnd-this.yStart)}return this.yStart},get isMouseDown(){return this.mouseDownStart&&!this.mouseUpStart},resetInteractionState:function(){this.maxRadius=0;this.mouseDownStart=0;this.mouseUpStart=0;this.xStart=0;this.yStart=0;this.xEnd=0;this.yEnd=0;this.slideDistance=0;this.containerMetrics=new ElementMetrics(this.element)},draw:function(){var scale;var translateString;var dx;var dy;this.wave.style.opacity=this.opacity;scale=this.radius/(this.containerMetrics.size/2);dx=this.xNow-this.containerMetrics.width/2;dy=this.yNow-this.containerMetrics.height/2;this.waveContainer.style.webkitTransform="translate("+dx+"px, "+dy+"px)";this.waveContainer.style.transform="translate3d("+dx+"px, "+dy+"px, 0)";this.wave.style.webkitTransform="scale("+scale+","+scale+")";this.wave.style.transform="scale3d("+scale+","+scale+",1)"},downAction:function(event){var xCenter=this.containerMetrics.width/2;var yCenter=this.containerMetrics.height/2;this.resetInteractionState();this.mouseDownStart=Utility.now();if(this.center){this.xStart=xCenter;this.yStart=yCenter;this.slideDistance=Utility.distance(this.xStart,this.yStart,this.xEnd,this.yEnd)}else{this.xStart=event?event.detail.x-this.containerMetrics.boundingRect.left:this.containerMetrics.width/2;this.yStart=event?event.detail.y-this.containerMetrics.boundingRect.top:this.containerMetrics.height/2}if(this.recenters){this.xEnd=xCenter;this.yEnd=yCenter;this.slideDistance=Utility.distance(this.xStart,this.yStart,this.xEnd,this.yEnd)}this.maxRadius=this.containerMetrics.furthestCornerDistanceFrom(this.xStart,this.yStart);this.waveContainer.style.top=(this.containerMetrics.height-this.containerMetrics.size)/2+"px";this.waveContainer.style.left=(this.containerMetrics.width-this.containerMetrics.size)/2+"px";this.waveContainer.style.width=this.containerMetrics.size+"px";this.waveContainer.style.height=this.containerMetrics.size+"px"},upAction:function(event){if(!this.isMouseDown){return}this.mouseUpStart=Utility.now()},remove:function(){Polymer.dom(this.waveContainer.parentNode).removeChild(this.waveContainer)}};Polymer({is:"paper-ripple",behaviors:[Polymer.IronA11yKeysBehavior],properties:{initialOpacity:{type:Number,value:.25},opacityDecayVelocity:{type:Number,value:.8},recenters:{type:Boolean,value:false},center:{type:Boolean,value:false},ripples:{type:Array,value:function(){return[]}},animating:{type:Boolean,readOnly:true,reflectToAttribute:true,value:false},holdDown:{type:Boolean,value:false,observer:"_holdDownChanged"},noink:{type:Boolean,value:false},_animating:{type:Boolean},_boundAnimate:{type:Function,value:function(){return this.animate.bind(this)}}},get target(){return this.keyEventTarget},keyBindings:{"enter:keydown":"_onEnterKeydown","space:keydown":"_onSpaceKeydown","space:keyup":"_onSpaceKeyup"},attached:function(){if(this.parentNode.nodeType==11){this.keyEventTarget=Polymer.dom(this).getOwnerRoot().host}else{this.keyEventTarget=this.parentNode}var keyEventTarget=this.keyEventTarget;this.listen(keyEventTarget,"up","uiUpAction");this.listen(keyEventTarget,"down","uiDownAction")},detached:function(){this.unlisten(this.keyEventTarget,"up","uiUpAction");this.unlisten(this.keyEventTarget,"down","uiDownAction");this.keyEventTarget=null},get shouldKeepAnimating(){for(var index=0;index<this.ripples.length;++index){if(!this.ripples[index].isAnimationComplete){return true}}return false},simulatedRipple:function(){this.downAction(null);this.async(function(){this.upAction()},1)},uiDownAction:function(event){if(!this.noink){this.downAction(event)}},downAction:function(event){if(this.holdDown&&this.ripples.length>0){return}var ripple=this.addRipple();ripple.downAction(event);if(!this._animating){this._animating=true;this.animate()}},uiUpAction:function(event){if(!this.noink){this.upAction(event)}},upAction:function(event){if(this.holdDown){return}this.ripples.forEach(function(ripple){ripple.upAction(event)});this._animating=true;this.animate()},onAnimationComplete:function(){this._animating=false;this.$.background.style.backgroundColor=null;this.fire("transitionend")},addRipple:function(){var ripple=new Ripple(this);Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);this.$.background.style.backgroundColor=ripple.color;this.ripples.push(ripple);this._setAnimating(true);return ripple},removeRipple:function(ripple){var rippleIndex=this.ripples.indexOf(ripple);if(rippleIndex<0){return}this.ripples.splice(rippleIndex,1);ripple.remove();if(!this.ripples.length){this._setAnimating(false)}},animate:function(){if(!this._animating){return}var index;var ripple;for(index=0;index<this.ripples.length;++index){ripple=this.ripples[index];ripple.draw();this.$.background.style.opacity=ripple.outerOpacity;if(ripple.isOpacityFullyDecayed&&!ripple.isRestingAtMaxRadius){this.removeRipple(ripple)}}if(!this.shouldKeepAnimating&&this.ripples.length===0){this.onAnimationComplete()}else{window.requestAnimationFrame(this._boundAnimate)}},_onEnterKeydown:function(){this.uiDownAction();this.async(this.uiUpAction,1)},_onSpaceKeydown:function(){this.uiDownAction()},_onSpaceKeyup:function(){this.uiUpAction()},_holdDownChanged:function(newVal,oldVal){if(oldVal===undefined){return}if(newVal){this.downAction()}else{this.upAction()}}})})();Polymer.PaperRippleBehavior={properties:{noink:{type:Boolean,observer:"_noinkChanged"},_rippleContainer:{type:Object}},_buttonStateChanged:function(){if(this.focused){this.ensureRipple()}},_downHandler:function(event){Polymer.IronButtonStateImpl._downHandler.call(this,event);if(this.pressed){this.ensureRipple(event)}},ensureRipple:function(optTriggeringEvent){if(!this.hasRipple()){this._ripple=this._createRipple();this._ripple.noink=this.noink;var rippleContainer=this._rippleContainer||this.root;if(rippleContainer){Polymer.dom(rippleContainer).appendChild(this._ripple)}if(optTriggeringEvent){var domContainer=Polymer.dom(this._rippleContainer||this);var target=Polymer.dom(optTriggeringEvent).rootTarget;if(domContainer.deepContains(target)){this._ripple.uiDownAction(optTriggeringEvent)}}}},getRipple:function(){this.ensureRipple();return this._ripple},hasRipple:function(){return Boolean(this._ripple)},_createRipple:function(){return document.createElement("paper-ripple")},_noinkChanged:function(noink){if(this.hasRipple()){this._ripple.noink=noink}}};Polymer.PaperButtonBehaviorImpl={properties:{elevation:{type:Number,reflectToAttribute:true,readOnly:true}},observers:["_calculateElevation(focused, disabled, active, pressed, receivedFocusFromKeyboard)","_computeKeyboardClass(receivedFocusFromKeyboard)"],hostAttributes:{role:"button",tabindex:"0",animated:true},_calculateElevation:function(){var e=1;if(this.disabled){e=0}else if(this.active||this.pressed){e=4}else if(this.receivedFocusFromKeyboard){e=3}this._setElevation(e)},_computeKeyboardClass:function(receivedFocusFromKeyboard){this.toggleClass("keyboard-focus",receivedFocusFromKeyboard)},_spaceKeyDownHandler:function(event){Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this,event);if(this.hasRipple()&&this.getRipple().ripples.length<1){this._ripple.uiDownAction()}},_spaceKeyUpHandler:function(event){Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this,event);if(this.hasRipple()){this._ripple.uiUpAction()}}};Polymer.PaperButtonBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperRippleBehavior,Polymer.PaperButtonBehaviorImpl];Polymer({is:"paper-button",behaviors:[Polymer.PaperButtonBehavior],properties:{raised:{type:Boolean,reflectToAttribute:true,value:false,observer:"_calculateElevation"}},_calculateElevation:function(){if(!this.raised){this._setElevation(0)}else{Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this)}}});Polymer({is:"paper-icon-button-light","extends":"button",behaviors:[Polymer.PaperRippleBehavior],listeners:{down:"_rippleDown",up:"_rippleUp",focus:"_rippleDown",blur:"_rippleUp"},_rippleDown:function(){this.getRipple().downAction()},_rippleUp:function(){this.getRipple().upAction()},ensureRipple:function(var_args){var lastRipple=this._ripple;Polymer.PaperRippleBehavior.ensureRipple.apply(this,arguments);if(this._ripple&&this._ripple!==lastRipple){this._ripple.center=true;this._ripple.classList.add("circle")}}});Polymer.IronRangeBehavior={properties:{value:{type:Number,value:0,notify:true,reflectToAttribute:true},min:{type:Number,value:0,notify:true},max:{type:Number,value:100,notify:true},step:{type:Number,value:1,notify:true},ratio:{type:Number,value:0,readOnly:true,notify:true}},observers:["_update(value, min, max, step)"],_calcRatio:function(value){return(this._clampValue(value)-this.min)/(this.max-this.min)},_clampValue:function(value){return Math.min(this.max,Math.max(this.min,this._calcStep(value)))},_calcStep:function(value){value=parseFloat(value);if(!this.step){return value}var numSteps=Math.round((value-this.min)/this.step);if(this.step<1){return numSteps/(1/this.step)+this.min}else{return numSteps*this.step+this.min}},_validateValue:function(){var v=this._clampValue(this.value);this.value=this.oldValue=isNaN(v)?this.oldValue:v;return this.value!==v},_update:function(){this._validateValue();this._setRatio(this._calcRatio(this.value)*100)}};Polymer({is:"paper-progress",behaviors:[Polymer.IronRangeBehavior],properties:{secondaryProgress:{type:Number,value:0},secondaryRatio:{type:Number,value:0,readOnly:true},indeterminate:{type:Boolean,value:false,observer:"_toggleIndeterminate"},disabled:{type:Boolean,value:false,reflectToAttribute:true,observer:"_disabledChanged"}},observers:["_progressChanged(secondaryProgress, value, min, max)"],hostAttributes:{role:"progressbar"},_toggleIndeterminate:function(indeterminate){this.toggleClass("indeterminate",indeterminate,this.$.primaryProgress)},_transformProgress:function(progress,ratio){var transform="scaleX("+ratio/100+")";progress.style.transform=progress.style.webkitTransform=transform},_mainRatioChanged:function(ratio){this._transformProgress(this.$.primaryProgress,ratio)},_progressChanged:function(secondaryProgress,value,min,max){secondaryProgress=this._clampValue(secondaryProgress);value=this._clampValue(value);var secondaryRatio=this._calcRatio(secondaryProgress)*100;var mainRatio=this._calcRatio(value)*100;this._setSecondaryRatio(secondaryRatio);this._transformProgress(this.$.secondaryProgress,secondaryRatio);this._transformProgress(this.$.primaryProgress,mainRatio);this.secondaryProgress=secondaryProgress;this.setAttribute("aria-valuenow",value);this.setAttribute("aria-valuemin",min);this.setAttribute("aria-valuemax",max)},_disabledChanged:function(disabled){this.setAttribute("aria-disabled",disabled?"true":"false")},_hideSecondaryProgress:function(secondaryRatio){return secondaryRatio===0}});Polymer({is:"iron-iconset-svg",properties:{name:{type:String,observer:"_nameChanged"},size:{type:Number,value:24},rtlMirroring:{type:Boolean,value:false}},_targetIsRTL:function(target){if(target&&target.nodeType!==Node.ELEMENT_NODE){target=target.host}return target&&window.getComputedStyle(target)["direction"]==="rtl"},attached:function(){this.style.display="none"},getIconNames:function(){this._icons=this._createIconMap();return Object.keys(this._icons).map(function(n){return this.name+":"+n},this)},applyIcon:function(element,iconName){element=element.root||element;this.removeIcon(element);var svg=this._cloneIcon(iconName,this.rtlMirroring&&this._targetIsRTL(element));if(svg){var pde=Polymer.dom(element);pde.insertBefore(svg,pde.childNodes[0]);return element._svgIcon=svg}return null},removeIcon:function(element){element=element.root||element;if(element._svgIcon){Polymer.dom(element).removeChild(element._svgIcon);element._svgIcon=null}},_nameChanged:function(){new Polymer.IronMeta({type:"iconset",key:this.name,value:this});this.async(function(){this.fire("iron-iconset-added",this,{node:window})})},_createIconMap:function(){var icons=Object.create(null);Polymer.dom(this).querySelectorAll("[id]").forEach(function(icon){icons[icon.id]=icon});return icons},_cloneIcon:function(id,mirrorAllowed){this._icons=this._icons||this._createIconMap();return this._prepareSvgClone(this._icons[id],this.size,mirrorAllowed)},_prepareSvgClone:function(sourceSvg,size,mirrorAllowed){if(sourceSvg){var content=sourceSvg.cloneNode(true),svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),viewBox=content.getAttribute("viewBox")||"0 0 "+size+" "+size,cssText="pointer-events: none; display: block; width: 100%; height: 100%;";if(mirrorAllowed&&content.hasAttribute("mirror-in-rtl")){cssText+="-webkit-transform:scale(-1,1);transform:scale(-1,1);"}svg.setAttribute("viewBox",viewBox);svg.setAttribute("preserveAspectRatio","xMidYMid meet");svg.style.cssText=cssText;svg.appendChild(content).removeAttribute("id");return svg}return null}});
-// 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.
-cr.define("downloads",function(){var Item=Polymer({is:"downloads-item",properties:{data:{type:Object},completelyOnDisk_:{computed:"computeCompletelyOnDisk_("+"data.state, data.file_externally_removed)",type:Boolean,value:true},controlledBy_:{computed:"computeControlledBy_(data.by_ext_id, data.by_ext_name)",type:String,value:""},isActive_:{computed:"computeIsActive_("+"data.state, data.file_externally_removed)",type:Boolean,value:true},isDangerous_:{computed:"computeIsDangerous_(data.state)",type:Boolean,value:false},isMalware_:{computed:"computeIsMalware_(isDangerous_, data.danger_type)",type:Boolean,value:false},isInProgress_:{computed:"computeIsInProgress_(data.state)",type:Boolean,value:false},pauseOrResumeText_:{computed:"computePauseOrResumeText_(isInProgress_, data.resume)",type:String},showCancel_:{computed:"computeShowCancel_(data.state)",type:Boolean,value:false},showProgress_:{computed:"computeShowProgress_(showCancel_, data.percent)",type:Boolean,value:false}},observers:["observeControlledBy_(controlledBy_)","observeIsDangerous_(isDangerous_, data)"],ready:function(){this.content=this.$.content},chopUrl_:function(url){return url.slice(0,300)},computeClass_:function(){var classes=[];if(this.isActive_)classes.push("is-active");if(this.isDangerous_)classes.push("dangerous");if(this.showProgress_)classes.push("show-progress");return classes.join(" ")},computeCompletelyOnDisk_:function(){return this.data.state==downloads.States.COMPLETE&&!this.data.file_externally_removed},computeControlledBy_:function(){if(!this.data.by_ext_id||!this.data.by_ext_name)return"";var url="chrome://extensions#"+this.data.by_ext_id;var name=this.data.by_ext_name;return loadTimeData.getStringF("controlledByUrl",url,HTMLEscape(name))},computeDangerIcon_:function(){return this.isDangerous_?"cr:warning":""},computeDate_:function(){assert(typeof this.data.hideDate=="boolean");if(this.data.hideDate)return"";return assert(this.data.since_string||this.data.date_string)},computeDescription_:function(){var data=this.data;switch(data.state){case downloads.States.DANGEROUS:var fileName=data.file_name;switch(data.danger_type){case downloads.DangerType.DANGEROUS_FILE:return loadTimeData.getString("dangerFileDesc");case downloads.DangerType.DANGEROUS_URL:case downloads.DangerType.DANGEROUS_CONTENT:case downloads.DangerType.DANGEROUS_HOST:return loadTimeData.getString("dangerDownloadDesc");case downloads.DangerType.UNCOMMON_CONTENT:return loadTimeData.getString("dangerUncommonDesc");case downloads.DangerType.POTENTIALLY_UNWANTED:return loadTimeData.getString("dangerSettingsDesc")}break;case downloads.States.IN_PROGRESS:case downloads.States.PAUSED:return data.progress_status_text}return""},computeIsActive_:function(){return this.data.state!=downloads.States.CANCELLED&&this.data.state!=downloads.States.INTERRUPTED&&!this.data.file_externally_removed},computeIsDangerous_:function(){return this.data.state==downloads.States.DANGEROUS},computeIsInProgress_:function(){return this.data.state==downloads.States.IN_PROGRESS},computeIsMalware_:function(){return this.isDangerous_&&(this.data.danger_type==downloads.DangerType.DANGEROUS_CONTENT||this.data.danger_type==downloads.DangerType.DANGEROUS_HOST||this.data.danger_type==downloads.DangerType.DANGEROUS_URL||this.data.danger_type==downloads.DangerType.POTENTIALLY_UNWANTED)},computePauseOrResumeText_:function(){if(this.isInProgress_)return loadTimeData.getString("controlPause");if(this.data.resume)return loadTimeData.getString("controlResume");return""},computeRemoveStyle_:function(){var canDelete=loadTimeData.getBoolean("allowDeletingHistory");var hideRemove=this.isDangerous_||this.showCancel_||!canDelete;return hideRemove?"visibility: hidden":""},computeShowCancel_:function(){return this.data.state==downloads.States.IN_PROGRESS||this.data.state==downloads.States.PAUSED},computeShowProgress_:function(){return this.showCancel_&&this.data.percent>=-1},computeTag_:function(){switch(this.data.state){case downloads.States.CANCELLED:return loadTimeData.getString("statusCancelled");case downloads.States.INTERRUPTED:return this.data.last_reason_text;case downloads.States.COMPLETE:return this.data.file_externally_removed?loadTimeData.getString("statusRemoved"):""}return""},isIndeterminate_:function(){return this.data.percent==-1},observeControlledBy_:function(){this.$["controlled-by"].innerHTML=this.controlledBy_},observeIsDangerous_:function(){if(!this.data)return;if(this.isDangerous_){this.$.url.removeAttribute("href")}else{this.$.url.href=assert(this.data.url);var filePath=encodeURIComponent(this.data.file_path);var scaleFactor="?scale="+window.devicePixelRatio+"x";this.$["file-icon"].src="chrome://fileicon/"+filePath+scaleFactor}},onCancelTap_:function(){downloads.ActionService.getInstance().cancel(this.data.id)},onDiscardDangerousTap_:function(){downloads.ActionService.getInstance().discardDangerous(this.data.id)},onDragStart_:function(e){e.preventDefault();downloads.ActionService.getInstance().drag(this.data.id)},onFileLinkTap_:function(e){e.preventDefault();downloads.ActionService.getInstance().openFile(this.data.id)},onPauseOrResumeTap_:function(){if(this.isInProgress_)downloads.ActionService.getInstance().pause(this.data.id);else downloads.ActionService.getInstance().resume(this.data.id)},onRemoveTap_:function(){downloads.ActionService.getInstance().remove(this.data.id)},onRetryTap_:function(){downloads.ActionService.getInstance().download(this.data.url)},onSaveDangerousTap_:function(){downloads.ActionService.getInstance().saveDangerous(this.data.id)},onShowTap_:function(){downloads.ActionService.getInstance().show(this.data.id)}});return{Item:Item}});Polymer.PaperItemBehaviorImpl={hostAttributes:{role:"option",tabindex:"0"}};Polymer.PaperItemBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperItemBehaviorImpl];Polymer({is:"paper-item",behaviors:[Polymer.PaperItemBehavior]});Polymer.IronSelection=function(selectCallback){this.selection=[];this.selectCallback=selectCallback};Polymer.IronSelection.prototype={get:function(){return this.multi?this.selection.slice():this.selection[0]},clear:function(excludes){this.selection.slice().forEach(function(item){if(!excludes||excludes.indexOf(item)<0){this.setItemSelected(item,false)}},this)},isSelected:function(item){return this.selection.indexOf(item)>=0},setItemSelected:function(item,isSelected){if(item!=null){if(isSelected!==this.isSelected(item)){if(isSelected){this.selection.push(item)}else{var i=this.selection.indexOf(item);if(i>=0){this.selection.splice(i,1)}}if(this.selectCallback){this.selectCallback(item,isSelected)}}}},select:function(item){if(this.multi){this.toggle(item)}else if(this.get()!==item){this.setItemSelected(this.get(),false);this.setItemSelected(item,true)}},toggle:function(item){this.setItemSelected(item,!this.isSelected(item))}};Polymer.IronSelectableBehavior={properties:{attrForSelected:{type:String,value:null},selected:{type:String,notify:true},selectedItem:{type:Object,readOnly:true,notify:true},activateEvent:{type:String,value:"tap",observer:"_activateEventChanged"},selectable:String,selectedClass:{type:String,value:"iron-selected"},selectedAttribute:{type:String,value:null},fallbackSelection:{type:String,value:null},items:{type:Array,readOnly:true,notify:true,value:function(){return[]}},_excludedLocalNames:{type:Object,value:function(){return{template:1}}}},observers:["_updateAttrForSelected(attrForSelected)","_updateSelected(selected)","_checkFallback(fallbackSelection)"],created:function(){this._bindFilterItem=this._filterItem.bind(this);this._selection=new Polymer.IronSelection(this._applySelection.bind(this))},attached:function(){this._observer=this._observeItems(this);this._updateItems();if(!this._shouldUpdateSelection){this._updateSelected()}this._addListener(this.activateEvent)},detached:function(){if(this._observer){Polymer.dom(this).unobserveNodes(this._observer)}this._removeListener(this.activateEvent)},indexOf:function(item){return this.items.indexOf(item)},select:function(value){this.selected=value},selectPrevious:function(){var length=this.items.length;var index=(Number(this._valueToIndex(this.selected))-1+length)%length;this.selected=this._indexToValue(index)},selectNext:function(){var index=(Number(this._valueToIndex(this.selected))+1)%this.items.length;this.selected=this._indexToValue(index)},selectIndex:function(index){this.select(this._indexToValue(index))},forceSynchronousItemUpdate:function(){this._updateItems()},get _shouldUpdateSelection(){return this.selected!=null},_checkFallback:function(){if(this._shouldUpdateSelection){this._updateSelected()}},_addListener:function(eventName){this.listen(this,eventName,"_activateHandler")},_removeListener:function(eventName){this.unlisten(this,eventName,"_activateHandler")},_activateEventChanged:function(eventName,old){this._removeListener(old);this._addListener(eventName)},_updateItems:function(){var nodes=Polymer.dom(this).queryDistributedElements(this.selectable||"*");nodes=Array.prototype.filter.call(nodes,this._bindFilterItem);this._setItems(nodes)},_updateAttrForSelected:function(){if(this._shouldUpdateSelection){this.selected=this._indexToValue(this.indexOf(this.selectedItem))}},_updateSelected:function(){this._selectSelected(this.selected)},_selectSelected:function(selected){this._selection.select(this._valueToItem(this.selected));if(this.fallbackSelection&&this.items.length&&this._selection.get()===undefined){this.selected=this.fallbackSelection}},_filterItem:function(node){return!this._excludedLocalNames[node.localName]},_valueToItem:function(value){return value==null?null:this.items[this._valueToIndex(value)]},_valueToIndex:function(value){if(this.attrForSelected){for(var i=0,item;item=this.items[i];i++){if(this._valueForItem(item)==value){return i}}}else{return Number(value)}},_indexToValue:function(index){if(this.attrForSelected){var item=this.items[index];if(item){return this._valueForItem(item)}}else{return index}},_valueForItem:function(item){var propValue=item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)];return propValue!=undefined?propValue:item.getAttribute(this.attrForSelected)},_applySelection:function(item,isSelected){if(this.selectedClass){this.toggleClass(this.selectedClass,isSelected,item)}if(this.selectedAttribute){this.toggleAttribute(this.selectedAttribute,isSelected,item)}this._selectionChange();this.fire("iron-"+(isSelected?"select":"deselect"),{item:item})},_selectionChange:function(){this._setSelectedItem(this._selection.get())},_observeItems:function(node){return Polymer.dom(node).observeNodes(function(mutation){this._updateItems();if(this._shouldUpdateSelection){this._updateSelected()}this.fire("iron-items-changed",mutation,{bubbles:false,cancelable:false})})},_activateHandler:function(e){var t=e.target;var items=this.items;while(t&&t!=this){var i=items.indexOf(t);if(i>=0){var value=this._indexToValue(i);this._itemActivate(value,t);return}t=t.parentNode}},_itemActivate:function(value,item){if(!this.fire("iron-activate",{selected:value,item:item},{cancelable:true}).defaultPrevented){this.select(value)}}};Polymer.IronMultiSelectableBehaviorImpl={properties:{multi:{type:Boolean,value:false,observer:"multiChanged"},selectedValues:{type:Array,notify:true},selectedItems:{type:Array,readOnly:true,notify:true}},observers:["_updateSelected(selectedValues.splices)"],select:function(value){if(this.multi){if(this.selectedValues){this._toggleSelected(value)}else{this.selectedValues=[value]}}else{this.selected=value}},multiChanged:function(multi){this._selection.multi=multi},get _shouldUpdateSelection(){return this.selected!=null||this.selectedValues!=null&&this.selectedValues.length},_updateAttrForSelected:function(){if(!this.multi){Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this)}else if(this._shouldUpdateSelection){this.selectedValues=this.selectedItems.map(function(selectedItem){return this._indexToValue(this.indexOf(selectedItem))},this).filter(function(unfilteredValue){return unfilteredValue!=null},this)}},_updateSelected:function(){if(this.multi){this._selectMulti(this.selectedValues)}else{this._selectSelected(this.selected)}},_selectMulti:function(values){if(values){var selectedItems=this._valuesToItems(values);this._selection.clear(selectedItems);for(var i=0;i<selectedItems.length;i++){this._selection.setItemSelected(selectedItems[i],true)}if(this.fallbackSelection&&this.items.length&&!this._selection.get().length){var fallback=this._valueToItem(this.fallbackSelection);if(fallback){this.selectedValues=[this.fallbackSelection]}}}else{this._selection.clear()}},_selectionChange:function(){var s=this._selection.get();if(this.multi){this._setSelectedItems(s)}else{this._setSelectedItems([s]);this._setSelectedItem(s)}},_toggleSelected:function(value){var i=this.selectedValues.indexOf(value);var unselected=i<0;if(unselected){this.push("selectedValues",value)}else{this.splice("selectedValues",i,1)}},_valuesToItems:function(values){return values==null?null:values.map(function(value){return this._valueToItem(value)},this)}};Polymer.IronMultiSelectableBehavior=[Polymer.IronSelectableBehavior,Polymer.IronMultiSelectableBehaviorImpl];Polymer.IronMenuBehaviorImpl={properties:{focusedItem:{observer:"_focusedItemChanged",readOnly:true,type:Object},attrForItemTitle:{type:String}},hostAttributes:{role:"menu",tabindex:"0"},observers:["_updateMultiselectable(multi)"],listeners:{focus:"_onFocus",keydown:"_onKeydown","iron-items-changed":"_onIronItemsChanged"},keyBindings:{up:"_onUpKey",down:"_onDownKey",esc:"_onEscKey","shift+tab:keydown":"_onShiftTabDown"},attached:function(){this._resetTabindices()},select:function(value){if(this._defaultFocusAsync){this.cancelAsync(this._defaultFocusAsync);this._defaultFocusAsync=null}var item=this._valueToItem(value);if(item&&item.hasAttribute("disabled"))return;this._setFocusedItem(item);Polymer.IronMultiSelectableBehaviorImpl.select.apply(this,arguments)},_resetTabindices:function(){var selectedItem=this.multi?this.selectedItems&&this.selectedItems[0]:this.selectedItem;this.items.forEach(function(item){item.setAttribute("tabindex",item===selectedItem?"0":"-1")},this)},_updateMultiselectable:function(multi){if(multi){this.setAttribute("aria-multiselectable","true")}else{this.removeAttribute("aria-multiselectable")}},_focusWithKeyboardEvent:function(event){for(var i=0,item;item=this.items[i];i++){var attr=this.attrForItemTitle||"textContent";var title=item[attr]||item.getAttribute(attr);if(!item.hasAttribute("disabled")&&title&&title.trim().charAt(0).toLowerCase()===String.fromCharCode(event.keyCode).toLowerCase()){this._setFocusedItem(item);break}}},_focusPrevious:function(){var length=this.items.length;var curFocusIndex=Number(this.indexOf(this.focusedItem));for(var i=1;i<length+1;i++){var item=this.items[(curFocusIndex-i+length)%length];if(!item.hasAttribute("disabled")){var owner=Polymer.dom(item).getOwnerRoot()||document;this._setFocusedItem(item);if(Polymer.dom(owner).activeElement==item){return}}}},_focusNext:function(){var length=this.items.length;var curFocusIndex=Number(this.indexOf(this.focusedItem));for(var i=1;i<length+1;i++){var item=this.items[(curFocusIndex+i)%length];if(!item.hasAttribute("disabled")){var owner=Polymer.dom(item).getOwnerRoot()||document;this._setFocusedItem(item);if(Polymer.dom(owner).activeElement==item){return}}}},_applySelection:function(item,isSelected){if(isSelected){item.setAttribute("aria-selected","true")}else{item.removeAttribute("aria-selected")}Polymer.IronSelectableBehavior._applySelection.apply(this,arguments)},_focusedItemChanged:function(focusedItem,old){old&&old.setAttribute("tabindex","-1");if(focusedItem){focusedItem.setAttribute("tabindex","0");focusedItem.focus()}},_onIronItemsChanged:function(event){if(event.detail.addedNodes.length){this._resetTabindices()}},_onShiftTabDown:function(event){var oldTabIndex=this.getAttribute("tabindex");Polymer.IronMenuBehaviorImpl._shiftTabPressed=true;this._setFocusedItem(null);this.setAttribute("tabindex","-1");this.async(function(){this.setAttribute("tabindex",oldTabIndex);Polymer.IronMenuBehaviorImpl._shiftTabPressed=false},1)},_onFocus:function(event){if(Polymer.IronMenuBehaviorImpl._shiftTabPressed){return}var rootTarget=Polymer.dom(event).rootTarget;if(rootTarget!==this&&typeof rootTarget.tabIndex!=="undefined"&&!this.isLightDescendant(rootTarget)){return}this._defaultFocusAsync=this.async(function(){var selectedItem=this.multi?this.selectedItems&&this.selectedItems[0]:this.selectedItem;this._setFocusedItem(null);if(selectedItem){this._setFocusedItem(selectedItem)}else if(this.items[0]){this._focusNext()}})},_onUpKey:function(event){this._focusPrevious();event.detail.keyboardEvent.preventDefault()},_onDownKey:function(event){this._focusNext();event.detail.keyboardEvent.preventDefault()},_onEscKey:function(event){this.focusedItem.blur()},_onKeydown:function(event){if(!this.keyboardEventMatchesKeys(event,"up down esc")){this._focusWithKeyboardEvent(event)}event.stopPropagation()},_activateHandler:function(event){Polymer.IronSelectableBehavior._activateHandler.call(this,event);event.stopPropagation()}};Polymer.IronMenuBehaviorImpl._shiftTabPressed=false;Polymer.IronMenuBehavior=[Polymer.IronMultiSelectableBehavior,Polymer.IronA11yKeysBehavior,Polymer.IronMenuBehaviorImpl];(function(){Polymer({is:"paper-menu",behaviors:[Polymer.IronMenuBehavior]})})();Polymer.IronFitBehavior={properties:{sizingTarget:{type:Object,value:function(){return this}},fitInto:{type:Object,value:window},noOverlap:{type:Boolean},positionTarget:{type:Element},horizontalAlign:{type:String},verticalAlign:{type:String},dynamicAlign:{type:Boolean},horizontalOffset:{type:Number,value:0,notify:true},verticalOffset:{type:Number,value:0,notify:true},autoFitOnAttach:{type:Boolean,value:false},_fitInfo:{type:Object}},get _fitWidth(){var fitWidth;if(this.fitInto===window){fitWidth=this.fitInto.innerWidth}else{fitWidth=this.fitInto.getBoundingClientRect().width}return fitWidth},get _fitHeight(){var fitHeight;if(this.fitInto===window){fitHeight=this.fitInto.innerHeight}else{fitHeight=this.fitInto.getBoundingClientRect().height}return fitHeight},get _fitLeft(){var fitLeft;if(this.fitInto===window){fitLeft=0}else{fitLeft=this.fitInto.getBoundingClientRect().left}return fitLeft},get _fitTop(){var fitTop;if(this.fitInto===window){fitTop=0}else{fitTop=this.fitInto.getBoundingClientRect().top}return fitTop},get _defaultPositionTarget(){var parent=Polymer.dom(this).parentNode;if(parent&&parent.nodeType===Node.DOCUMENT_FRAGMENT_NODE){parent=parent.host}return parent},get _localeHorizontalAlign(){if(this._isRTL){if(this.horizontalAlign==="right"){return"left"}if(this.horizontalAlign==="left"){return"right"}}return this.horizontalAlign},attached:function(){this._isRTL=window.getComputedStyle(this).direction=="rtl";this.positionTarget=this.positionTarget||this._defaultPositionTarget;if(this.autoFitOnAttach){if(window.getComputedStyle(this).display==="none"){setTimeout(function(){this.fit()}.bind(this))}else{this.fit()}}},fit:function(){this.position();this.constrain();this.center()},_discoverInfo:function(){if(this._fitInfo){return}var target=window.getComputedStyle(this);var sizer=window.getComputedStyle(this.sizingTarget);this._fitInfo={inlineStyle:{top:this.style.top||"",left:this.style.left||"",position:this.style.position||""},sizerInlineStyle:{maxWidth:this.sizingTarget.style.maxWidth||"",maxHeight:this.sizingTarget.style.maxHeight||"",boxSizing:this.sizingTarget.style.boxSizing||""},positionedBy:{vertically:target.top!=="auto"?"top":target.bottom!=="auto"?"bottom":null,horizontally:target.left!=="auto"?"left":target.right!=="auto"?"right":null},sizedBy:{height:sizer.maxHeight!=="none",width:sizer.maxWidth!=="none",minWidth:parseInt(sizer.minWidth,10)||0,minHeight:parseInt(sizer.minHeight,10)||0},margin:{top:parseInt(target.marginTop,10)||0,right:parseInt(target.marginRight,10)||0,bottom:parseInt(target.marginBottom,10)||0,left:parseInt(target.marginLeft,10)||0}};if(this.verticalOffset){this._fitInfo.margin.top=this._fitInfo.margin.bottom=this.verticalOffset;this._fitInfo.inlineStyle.marginTop=this.style.marginTop||"";this._fitInfo.inlineStyle.marginBottom=this.style.marginBottom||"";this.style.marginTop=this.style.marginBottom=this.verticalOffset+"px"}if(this.horizontalOffset){this._fitInfo.margin.left=this._fitInfo.margin.right=this.horizontalOffset;this._fitInfo.inlineStyle.marginLeft=this.style.marginLeft||"";this._fitInfo.inlineStyle.marginRight=this.style.marginRight||"";this.style.marginLeft=this.style.marginRight=this.horizontalOffset+"px"}},resetFit:function(){var info=this._fitInfo||{};for(var property in info.sizerInlineStyle){this.sizingTarget.style[property]=info.sizerInlineStyle[property]}for(var property in info.inlineStyle){this.style[property]=info.inlineStyle[property]}this._fitInfo=null},refit:function(){var scrollLeft=this.sizingTarget.scrollLeft;var scrollTop=this.sizingTarget.scrollTop;this.resetFit();this.fit();this.sizingTarget.scrollLeft=scrollLeft;this.sizingTarget.scrollTop=scrollTop},position:function(){if(!this.horizontalAlign&&!this.verticalAlign){return}this._discoverInfo();this.style.position="fixed";this.sizingTarget.style.boxSizing="border-box";this.style.left="0px";this.style.top="0px";var rect=this.getBoundingClientRect();var positionRect=this.__getNormalizedRect(this.positionTarget);var fitRect=this.__getNormalizedRect(this.fitInto);var margin=this._fitInfo.margin;var size={width:rect.width+margin.left+margin.right,height:rect.height+margin.top+margin.bottom};var position=this.__getPosition(this._localeHorizontalAlign,this.verticalAlign,size,positionRect,fitRect);var left=position.left+margin.left;var top=position.top+margin.top;var right=Math.min(fitRect.right-margin.right,left+rect.width);var bottom=Math.min(fitRect.bottom-margin.bottom,top+rect.height);var minWidth=this._fitInfo.sizedBy.minWidth;var minHeight=this._fitInfo.sizedBy.minHeight;if(left<margin.left){left=margin.left;if(right-left<minWidth){left=right-minWidth}}if(top<margin.top){top=margin.top;if(bottom-top<minHeight){top=bottom-minHeight}}this.sizingTarget.style.maxWidth=right-left+"px";this.sizingTarget.style.maxHeight=bottom-top+"px";this.style.left=left-rect.left+"px";this.style.top=top-rect.top+"px"},constrain:function(){if(this.horizontalAlign||this.verticalAlign){return}this._discoverInfo();var info=this._fitInfo;if(!info.positionedBy.vertically){this.style.position="fixed";this.style.top="0px"}if(!info.positionedBy.horizontally){this.style.position="fixed";this.style.left="0px"}this.sizingTarget.style.boxSizing="border-box";var rect=this.getBoundingClientRect();if(!info.sizedBy.height){this.__sizeDimension(rect,info.positionedBy.vertically,"top","bottom","Height")}if(!info.sizedBy.width){this.__sizeDimension(rect,info.positionedBy.horizontally,"left","right","Width")}},_sizeDimension:function(rect,positionedBy,start,end,extent){this.__sizeDimension(rect,positionedBy,start,end,extent)},__sizeDimension:function(rect,positionedBy,start,end,extent){var info=this._fitInfo;var fitRect=this.__getNormalizedRect(this.fitInto);var max=extent==="Width"?fitRect.width:fitRect.height;var flip=positionedBy===end;var offset=flip?max-rect[end]:rect[start];var margin=info.margin[flip?start:end];var offsetExtent="offset"+extent;var sizingOffset=this[offsetExtent]-this.sizingTarget[offsetExtent];this.sizingTarget.style["max"+extent]=max-margin-offset-sizingOffset+"px"},center:function(){if(this.horizontalAlign||this.verticalAlign){return}this._discoverInfo();var positionedBy=this._fitInfo.positionedBy;if(positionedBy.vertically&&positionedBy.horizontally){return}this.style.position="fixed";if(!positionedBy.vertically){this.style.top="0px"}if(!positionedBy.horizontally){this.style.left="0px"}var rect=this.getBoundingClientRect();var fitRect=this.__getNormalizedRect(this.fitInto);if(!positionedBy.vertically){var top=fitRect.top-rect.top+(fitRect.height-rect.height)/2;this.style.top=top+"px"}if(!positionedBy.horizontally){var left=fitRect.left-rect.left+(fitRect.width-rect.width)/2;this.style.left=left+"px"}},__getNormalizedRect:function(target){if(target===document.documentElement||target===window){return{top:0,left:0,width:window.innerWidth,height:window.innerHeight,right:window.innerWidth,bottom:window.innerHeight}}return target.getBoundingClientRect()},__getCroppedArea:function(position,size,fitRect){var verticalCrop=Math.min(0,position.top)+Math.min(0,fitRect.bottom-(position.top+size.height));var horizontalCrop=Math.min(0,position.left)+Math.min(0,fitRect.right-(position.left+size.width));return Math.abs(verticalCrop)*size.width+Math.abs(horizontalCrop)*size.height},__getPosition:function(hAlign,vAlign,size,positionRect,fitRect){var positions=[{verticalAlign:"top",horizontalAlign:"left",top:positionRect.top,left:positionRect.left},{verticalAlign:"top",horizontalAlign:"right",top:positionRect.top,left:positionRect.right-size.width},{verticalAlign:"bottom",horizontalAlign:"left",top:positionRect.bottom-size.height,left:positionRect.left},{verticalAlign:"bottom",horizontalAlign:"right",top:positionRect.bottom-size.height,left:positionRect.right-size.width}];if(this.noOverlap){for(var i=0,l=positions.length;i<l;i++){var copy={};for(var key in positions[i]){copy[key]=positions[i][key]}positions.push(copy)}positions[0].top=positions[1].top+=positionRect.height;positions[2].top=positions[3].top-=positionRect.height;positions[4].left=positions[6].left+=positionRect.width;positions[5].left=positions[7].left-=positionRect.width}vAlign=vAlign==="auto"?null:vAlign;hAlign=hAlign==="auto"?null:hAlign;var position;for(var i=0;i<positions.length;i++){var pos=positions[i];if(!this.dynamicAlign&&!this.noOverlap&&pos.verticalAlign===vAlign&&pos.horizontalAlign===hAlign){position=pos;break}var alignOk=(!vAlign||pos.verticalAlign===vAlign)&&(!hAlign||pos.horizontalAlign===hAlign);if(!this.dynamicAlign&&!alignOk){continue}position=position||pos;pos.croppedArea=this.__getCroppedArea(pos,size,fitRect);var diff=pos.croppedArea-position.croppedArea;if(diff<0||diff===0&&alignOk){position=pos}if(position.croppedArea===0&&alignOk){break}}return position}};(function(){"use strict";Polymer({is:"iron-overlay-backdrop",properties:{opened:{reflectToAttribute:true,type:Boolean,value:false,observer:"_openedChanged"}},listeners:{transitionend:"_onTransitionend"},created:function(){this.__openedRaf=null},attached:function(){this.opened&&this._openedChanged(this.opened)},prepare:function(){if(this.opened&&!this.parentNode){Polymer.dom(document.body).appendChild(this)}},open:function(){this.opened=true},close:function(){this.opened=false},complete:function(){if(!this.opened&&this.parentNode===document.body){Polymer.dom(this.parentNode).removeChild(this)}},_onTransitionend:function(event){if(event&&event.target===this){this.complete()}},_openedChanged:function(opened){if(opened){this.prepare()}else{var cs=window.getComputedStyle(this);if(cs.transitionDuration==="0s"||cs.opacity==0){this.complete()}}if(!this.isAttached){return}if(this.__openedRaf){window.cancelAnimationFrame(this.__openedRaf);this.__openedRaf=null}this.scrollTop=this.scrollTop;this.__openedRaf=window.requestAnimationFrame(function(){this.__openedRaf=null;this.toggleClass("opened",this.opened)}.bind(this))}})})();Polymer.IronOverlayManagerClass=function(){this._overlays=[];this._minimumZ=101;this._backdropElement=null;Polymer.Gestures.add(document,"tap",this._onCaptureClick.bind(this));document.addEventListener("focus",this._onCaptureFocus.bind(this),true);document.addEventListener("keydown",this._onCaptureKeyDown.bind(this),true)};Polymer.IronOverlayManagerClass.prototype={constructor:Polymer.IronOverlayManagerClass,get backdropElement(){if(!this._backdropElement){this._backdropElement=document.createElement("iron-overlay-backdrop")}return this._backdropElement},get deepActiveElement(){var active=document.activeElement||document.body;while(active.root&&Polymer.dom(active.root).activeElement){active=Polymer.dom(active.root).activeElement}return active},_bringOverlayAtIndexToFront:function(i){var overlay=this._overlays[i];if(!overlay){return}var lastI=this._overlays.length-1;var currentOverlay=this._overlays[lastI];if(currentOverlay&&this._shouldBeBehindOverlay(overlay,currentOverlay)){lastI--}if(i>=lastI){return}var minimumZ=Math.max(this.currentOverlayZ(),this._minimumZ);if(this._getZ(overlay)<=minimumZ){this._applyOverlayZ(overlay,minimumZ)}while(i<lastI){this._overlays[i]=this._overlays[i+1];i++}this._overlays[lastI]=overlay},addOrRemoveOverlay:function(overlay){if(overlay.opened){this.addOverlay(overlay)}else{this.removeOverlay(overlay)}},addOverlay:function(overlay){var i=this._overlays.indexOf(overlay);if(i>=0){this._bringOverlayAtIndexToFront(i);this.trackBackdrop();return}var insertionIndex=this._overlays.length;var currentOverlay=this._overlays[insertionIndex-1];var minimumZ=Math.max(this._getZ(currentOverlay),this._minimumZ);var newZ=this._getZ(overlay);if(currentOverlay&&this._shouldBeBehindOverlay(overlay,currentOverlay)){this._applyOverlayZ(currentOverlay,minimumZ);insertionIndex--;var previousOverlay=this._overlays[insertionIndex-1];minimumZ=Math.max(this._getZ(previousOverlay),this._minimumZ)}if(newZ<=minimumZ){this._applyOverlayZ(overlay,minimumZ)}this._overlays.splice(insertionIndex,0,overlay);this.trackBackdrop()},removeOverlay:function(overlay){var i=this._overlays.indexOf(overlay);if(i===-1){return}this._overlays.splice(i,1);this.trackBackdrop()},currentOverlay:function(){var i=this._overlays.length-1;return this._overlays[i]},currentOverlayZ:function(){return this._getZ(this.currentOverlay())},ensureMinimumZ:function(minimumZ){this._minimumZ=Math.max(this._minimumZ,minimumZ)},focusOverlay:function(){var current=this.currentOverlay();if(current){current._applyFocus()}},trackBackdrop:function(){var overlay=this._overlayWithBackdrop();if(!overlay&&!this._backdropElement){return}this.backdropElement.style.zIndex=this._getZ(overlay)-1;this.backdropElement.opened=!!overlay},getBackdrops:function(){var backdrops=[];for(var i=0;i<this._overlays.length;i++){if(this._overlays[i].withBackdrop){backdrops.push(this._overlays[i])}}return backdrops},backdropZ:function(){return this._getZ(this._overlayWithBackdrop())-1},_overlayWithBackdrop:function(){for(var i=0;i<this._overlays.length;i++){if(this._overlays[i].withBackdrop){return this._overlays[i]}}},_getZ:function(overlay){var z=this._minimumZ;if(overlay){var z1=Number(overlay.style.zIndex||window.getComputedStyle(overlay).zIndex);if(z1===z1){z=z1}}return z},_setZ:function(element,z){element.style.zIndex=z},_applyOverlayZ:function(overlay,aboveZ){this._setZ(overlay,aboveZ+2)},_overlayInPath:function(path){path=path||[];for(var i=0;i<path.length;i++){if(path[i]._manager===this){return path[i]}}},_onCaptureClick:function(event){var overlay=this.currentOverlay();if(overlay&&this._overlayInPath(Polymer.dom(event).path)!==overlay){overlay._onCaptureClick(event)}},_onCaptureFocus:function(event){var overlay=this.currentOverlay();if(overlay){overlay._onCaptureFocus(event)}},_onCaptureKeyDown:function(event){var overlay=this.currentOverlay();if(overlay){if(Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event,"esc")){overlay._onCaptureEsc(event)}else if(Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event,"tab")){overlay._onCaptureTab(event)}}},_shouldBeBehindOverlay:function(overlay1,overlay2){return!overlay1.alwaysOnTop&&overlay2.alwaysOnTop}};Polymer.IronOverlayManager=new Polymer.IronOverlayManagerClass;(function(){"use strict";var p=Element.prototype;var matches=p.matches||p.matchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector||p.webkitMatchesSelector;Polymer.IronFocusablesHelper={getTabbableNodes:function(node){var result=[];var needsSortByTabIndex=this._collectTabbableNodes(node,result);if(needsSortByTabIndex){return this._sortByTabIndex(result)}return result},isFocusable:function(element){if(matches.call(element,"input, select, textarea, button, object")){
-return matches.call(element,":not([disabled])")}return matches.call(element,"a[href], area[href], iframe, [tabindex], [contentEditable]")},isTabbable:function(element){return this.isFocusable(element)&&matches.call(element,':not([tabindex="-1"])')&&this._isVisible(element)},_normalizedTabIndex:function(element){if(this.isFocusable(element)){var tabIndex=element.getAttribute("tabindex")||0;return Number(tabIndex)}return-1},_collectTabbableNodes:function(node,result){if(node.nodeType!==Node.ELEMENT_NODE||!this._isVisible(node)){return false}var element=node;var tabIndex=this._normalizedTabIndex(element);var needsSortByTabIndex=tabIndex>0;if(tabIndex>=0){result.push(element)}var children;if(element.localName==="content"){children=Polymer.dom(element).getDistributedNodes()}else{children=Polymer.dom(element.root||element).children}for(var i=0;i<children.length;i++){var needsSort=this._collectTabbableNodes(children[i],result);needsSortByTabIndex=needsSortByTabIndex||needsSort}return needsSortByTabIndex},_isVisible:function(element){var style=element.style;if(style.visibility!=="hidden"&&style.display!=="none"){style=window.getComputedStyle(element);return style.visibility!=="hidden"&&style.display!=="none"}return false},_sortByTabIndex:function(tabbables){var len=tabbables.length;if(len<2){return tabbables}var pivot=Math.ceil(len/2);var left=this._sortByTabIndex(tabbables.slice(0,pivot));var right=this._sortByTabIndex(tabbables.slice(pivot));return this._mergeSortByTabIndex(left,right)},_mergeSortByTabIndex:function(left,right){var result=[];while(left.length>0&&right.length>0){if(this._hasLowerTabOrder(left[0],right[0])){result.push(right.shift())}else{result.push(left.shift())}}return result.concat(left,right)},_hasLowerTabOrder:function(a,b){var ati=Math.max(a.tabIndex,0);var bti=Math.max(b.tabIndex,0);return ati===0||bti===0?bti>ati:ati>bti}}})();(function(){"use strict";Polymer.IronOverlayBehaviorImpl={properties:{opened:{observer:"_openedChanged",type:Boolean,value:false,notify:true},canceled:{observer:"_canceledChanged",readOnly:true,type:Boolean,value:false},withBackdrop:{observer:"_withBackdropChanged",type:Boolean},noAutoFocus:{type:Boolean,value:false},noCancelOnEscKey:{type:Boolean,value:false},noCancelOnOutsideClick:{type:Boolean,value:false},closingReason:{type:Object},restoreFocusOnClose:{type:Boolean,value:false},alwaysOnTop:{type:Boolean},_manager:{type:Object,value:Polymer.IronOverlayManager},_focusedChild:{type:Object}},listeners:{"iron-resize":"_onIronResize"},get backdropElement(){return this._manager.backdropElement},get _focusNode(){return this._focusedChild||Polymer.dom(this).querySelector("[autofocus]")||this},get _focusableNodes(){return Polymer.IronFocusablesHelper.getTabbableNodes(this)},ready:function(){this.__isAnimating=false;this.__shouldRemoveTabIndex=false;this.__firstFocusableNode=this.__lastFocusableNode=null;this.__raf=null;this.__restoreFocusNode=null;this._ensureSetup()},attached:function(){if(this.opened){this._openedChanged(this.opened)}this._observer=Polymer.dom(this).observeNodes(this._onNodesChange)},detached:function(){Polymer.dom(this).unobserveNodes(this._observer);this._observer=null;if(this.__raf){window.cancelAnimationFrame(this.__raf);this.__raf=null}this._manager.removeOverlay(this)},toggle:function(){this._setCanceled(false);this.opened=!this.opened},open:function(){this._setCanceled(false);this.opened=true},close:function(){this._setCanceled(false);this.opened=false},cancel:function(event){var cancelEvent=this.fire("iron-overlay-canceled",event,{cancelable:true});if(cancelEvent.defaultPrevented){return}this._setCanceled(true);this.opened=false},invalidateTabbables:function(){this.__firstFocusableNode=this.__lastFocusableNode=null},_ensureSetup:function(){if(this._overlaySetup){return}this._overlaySetup=true;this.style.outline="none";this.style.display="none"},_openedChanged:function(opened){if(opened){this.removeAttribute("aria-hidden")}else{this.setAttribute("aria-hidden","true")}if(!this.isAttached){return}this.__isAnimating=true;this.__onNextAnimationFrame(this.__openedChanged)},_canceledChanged:function(){this.closingReason=this.closingReason||{};this.closingReason.canceled=this.canceled},_withBackdropChanged:function(){if(this.withBackdrop&&!this.hasAttribute("tabindex")){this.setAttribute("tabindex","-1");this.__shouldRemoveTabIndex=true}else if(this.__shouldRemoveTabIndex){this.removeAttribute("tabindex");this.__shouldRemoveTabIndex=false}if(this.opened&&this.isAttached){this._manager.trackBackdrop()}},_prepareRenderOpened:function(){this.__restoreFocusNode=this._manager.deepActiveElement;this._preparePositioning();this.refit();this._finishPositioning();if(this.noAutoFocus&&document.activeElement===this._focusNode){this._focusNode.blur();this.__restoreFocusNode.focus()}},_renderOpened:function(){this._finishRenderOpened()},_renderClosed:function(){this._finishRenderClosed()},_finishRenderOpened:function(){this.notifyResize();this.__isAnimating=false;this.fire("iron-overlay-opened")},_finishRenderClosed:function(){this.style.display="none";this.style.zIndex="";this.notifyResize();this.__isAnimating=false;this.fire("iron-overlay-closed",this.closingReason)},_preparePositioning:function(){this.style.transition=this.style.webkitTransition="none";this.style.transform=this.style.webkitTransform="none";this.style.display=""},_finishPositioning:function(){this.style.display="none";this.scrollTop=this.scrollTop;this.style.transition=this.style.webkitTransition="";this.style.transform=this.style.webkitTransform="";this.style.display="";this.scrollTop=this.scrollTop},_applyFocus:function(){if(this.opened){if(!this.noAutoFocus){this._focusNode.focus()}}else{this._focusNode.blur();this._focusedChild=null;if(this.restoreFocusOnClose&&this.__restoreFocusNode){this.__restoreFocusNode.focus()}this.__restoreFocusNode=null;var currentOverlay=this._manager.currentOverlay();if(currentOverlay&&this!==currentOverlay){currentOverlay._applyFocus()}}},_onCaptureClick:function(event){if(!this.noCancelOnOutsideClick){this.cancel(event)}},_onCaptureFocus:function(event){if(!this.withBackdrop){return}var path=Polymer.dom(event).path;if(path.indexOf(this)===-1){event.stopPropagation();this._applyFocus()}else{this._focusedChild=path[0]}},_onCaptureEsc:function(event){if(!this.noCancelOnEscKey){this.cancel(event)}},_onCaptureTab:function(event){if(!this.withBackdrop){return}this.__ensureFirstLastFocusables();var shift=event.shiftKey;var nodeToCheck=shift?this.__firstFocusableNode:this.__lastFocusableNode;var nodeToSet=shift?this.__lastFocusableNode:this.__firstFocusableNode;var shouldWrap=false;if(nodeToCheck===nodeToSet){shouldWrap=true}else{var focusedNode=this._manager.deepActiveElement;shouldWrap=focusedNode===nodeToCheck||focusedNode===this}if(shouldWrap){event.preventDefault();this._focusedChild=nodeToSet;this._applyFocus()}},_onIronResize:function(){if(this.opened&&!this.__isAnimating){this.__onNextAnimationFrame(this.refit)}},_onNodesChange:function(){if(this.opened&&!this.__isAnimating){this.invalidateTabbables();this.notifyResize()}},__ensureFirstLastFocusables:function(){if(!this.__firstFocusableNode||!this.__lastFocusableNode){var focusableNodes=this._focusableNodes;this.__firstFocusableNode=focusableNodes[0];this.__lastFocusableNode=focusableNodes[focusableNodes.length-1]}},__openedChanged:function(){if(this.opened){this._prepareRenderOpened();this._manager.addOverlay(this);this._applyFocus();this._renderOpened()}else{this._manager.removeOverlay(this);this._applyFocus();this._renderClosed()}},__onNextAnimationFrame:function(callback){if(this.__raf){window.cancelAnimationFrame(this.__raf)}var self=this;this.__raf=window.requestAnimationFrame(function nextAnimationFrame(){self.__raf=null;callback.call(self)})}};Polymer.IronOverlayBehavior=[Polymer.IronFitBehavior,Polymer.IronResizableBehavior,Polymer.IronOverlayBehaviorImpl]})();Polymer.NeonAnimatableBehavior={properties:{animationConfig:{type:Object},entryAnimation:{observer:"_entryAnimationChanged",type:String},exitAnimation:{observer:"_exitAnimationChanged",type:String}},_entryAnimationChanged:function(){this.animationConfig=this.animationConfig||{};this.animationConfig["entry"]=[{name:this.entryAnimation,node:this}]},_exitAnimationChanged:function(){this.animationConfig=this.animationConfig||{};this.animationConfig["exit"]=[{name:this.exitAnimation,node:this}]},_copyProperties:function(config1,config2){for(var property in config2){config1[property]=config2[property]}},_cloneConfig:function(config){var clone={isClone:true};this._copyProperties(clone,config);return clone},_getAnimationConfigRecursive:function(type,map,allConfigs){if(!this.animationConfig){return}if(this.animationConfig.value&&typeof this.animationConfig.value==="function"){this._warn(this._logf("playAnimation","Please put 'animationConfig' inside of your components 'properties' object instead of outside of it."));return}var thisConfig;if(type){thisConfig=this.animationConfig[type]}else{thisConfig=this.animationConfig}if(!Array.isArray(thisConfig)){thisConfig=[thisConfig]}if(thisConfig){for(var config,index=0;config=thisConfig[index];index++){if(config.animatable){config.animatable._getAnimationConfigRecursive(config.type||type,map,allConfigs)}else{if(config.id){var cachedConfig=map[config.id];if(cachedConfig){if(!cachedConfig.isClone){map[config.id]=this._cloneConfig(cachedConfig);cachedConfig=map[config.id]}this._copyProperties(cachedConfig,config)}else{map[config.id]=config}}else{allConfigs.push(config)}}}}},getAnimationConfig:function(type){var map={};var allConfigs=[];this._getAnimationConfigRecursive(type,map,allConfigs);for(var key in map){allConfigs.push(map[key])}return allConfigs}};Polymer.NeonAnimationRunnerBehaviorImpl={_configureAnimations:function(configs){var results=[];if(configs.length>0){for(var config,index=0;config=configs[index];index++){var neonAnimation=document.createElement(config.name);if(neonAnimation.isNeonAnimation){var result=null;try{result=neonAnimation.configure(config);if(typeof result.cancel!="function"){result=document.timeline.play(result)}}catch(e){result=null;console.warn("Couldnt play","(",config.name,").",e)}if(result){results.push({neonAnimation:neonAnimation,config:config,animation:result})}}else{console.warn(this.is+":",config.name,"not found!")}}}return results},_shouldComplete:function(activeEntries){var finished=true;for(var i=0;i<activeEntries.length;i++){if(activeEntries[i].animation.playState!="finished"){finished=false;break}}return finished},_complete:function(activeEntries){for(var i=0;i<activeEntries.length;i++){activeEntries[i].neonAnimation.complete(activeEntries[i].config)}for(var i=0;i<activeEntries.length;i++){activeEntries[i].animation.cancel()}},playAnimation:function(type,cookie){var configs=this.getAnimationConfig(type);if(!configs){return}this._active=this._active||{};if(this._active[type]){this._complete(this._active[type]);delete this._active[type]}var activeEntries=this._configureAnimations(configs);if(activeEntries.length==0){this.fire("neon-animation-finish",cookie,{bubbles:false});return}this._active[type]=activeEntries;for(var i=0;i<activeEntries.length;i++){activeEntries[i].animation.onfinish=function(){if(this._shouldComplete(activeEntries)){this._complete(activeEntries);delete this._active[type];this.fire("neon-animation-finish",cookie,{bubbles:false})}}.bind(this)}},cancelAnimation:function(){for(var k in this._animations){this._animations[k].cancel()}this._animations={}}};Polymer.NeonAnimationRunnerBehavior=[Polymer.NeonAnimatableBehavior,Polymer.NeonAnimationRunnerBehaviorImpl];Polymer.NeonAnimationBehavior={properties:{animationTiming:{type:Object,value:function(){return{duration:500,easing:"cubic-bezier(0.4, 0, 0.2, 1)",fill:"both"}}}},isNeonAnimation:true,timingFromConfig:function(config){if(config.timing){for(var property in config.timing){this.animationTiming[property]=config.timing[property]}}return this.animationTiming},setPrefixedProperty:function(node,property,value){var map={transform:["webkitTransform"],transformOrigin:["mozTransformOrigin","webkitTransformOrigin"]};var prefixes=map[property];for(var prefix,index=0;prefix=prefixes[index];index++){node.style[prefix]=value}node.style[property]=value},complete:function(){}};Polymer({is:"opaque-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;this._effect=new KeyframeEffect(node,[{opacity:"1"},{opacity:"1"}],this.timingFromConfig(config));node.style.opacity="0";return this._effect},complete:function(config){config.node.style.opacity=""}});(function(){"use strict";var LAST_TOUCH_POSITION={pageX:0,pageY:0};var ROOT_TARGET=null;var SCROLLABLE_NODES=[];Polymer.IronDropdownScrollManager={get currentLockingElement(){return this._lockingElements[this._lockingElements.length-1]},elementIsScrollLocked:function(element){var currentLockingElement=this.currentLockingElement;if(currentLockingElement===undefined)return false;var scrollLocked;if(this._hasCachedLockedElement(element)){return true}if(this._hasCachedUnlockedElement(element)){return false}scrollLocked=!!currentLockingElement&&currentLockingElement!==element&&!this._composedTreeContains(currentLockingElement,element);if(scrollLocked){this._lockedElementCache.push(element)}else{this._unlockedElementCache.push(element)}return scrollLocked},pushScrollLock:function(element){if(this._lockingElements.indexOf(element)>=0){return}if(this._lockingElements.length===0){this._lockScrollInteractions()}this._lockingElements.push(element);this._lockedElementCache=[];this._unlockedElementCache=[]},removeScrollLock:function(element){var index=this._lockingElements.indexOf(element);if(index===-1){return}this._lockingElements.splice(index,1);this._lockedElementCache=[];this._unlockedElementCache=[];if(this._lockingElements.length===0){this._unlockScrollInteractions()}},_lockingElements:[],_lockedElementCache:null,_unlockedElementCache:null,_hasCachedLockedElement:function(element){return this._lockedElementCache.indexOf(element)>-1},_hasCachedUnlockedElement:function(element){return this._unlockedElementCache.indexOf(element)>-1},_composedTreeContains:function(element,child){var contentElements;var distributedNodes;var contentIndex;var nodeIndex;if(element.contains(child)){return true}contentElements=Polymer.dom(element).querySelectorAll("content");for(contentIndex=0;contentIndex<contentElements.length;++contentIndex){distributedNodes=Polymer.dom(contentElements[contentIndex]).getDistributedNodes();for(nodeIndex=0;nodeIndex<distributedNodes.length;++nodeIndex){if(this._composedTreeContains(distributedNodes[nodeIndex],child)){return true}}}return false},_scrollInteractionHandler:function(event){if(event.cancelable&&this._shouldPreventScrolling(event)){event.preventDefault()}if(event.targetTouches){var touch=event.targetTouches[0];LAST_TOUCH_POSITION.pageX=touch.pageX;LAST_TOUCH_POSITION.pageY=touch.pageY}},_lockScrollInteractions:function(){this._boundScrollHandler=this._boundScrollHandler||this._scrollInteractionHandler.bind(this);document.addEventListener("wheel",this._boundScrollHandler,true);document.addEventListener("mousewheel",this._boundScrollHandler,true);document.addEventListener("DOMMouseScroll",this._boundScrollHandler,true);document.addEventListener("touchstart",this._boundScrollHandler,true);document.addEventListener("touchmove",this._boundScrollHandler,true)},_unlockScrollInteractions:function(){document.removeEventListener("wheel",this._boundScrollHandler,true);document.removeEventListener("mousewheel",this._boundScrollHandler,true);document.removeEventListener("DOMMouseScroll",this._boundScrollHandler,true);document.removeEventListener("touchstart",this._boundScrollHandler,true);document.removeEventListener("touchmove",this._boundScrollHandler,true)},_shouldPreventScrolling:function(event){var target=Polymer.dom(event).rootTarget;if(event.type!=="touchmove"&&ROOT_TARGET!==target){ROOT_TARGET=target;SCROLLABLE_NODES=this._getScrollableNodes(Polymer.dom(event).path)}if(!SCROLLABLE_NODES.length){return true}if(event.type==="touchstart"){return false}var info=this._getScrollInfo(event);return!this._getScrollingNode(SCROLLABLE_NODES,info.deltaX,info.deltaY)},_getScrollableNodes:function(nodes){var scrollables=[];var lockingIndex=nodes.indexOf(this.currentLockingElement);for(var i=0;i<=lockingIndex;i++){var node=nodes[i];if(node.nodeType===11){continue}var style=node.style;if(style.overflow!=="scroll"&&style.overflow!=="auto"){style=window.getComputedStyle(node)}if(style.overflow==="scroll"||style.overflow==="auto"){scrollables.push(node)}}return scrollables},_getScrollingNode:function(nodes,deltaX,deltaY){if(!deltaX&&!deltaY){return}var verticalScroll=Math.abs(deltaY)>=Math.abs(deltaX);for(var i=0;i<nodes.length;i++){var node=nodes[i];var canScroll=false;if(verticalScroll){canScroll=deltaY<0?node.scrollTop>0:node.scrollTop<node.scrollHeight-node.clientHeight}else{canScroll=deltaX<0?node.scrollLeft>0:node.scrollLeft<node.scrollWidth-node.clientWidth}if(canScroll){return node}}},_getScrollInfo:function(event){var info={deltaX:event.deltaX,deltaY:event.deltaY};if("deltaX"in event){}else if("wheelDeltaX"in event){info.deltaX=-event.wheelDeltaX;info.deltaY=-event.wheelDeltaY}else if("axis"in event){info.deltaX=event.axis===1?event.detail:0;info.deltaY=event.axis===2?event.detail:0}else if(event.targetTouches){var touch=event.targetTouches[0];info.deltaX=LAST_TOUCH_POSITION.pageX-touch.pageX;info.deltaY=LAST_TOUCH_POSITION.pageY-touch.pageY}return info}}})();(function(){"use strict";Polymer({is:"iron-dropdown",behaviors:[Polymer.IronControlState,Polymer.IronA11yKeysBehavior,Polymer.IronOverlayBehavior,Polymer.NeonAnimationRunnerBehavior],properties:{horizontalAlign:{type:String,value:"left",reflectToAttribute:true},verticalAlign:{type:String,value:"top",reflectToAttribute:true},openAnimationConfig:{type:Object},closeAnimationConfig:{type:Object},focusTarget:{type:Object},noAnimations:{type:Boolean,value:false},allowOutsideScroll:{type:Boolean,value:false},_boundOnCaptureScroll:{type:Function,value:function(){return this._onCaptureScroll.bind(this)}}},listeners:{"neon-animation-finish":"_onNeonAnimationFinish"},observers:["_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)"],get containedElement(){return Polymer.dom(this.$.content).getDistributedNodes()[0]},get _focusTarget(){return this.focusTarget||this.containedElement},ready:function(){this._scrollTop=0;this._scrollLeft=0;this._refitOnScrollRAF=null},attached:function(){if(!this.sizingTarget||this.sizingTarget===this){this.sizingTarget=this.containedElement}},detached:function(){this.cancelAnimation();document.removeEventListener("scroll",this._boundOnCaptureScroll);Polymer.IronDropdownScrollManager.removeScrollLock(this)},_openedChanged:function(){if(this.opened&&this.disabled){this.cancel()}else{this.cancelAnimation();this._updateAnimationConfig();this._saveScrollPosition();if(this.opened){document.addEventListener("scroll",this._boundOnCaptureScroll);!this.allowOutsideScroll&&Polymer.IronDropdownScrollManager.pushScrollLock(this)}else{document.removeEventListener("scroll",this._boundOnCaptureScroll);Polymer.IronDropdownScrollManager.removeScrollLock(this)}Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this,arguments)}},_renderOpened:function(){if(!this.noAnimations&&this.animationConfig.open){this.$.contentWrapper.classList.add("animating");this.playAnimation("open")}else{Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this,arguments)}},_renderClosed:function(){if(!this.noAnimations&&this.animationConfig.close){this.$.contentWrapper.classList.add("animating");this.playAnimation("close")}else{Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this,arguments)}},_onNeonAnimationFinish:function(){this.$.contentWrapper.classList.remove("animating");if(this.opened){this._finishRenderOpened()}else{this._finishRenderClosed()}},_onCaptureScroll:function(){if(!this.allowOutsideScroll){this._restoreScrollPosition()}else{this._refitOnScrollRAF&&window.cancelAnimationFrame(this._refitOnScrollRAF);this._refitOnScrollRAF=window.requestAnimationFrame(this.refit.bind(this))}},_saveScrollPosition:function(){if(document.scrollingElement){this._scrollTop=document.scrollingElement.scrollTop;this._scrollLeft=document.scrollingElement.scrollLeft}else{this._scrollTop=Math.max(document.documentElement.scrollTop,document.body.scrollTop);this._scrollLeft=Math.max(document.documentElement.scrollLeft,document.body.scrollLeft)}},_restoreScrollPosition:function(){if(document.scrollingElement){document.scrollingElement.scrollTop=this._scrollTop;document.scrollingElement.scrollLeft=this._scrollLeft}else{document.documentElement.scrollTop=this._scrollTop;document.documentElement.scrollLeft=this._scrollLeft;document.body.scrollTop=this._scrollTop;document.body.scrollLeft=this._scrollLeft}},_updateAnimationConfig:function(){var animations=(this.openAnimationConfig||[]).concat(this.closeAnimationConfig||[]);for(var i=0;i<animations.length;i++){animations[i].node=this.containedElement}this.animationConfig={open:this.openAnimationConfig,close:this.closeAnimationConfig}},_updateOverlayPosition:function(){if(this.isAttached){this.notifyResize()}},_applyFocus:function(){var focusTarget=this.focusTarget||this.containedElement;if(focusTarget&&this.opened&&!this.noAutoFocus){focusTarget.focus()}else{Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this,arguments)}}})})();Polymer({is:"fade-in-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;this._effect=new KeyframeEffect(node,[{opacity:"0"},{opacity:"1"}],this.timingFromConfig(config));return this._effect}});Polymer({is:"fade-out-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;this._effect=new KeyframeEffect(node,[{opacity:"1"},{opacity:"0"}],this.timingFromConfig(config));return this._effect}});Polymer({is:"paper-menu-grow-height-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;var rect=node.getBoundingClientRect();var height=rect.height;this._effect=new KeyframeEffect(node,[{height:height/2+"px"},{height:height+"px"}],this.timingFromConfig(config));return this._effect}});Polymer({is:"paper-menu-grow-width-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;var rect=node.getBoundingClientRect();var width=rect.width;this._effect=new KeyframeEffect(node,[{width:width/2+"px"},{width:width+"px"}],this.timingFromConfig(config));return this._effect}});Polymer({is:"paper-menu-shrink-width-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;var rect=node.getBoundingClientRect();var width=rect.width;this._effect=new KeyframeEffect(node,[{width:width+"px"},{width:width-width/20+"px"}],this.timingFromConfig(config));return this._effect}});Polymer({is:"paper-menu-shrink-height-animation",behaviors:[Polymer.NeonAnimationBehavior],configure:function(config){var node=config.node;var rect=node.getBoundingClientRect();var height=rect.height;var top=rect.top;this.setPrefixedProperty(node,"transformOrigin","0 0");this._effect=new KeyframeEffect(node,[{height:height+"px",transform:"translateY(0)"},{height:height/2+"px",transform:"translateY(-20px)"}],this.timingFromConfig(config));return this._effect}});(function(){"use strict";var config={ANIMATION_CUBIC_BEZIER:"cubic-bezier(.3,.95,.5,1)",MAX_ANIMATION_TIME_MS:400};var PaperMenuButton=Polymer({is:"paper-menu-button",behaviors:[Polymer.IronA11yKeysBehavior,Polymer.IronControlState],properties:{opened:{type:Boolean,value:false,notify:true,observer:"_openedChanged"},horizontalAlign:{type:String,value:"left",reflectToAttribute:true},verticalAlign:{type:String,value:"top",reflectToAttribute:true},dynamicAlign:{type:Boolean},horizontalOffset:{type:Number,value:0,notify:true},verticalOffset:{type:Number,value:0,notify:true},noOverlap:{type:Boolean},noAnimations:{type:Boolean,value:false},ignoreSelect:{type:Boolean,value:false},closeOnActivate:{type:Boolean,value:false},openAnimationConfig:{type:Object,value:function(){return[{name:"fade-in-animation",timing:{delay:100,duration:200}},{name:"paper-menu-grow-width-animation",timing:{delay:100,duration:150,easing:config.ANIMATION_CUBIC_BEZIER}},{name:"paper-menu-grow-height-animation",timing:{delay:100,duration:275,easing:config.ANIMATION_CUBIC_BEZIER}}]}},closeAnimationConfig:{type:Object,value:function(){return[{name:"fade-out-animation",timing:{duration:150}},{name:"paper-menu-shrink-width-animation",timing:{delay:100,duration:50,easing:config.ANIMATION_CUBIC_BEZIER}},{name:"paper-menu-shrink-height-animation",timing:{duration:200,easing:"ease-in"}}]}},allowOutsideScroll:{type:Boolean,value:false},restoreFocusOnClose:{type:Boolean,value:true},_dropdownContent:{type:Object}},hostAttributes:{role:"group","aria-haspopup":"true"},listeners:{"iron-activate":"_onIronActivate","iron-select":"_onIronSelect"},get contentElement(){return Polymer.dom(this.$.content).getDistributedNodes()[0]},toggle:function(){if(this.opened){this.close()}else{this.open()}},open:function(){if(this.disabled){return}this.$.dropdown.open()},close:function(){this.$.dropdown.close()},_onIronSelect:function(event){if(!this.ignoreSelect){this.close()}},_onIronActivate:function(event){if(this.closeOnActivate){this.close()}},_openedChanged:function(opened,oldOpened){if(opened){this._dropdownContent=this.contentElement;this.fire("paper-dropdown-open")}else if(oldOpened!=null){this.fire("paper-dropdown-close")}},_disabledChanged:function(disabled){Polymer.IronControlState._disabledChanged.apply(this,arguments);if(disabled&&this.opened){this.close()}},__onIronOverlayCanceled:function(event){var uiEvent=event.detail;var target=Polymer.dom(uiEvent).rootTarget;var trigger=this.$.trigger;var path=Polymer.dom(uiEvent).path;if(path.indexOf(trigger)>-1){event.preventDefault()}}});Object.keys(config).forEach(function(key){PaperMenuButton[key]=config[key]});Polymer.PaperMenuButton=PaperMenuButton})();Polymer.PaperInkyFocusBehaviorImpl={observers:["_focusedChanged(receivedFocusFromKeyboard)"],_focusedChanged:function(receivedFocusFromKeyboard){if(receivedFocusFromKeyboard){this.ensureRipple()}if(this.hasRipple()){this._ripple.holdDown=receivedFocusFromKeyboard}},_createRipple:function(){var ripple=Polymer.PaperRippleBehavior._createRipple();ripple.id="ink";ripple.setAttribute("center","");ripple.classList.add("circle");return ripple}};Polymer.PaperInkyFocusBehavior=[Polymer.IronButtonState,Polymer.IronControlState,Polymer.PaperRippleBehavior,Polymer.PaperInkyFocusBehaviorImpl];Polymer({is:"paper-icon-button",hostAttributes:{role:"button",tabindex:"0"},behaviors:[Polymer.PaperInkyFocusBehavior],properties:{src:{type:String},icon:{type:String},alt:{type:String,observer:"_altChanged"}},_altChanged:function(newValue,oldValue){var label=this.getAttribute("aria-label");if(!label||oldValue==label){this.setAttribute("aria-label",newValue)}}});Polymer({is:"iron-media-query",properties:{queryMatches:{type:Boolean,value:false,readOnly:true,notify:true},query:{type:String,observer:"queryChanged"},full:{type:Boolean,value:false},_boundMQHandler:{value:function(){return this.queryHandler.bind(this)}},_mq:{value:null}},attached:function(){this.style.display="none";this.queryChanged()},detached:function(){this._remove()},_add:function(){if(this._mq){this._mq.addListener(this._boundMQHandler)}},_remove:function(){if(this._mq){this._mq.removeListener(this._boundMQHandler)}this._mq=null},queryChanged:function(){this._remove();var query=this.query;if(!query){return}if(!this.full&&query[0]!=="("){query="("+query+")"}this._mq=window.matchMedia(query);this._add();this.queryHandler(this._mq)},queryHandler:function(mq){this._setQueryMatches(mq.matches)}});Polymer.PaperSpinnerBehavior={listeners:{animationend:"__reset",webkitAnimationEnd:"__reset"},properties:{active:{type:Boolean,value:false,reflectToAttribute:true,observer:"__activeChanged"},alt:{type:String,value:"loading",observer:"__altChanged"},__coolingDown:{type:Boolean,value:false}},__computeContainerClasses:function(active,coolingDown){return[active||coolingDown?"active":"",coolingDown?"cooldown":""].join(" ")},__activeChanged:function(active,old){this.__setAriaHidden(!active);this.__coolingDown=!active&&old},__altChanged:function(alt){if(alt===this.getPropertyInfo("alt").value){this.alt=this.getAttribute("aria-label")||alt}else{this.__setAriaHidden(alt==="");this.setAttribute("aria-label",alt)}},__setAriaHidden:function(hidden){var attr="aria-hidden";if(hidden){this.setAttribute(attr,"true")}else{this.removeAttribute(attr)}},__reset:function(){this.active=false;this.__coolingDown=false}};Polymer({is:"paper-spinner-lite",behaviors:[Polymer.PaperSpinnerBehavior]});
-// Copyright 2016 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.
-var CrSearchFieldBehavior={properties:{label:{type:String,value:""},clearLabel:{type:String,value:""},hasSearchText:{type:Boolean,reflectToAttribute:true,value:false},lastValue_:{type:String,value:""}},getSearchInput:function(){},getValue:function(){return this.getSearchInput().value},setValue:function(value,opt_noEvent){var searchInput=this.getSearchInput();searchInput.value=value;this.onSearchTermInput();this.onValueChanged_(value,!!opt_noEvent)},onSearchTermSearch:function(){this.onValueChanged_(this.getValue(),false)},onSearchTermInput:function(){this.hasSearchText=this.$.searchInput.value!=""},onValueChanged_:function(newValue,noEvent){if(newValue==this.lastValue_)return;this.lastValue_=newValue;if(!noEvent)this.fire("search-changed",newValue)}};
-// Copyright 2016 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.
-Polymer({is:"cr-toolbar-search-field",behaviors:[CrSearchFieldBehavior],properties:{narrow:{type:Boolean,reflectToAttribute:true},showingSearch:{type:Boolean,value:false,notify:true,observer:"showingSearchChanged_",reflectToAttribute:true},label:String,clearLabel:String,spinnerActive:{type:Boolean,reflectToAttribute:true},isSpinnerShown_:{type:Boolean,computed:"computeIsSpinnerShown_(spinnerActive, showingSearch)"},searchFocused_:{type:Boolean,value:false}},listeners:{click:"showSearch_"},getSearchInput:function(){return this.$.searchInput},isSearchFocused:function(){return this.searchFocused_},showAndFocus:function(){this.showingSearch=true;this.focus_()},onSearchTermInput:function(){CrSearchFieldBehavior.onSearchTermInput.call(this);this.showingSearch=this.hasSearchText||this.isSearchFocused()},focus_:function(){this.getSearchInput().focus()},computeIconTabIndex_:function(narrow){return narrow?0:-1},computeIsSpinnerShown_:function(){return this.spinnerActive&&this.showingSearch},onInputFocus_:function(){this.searchFocused_=true},onInputBlur_:function(){this.searchFocused_=false;if(!this.hasSearchText)this.showingSearch=false},onSearchTermKeydown_:function(e){if(e.key=="Escape")this.showingSearch=false},showSearch_:function(e){if(e.target!=this.$.clearSearch)this.showingSearch=true},clearSearch_:function(e){this.setValue("");this.focus_()},showingSearchChanged_:function(current,previous){if(previous==undefined)return;if(this.showingSearch){this.focus_();return}this.setValue("");this.getSearchInput().blur()}});
-// Copyright 2016 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.
-Polymer({is:"cr-toolbar",properties:{pageName:String,searchPrompt:String,clearLabel:String,menuLabel:String,menuPromo:String,spinnerActive:Boolean,showMenu:{type:Boolean,value:false},showMenuPromo:{type:Boolean,value:false},closeMenuPromo:String,narrow_:{type:Boolean,reflectToAttribute:true},showingSearch_:{type:Boolean,reflectToAttribute:true}},observers:["possiblyShowMenuPromo_(showMenu, showMenuPromo, showingSearch_)"],getSearchField:function(){return this.$.search},onClosePromoTap_:function(){this.fire("cr-toolbar-menu-promo-close")},onMenuTap_:function(){this.fire("cr-toolbar-menu-tap")},possiblyShowMenuPromo_:function(){Polymer.RenderStatus.afterNextRender(this,function(){if(this.showMenu&&this.showMenuPromo&&!this.showingSearch_){this.$$("#menuPromo").animate({opacity:[0,.9]},{duration:500,fill:"forwards"});this.fire("cr-toolbar-menu-promo-shown")}}.bind(this))},titleIfNotShowMenuPromo_:function(title,showMenuPromo){return showMenuPromo?"":title}});
-// 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.
-cr.define("downloads",function(){var Toolbar=Polymer({is:"downloads-toolbar",properties:{downloadsShowing:{reflectToAttribute:true,type:Boolean,value:false,observer:"downloadsShowingChanged_"},spinnerActive:{type:Boolean,notify:true}},listeners:{"paper-dropdown-close":"onPaperDropdownClose_","paper-dropdown-open":"onPaperDropdownOpen_"},canUndo:function(){return!this.$.toolbar.getSearchField().isSearchFocused()},canClearAll:function(){return!this.$.toolbar.getSearchField().getValue()&&this.downloadsShowing},onFindCommand:function(){this.$.toolbar.getSearchField().showAndFocus()},closeMoreActions_:function(){this.$.more.close()},downloadsShowingChanged_:function(){this.updateClearAll_()},onClearAllTap_:function(){assert(this.canClearAll());downloads.ActionService.getInstance().clearAll()},onPaperDropdownClose_:function(){window.removeEventListener("resize",assert(this.boundClose_))},onItemBlur_:function(e){var menu=this.$$("paper-menu");if(menu.items.indexOf(e.relatedTarget)>=0)return;this.$.more.restoreFocusOnClose=false;this.closeMoreActions_();this.$.more.restoreFocusOnClose=true},onPaperDropdownOpen_:function(){this.boundClose_=this.boundClose_||this.closeMoreActions_.bind(this);window.addEventListener("resize",this.boundClose_)},onSearchChanged_:function(event){var actionService=downloads.ActionService.getInstance();if(actionService.search(event.detail))this.spinnerActive=actionService.isSearching();this.updateClearAll_()},onOpenDownloadsFolderTap_:function(){downloads.ActionService.getInstance().openDownloadsFolder()},updateClearAll_:function(){this.$$("paper-menu .clear-all").hidden=!this.canClearAll()}});return{Toolbar:Toolbar}});
-// 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.
-cr.define("downloads",function(){var Manager=Polymer({is:"downloads-manager",properties:{hasDownloads_:{observer:"hasDownloadsChanged_",type:Boolean},hasShadow_:{type:Boolean,value:false,reflectToAttribute:true},inSearchMode_:{type:Boolean,value:false},items_:{type:Array,value:function(){return[]}},spinnerActive_:{type:Boolean,notify:true}},hostAttributes:{loading:true},listeners:{"downloads-list.scroll":"onListScroll_","toolbar.search-changed":"onSearchChanged_"},observers:["itemsChanged_(items_.*)"],loaded_:new PromiseResolver,clearAll_:function(){this.set("items_",[])},hasDownloadsChanged_:function(){if(loadTimeData.getBoolean("allowDeletingHistory"))this.$.toolbar.downloadsShowing=this.hasDownloads_;if(this.hasDownloads_)this.$["downloads-list"].fire("iron-resize")},insertItems_:function(index,list){this.splice.apply(this,["items_",index,0].concat(list));this.updateHideDates_(index,index+list.length);if(this.hasAttribute("loading")){this.removeAttribute("loading");this.loaded_.resolve()}this.spinnerActive_=false},itemsChanged_:function(){this.hasDownloads_=this.items_.length>0},noDownloadsText_:function(){return loadTimeData.getString(this.inSearchMode_?"noSearchResults":"noDownloads")},onCanExecute_:function(e){e=e;switch(e.command.id){case"undo-command":e.canExecute=this.$.toolbar.canUndo();break;case"clear-all-command":e.canExecute=this.$.toolbar.canClearAll();break;case"find-command":e.canExecute=true;break}},onCommand_:function(e){if(e.command.id=="clear-all-command")downloads.ActionService.getInstance().clearAll();else if(e.command.id=="undo-command")downloads.ActionService.getInstance().undo();else if(e.command.id=="find-command")this.$.toolbar.onFindCommand()},onListScroll_:function(){var list=this.$["downloads-list"];if(list.scrollHeight-list.scrollTop-list.offsetHeight<=100){downloads.ActionService.getInstance().loadMore()}this.hasShadow_=list.scrollTop>0},onLoad_:function(){cr.ui.decorate("command",cr.ui.Command);document.addEventListener("canExecute",this.onCanExecute_.bind(this));document.addEventListener("command",this.onCommand_.bind(this));downloads.ActionService.getInstance().loadMore();return this.loaded_.promise},onSearchChanged_:function(){this.inSearchMode_=downloads.ActionService.getInstance().isSearching()},removeItem_:function(index){this.splice("items_",index,1);this.updateHideDates_(index,index);this.onListScroll_()},updateHideDates_:function(start,end){for(var i=start;i<=end;++i){var current=this.items_[i];if(!current)continue;var prev=this.items_[i-1];var hideDate=!!prev&&prev.date_string==current.date_string;this.set("items_."+i+".hideDate",hideDate)}},updateItem_:function(index,data){this.set("items_."+index,data);this.updateHideDates_(index,index);var list=this.$["downloads-list"];list.updateSizeForItem(index)}});Manager.clearAll=function(){Manager.get().clearAll_()};Manager.get=function(){return queryRequiredElement("downloads-manager")};Manager.insertItems=function(index,list){Manager.get().insertItems_(index,list)};Manager.onLoad=function(){return Manager.get().onLoad_()};Manager.removeItem=function(index){Manager.get().removeItem_(index)};Manager.updateItem=function(index,data){Manager.get().updateItem_(index,data)};return{Manager:Manager}});
-// 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.
-window.addEventListener("load",function(){downloads.Manager.onLoad().then(function(){requestIdleCallback(function(){chrome.send("metricsHandler:recordTime",["Download.ResultsRenderedTime",window.performance.now()]);document.fonts.load("bold 12px Roboto")})})});
\ No newline at end of file
diff --git a/chrome/browser/resources/md_downloads/item.html b/chrome/browser/resources/md_downloads/item.html
index c54bd38..d1b4ec0 100644
--- a/chrome/browser/resources/md_downloads/item.html
+++ b/chrome/browser/resources/md_downloads/item.html
@@ -1,3 +1,4 @@
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
diff --git a/chrome/browser/resources/md_downloads/toolbar.html b/chrome/browser/resources/md_downloads/toolbar.html
index d2cd8e2..da1cb35 100644
--- a/chrome/browser/resources/md_downloads/toolbar.html
+++ b/chrome/browser/resources/md_downloads/toolbar.html
@@ -3,10 +3,9 @@
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/util.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu-button/paper-menu-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 
@@ -30,59 +29,34 @@
         flex: 1;
       }
 
-      paper-icon-button {
+      #moreActions {
         --iron-icon-height: 20px;
         --iron-icon-width: 20px;
-        --paper-icon-button: {
-          height: 32px;
-          padding: 6px;
-          width: 32px;
-        };
-      }
-
-      #more {
-        --paper-menu-button: {
-          padding: 6px;
-        };
-      }
-
-      paper-menu {
-        --paper-menu-selected-item: {
-          font-weight: normal;
-        };
-      }
-
-      paper-item {
-        -webkit-user-select: none;
-        cursor: pointer;
-        font: inherit;
-        min-height: 40px;
-        /* TODO(michaelpg): fix this for everybody ever.
-         * https://github.com/PolymerElements/paper-menu-button/issues/56 */
-        white-space: nowrap;
+        height: 32px;
+        padding: 6px;
+        width: 32px;
       }
     </style>
     <cr-toolbar id="toolbar" page-name="$i18n{title}"
         search-prompt="$i18n{search}" clear-label="$i18n{clearSearch}"
         spinner-active="{{spinnerActive}}" on-search-changed="onSearchChanged_">
-      <div class="more-actions">
-        <paper-menu-button id="more" horizontal-align="right"
-            allow-outside-scroll>
-          <paper-icon-button icon="cr:more-vert" title="$i18n{moreActions}"
-               class="dropdown-trigger"></paper-icon-button>
-          <paper-menu class="dropdown-content">
-            <paper-item class="clear-all" on-tap="onClearAllTap_"
-                role="menuitem" on-blur="onItemBlur_">
-              $i18n{clearAll}
-            </paper-item>
-            <paper-item on-tap="onOpenDownloadsFolderTap_"
-                role="menuitem" on-blur="onItemBlur_">
-              $i18n{openDownloadsFolder}
-            </paper-item>
-          </paper-menu>
-        </paper-menu-button>
-      </div>
+      <button is="paper-icon-button-light" class="more-actions" id="moreActions"
+          title="$i18n{moreActions}" class="dropdown-trigger"
+          on-tap="onMoreActionsTap_">
+        <iron-icon icon="cr:more-vert"></iron-icon>
+      </button>
     </cr-toolbar>
+    <!-- TODO(dbeam): should cr-action-menu be role="menu" by default? -->
+    <dialog is="cr-action-menu" id="moreActionsMenu" role="menu">
+      <button class="dropdown-item clear-all" on-tap="onClearAllTap_"
+          role="menuitem">
+        $i18n{clearAll}
+      </div>
+      <button class="dropdown-item" on-tap="onOpenDownloadsFolderTap_"
+          role="menuitem">
+        $i18n{openDownloadsFolder}
+      </button>
+    </dialog>
   </template>
   <script src="chrome://downloads/toolbar.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/md_downloads/toolbar.js b/chrome/browser/resources/md_downloads/toolbar.js
index 726f3a4..4a40daa 100644
--- a/chrome/browser/resources/md_downloads/toolbar.js
+++ b/chrome/browser/resources/md_downloads/toolbar.js
@@ -20,11 +20,6 @@
       },
     },
 
-    listeners: {
-      'paper-dropdown-close': 'onPaperDropdownClose_',
-      'paper-dropdown-open': 'onPaperDropdownOpen_',
-    },
-
     /** @return {boolean} Whether removal can be undone. */
     canUndo: function() {
       return !this.$.toolbar.getSearchField().isSearchFocused();
@@ -41,11 +36,6 @@
     },
 
     /** @private */
-    closeMoreActions_: function() {
-      this.$.more.close();
-    },
-
-    /** @private */
     downloadsShowingChanged_: function() {
       this.updateClearAll_();
     },
@@ -54,31 +44,12 @@
     onClearAllTap_: function() {
       assert(this.canClearAll());
       downloads.ActionService.getInstance().clearAll();
+      this.$.moreActionsMenu.close();
     },
 
     /** @private */
-    onPaperDropdownClose_: function() {
-      window.removeEventListener('resize', assert(this.boundClose_));
-    },
-
-    /**
-     * @param {!Event} e
-     * @private
-     */
-    onItemBlur_: function(e) {
-      var menu = /** @type {PaperMenuElement} */(this.$$('paper-menu'));
-      if (menu.items.indexOf(e.relatedTarget) >= 0)
-        return;
-
-      this.$.more.restoreFocusOnClose = false;
-      this.closeMoreActions_();
-      this.$.more.restoreFocusOnClose = true;
-    },
-
-    /** @private */
-    onPaperDropdownOpen_: function() {
-      this.boundClose_ = this.boundClose_ || this.closeMoreActions_.bind(this);
-      window.addEventListener('resize', this.boundClose_);
+    onMoreActionsTap_: function() {
+      this.$.moreActionsMenu.showAt(this.$.moreActions);
     },
 
     /**
@@ -95,11 +66,12 @@
     /** @private */
     onOpenDownloadsFolderTap_: function() {
       downloads.ActionService.getInstance().openDownloadsFolder();
+      this.$.moreActionsMenu.close();
     },
 
     /** @private */
     updateClearAll_: function() {
-      this.$$('paper-menu .clear-all').hidden = !this.canClearAll();
+      this.$$('.clear-all').hidden = !this.canClearAll();
     },
   });
 
diff --git a/chrome/browser/resources/md_downloads/vulcanized.html b/chrome/browser/resources/md_downloads/vulcanized.html
deleted file mode 100644
index cb5cfb6..0000000
--- a/chrome/browser/resources/md_downloads/vulcanized.html
+++ /dev/null
@@ -1,3380 +0,0 @@
-<!DOCTYPE html><html dir="$i18n{textdirection}" lang="$i18n{language}"><head><!--
-@license
-Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-Code distributed by Google as part of the polymer project is also
-subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
---><!--
-@license
-Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-Code distributed by Google as part of the polymer project is also
-subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
---><!--
-@license
-Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-Code distributed by Google as part of the polymer project is also
-subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
--->
-  <meta charset="utf-8">
-  <title>$i18n{title}</title>
-  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
-  <style>
-/* Copyright 2016 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. */
-
-:root {
-  /* This is a custom, Chrome-specific color that does not have a --paper or
-   * --google equivalent. */
-  --md-background-color: #f1f1f1;
-  --md-loading-message-color: #6e6e6e;
-  /* This is --google-blue-700, rewritten as a native custom property for speed.
-   */
-  --md-toolbar-color: rgb(51, 103, 214);
-}
-
-</style>
-  <style>
-    html {
-      background: var(--md-background-color);
-    }
-
-    html,
-    body {
-      height: 100%;
-    }
-
-    body {
-      display: flex;
-      margin: 0;
-    }
-
-    :root {
-      --downloads-card-margin: 24px;
-      --downloads-card-width: 640px;
-    }
-  </style>
-</head>
-<body>
-  <downloads-manager></downloads-manager>
-<if expr="is_macosx">
-  <command id="clear-all-command" shortcut="Alt|c Alt|ç"></command>
-  <command id="undo-command" shortcut="Meta|z"></command>
-  <command id="find-command" shortcut="Meta|f"></command>
-</if>
-<if expr="not is_macosx">
-  <command id="clear-all-command" shortcut="Alt|c"></command>
-  <command id="undo-command" shortcut="Ctrl|z"></command>
-  <command id="find-command" shortcut="Ctrl|f"></command>
-</if>
-  <div hidden="" by-vulcanize=""></div><link rel="import" href="chrome://resources/html/polymer.html">
-  <div hidden="" by-vulcanize=""><script src="chrome://resources/js/load_time_data.js"></script>
-<script src="chrome://downloads/strings.js"></script>
-</div><div hidden="" by-vulcanize=""><dom-module id="iron-list" assetpath="chrome://resources/polymer/v1_0/iron-list/" css-build="shadow">
-  <template>
-    <style scope="iron-list">:host {
-  display: block;
-        position: relative;
-}
-
-@media only screen and (-webkit-max-device-pixel-ratio: 1) {
-:host {
-  will-change: transform;
-}
-
-}
-
-#items {
-  ;
-        position: relative;
-}
-
-:host(:not([grid])) #items > ::content > * {
-  width: 100%;
-}
-
-#items > ::content > * {
-  box-sizing: border-box;
-        margin: 0;
-        position: absolute;
-        top: 0;
-        will-change: transform;
-}
-
-</style>
-
-    <array-selector id="selector" items="{{items}}" selected="{{selectedItems}}" selected-item="{{selectedItem}}">
-    </array-selector>
-
-    <div id="items">
-      <content></content>
-    </div>
-
-  </template>
-</dom-module>
-
-<style>
-  /* IE 10 support for HTML5 hidden attr */
-  [hidden] {
-    display: none !important;
-  }
-</style><style is="custom-style" css-build="shadow">html {
-  --layout_-_display:  flex;;
-
-    --layout-inline_-_display:  inline-flex;;
-
-    --layout-horizontal_-_display:  var(--layout_-_display); --layout-horizontal_-_-ms-flex-direction:  row; --layout-horizontal_-_-webkit-flex-direction:  row; --layout-horizontal_-_flex-direction:  row;;
-
-    --layout-horizontal-reverse_-_display:  var(--layout_-_display); --layout-horizontal-reverse_-_-ms-flex-direction:  row-reverse; --layout-horizontal-reverse_-_-webkit-flex-direction:  row-reverse; --layout-horizontal-reverse_-_flex-direction:  row-reverse;;
-
-    --layout-vertical_-_display:  var(--layout_-_display); --layout-vertical_-_-ms-flex-direction:  column; --layout-vertical_-_-webkit-flex-direction:  column; --layout-vertical_-_flex-direction:  column;;
-
-    --layout-vertical-reverse_-_display:  var(--layout_-_display); --layout-vertical-reverse_-_-ms-flex-direction:  column-reverse; --layout-vertical-reverse_-_-webkit-flex-direction:  column-reverse; --layout-vertical-reverse_-_flex-direction:  column-reverse;;
-
-    --layout-wrap_-_-ms-flex-wrap:  wrap; --layout-wrap_-_-webkit-flex-wrap:  wrap; --layout-wrap_-_flex-wrap:  wrap;;
-
-    --layout-wrap-reverse_-_-ms-flex-wrap:  wrap-reverse; --layout-wrap-reverse_-_-webkit-flex-wrap:  wrap-reverse; --layout-wrap-reverse_-_flex-wrap:  wrap-reverse;;
-
-    --layout-flex-auto_-_-ms-flex:  1 1 auto; --layout-flex-auto_-_-webkit-flex:  1 1 auto; --layout-flex-auto_-_flex:  1 1 auto;;
-
-    --layout-flex-none_-_-ms-flex:  none; --layout-flex-none_-_-webkit-flex:  none; --layout-flex-none_-_flex:  none;;
-
-    --layout-flex_-_-ms-flex:  1 1 0.000000001px; --layout-flex_-_-webkit-flex:  1; --layout-flex_-_flex:  1; --layout-flex_-_-webkit-flex-basis:  0.000000001px; --layout-flex_-_flex-basis:  0.000000001px;;
-
-    --layout-flex-2_-_-ms-flex:  2; --layout-flex-2_-_-webkit-flex:  2; --layout-flex-2_-_flex:  2;;
-
-    --layout-flex-3_-_-ms-flex:  3; --layout-flex-3_-_-webkit-flex:  3; --layout-flex-3_-_flex:  3;;
-
-    --layout-flex-4_-_-ms-flex:  4; --layout-flex-4_-_-webkit-flex:  4; --layout-flex-4_-_flex:  4;;
-
-    --layout-flex-5_-_-ms-flex:  5; --layout-flex-5_-_-webkit-flex:  5; --layout-flex-5_-_flex:  5;;
-
-    --layout-flex-6_-_-ms-flex:  6; --layout-flex-6_-_-webkit-flex:  6; --layout-flex-6_-_flex:  6;;
-
-    --layout-flex-7_-_-ms-flex:  7; --layout-flex-7_-_-webkit-flex:  7; --layout-flex-7_-_flex:  7;;
-
-    --layout-flex-8_-_-ms-flex:  8; --layout-flex-8_-_-webkit-flex:  8; --layout-flex-8_-_flex:  8;;
-
-    --layout-flex-9_-_-ms-flex:  9; --layout-flex-9_-_-webkit-flex:  9; --layout-flex-9_-_flex:  9;;
-
-    --layout-flex-10_-_-ms-flex:  10; --layout-flex-10_-_-webkit-flex:  10; --layout-flex-10_-_flex:  10;;
-
-    --layout-flex-11_-_-ms-flex:  11; --layout-flex-11_-_-webkit-flex:  11; --layout-flex-11_-_flex:  11;;
-
-    --layout-flex-12_-_-ms-flex:  12; --layout-flex-12_-_-webkit-flex:  12; --layout-flex-12_-_flex:  12;;
-
-    
-
-    --layout-start_-_-ms-flex-align:  start; --layout-start_-_-webkit-align-items:  flex-start; --layout-start_-_align-items:  flex-start;;
-
-    --layout-center_-_-ms-flex-align:  center; --layout-center_-_-webkit-align-items:  center; --layout-center_-_align-items:  center;;
-
-    --layout-end_-_-ms-flex-align:  end; --layout-end_-_-webkit-align-items:  flex-end; --layout-end_-_align-items:  flex-end;;
-
-    --layout-baseline_-_-ms-flex-align:  baseline; --layout-baseline_-_-webkit-align-items:  baseline; --layout-baseline_-_align-items:  baseline;;
-
-    
-
-    --layout-start-justified_-_-ms-flex-pack:  start; --layout-start-justified_-_-webkit-justify-content:  flex-start; --layout-start-justified_-_justify-content:  flex-start;;
-
-    --layout-center-justified_-_-ms-flex-pack:  center; --layout-center-justified_-_-webkit-justify-content:  center; --layout-center-justified_-_justify-content:  center;;
-
-    --layout-end-justified_-_-ms-flex-pack:  end; --layout-end-justified_-_-webkit-justify-content:  flex-end; --layout-end-justified_-_justify-content:  flex-end;;
-
-    --layout-around-justified_-_-ms-flex-pack:  distribute; --layout-around-justified_-_-webkit-justify-content:  space-around; --layout-around-justified_-_justify-content:  space-around;;
-
-    --layout-justified_-_-ms-flex-pack:  justify; --layout-justified_-_-webkit-justify-content:  space-between; --layout-justified_-_justify-content:  space-between;;
-
-    --layout-center-center_-_-ms-flex-align:  var(--layout-center_-_-ms-flex-align); --layout-center-center_-_-webkit-align-items:  var(--layout-center_-_-webkit-align-items); --layout-center-center_-_align-items:  var(--layout-center_-_align-items); --layout-center-center_-_-ms-flex-pack:  var(--layout-center-justified_-_-ms-flex-pack); --layout-center-center_-_-webkit-justify-content:  var(--layout-center-justified_-_-webkit-justify-content); --layout-center-center_-_justify-content:  var(--layout-center-justified_-_justify-content);;
-
-    
-
-    --layout-self-start_-_-ms-align-self:  flex-start; --layout-self-start_-_-webkit-align-self:  flex-start; --layout-self-start_-_align-self:  flex-start;;
-
-    --layout-self-center_-_-ms-align-self:  center; --layout-self-center_-_-webkit-align-self:  center; --layout-self-center_-_align-self:  center;;
-
-    --layout-self-end_-_-ms-align-self:  flex-end; --layout-self-end_-_-webkit-align-self:  flex-end; --layout-self-end_-_align-self:  flex-end;;
-
-    --layout-self-stretch_-_-ms-align-self:  stretch; --layout-self-stretch_-_-webkit-align-self:  stretch; --layout-self-stretch_-_align-self:  stretch;;
-
-    --layout-self-baseline_-_-ms-align-self:  baseline; --layout-self-baseline_-_-webkit-align-self:  baseline; --layout-self-baseline_-_align-self:  baseline;;
-
-    
-
-    --layout-start-aligned_-_-ms-flex-line-pack:  start; --layout-start-aligned_-_-ms-align-content:  flex-start; --layout-start-aligned_-_-webkit-align-content:  flex-start; --layout-start-aligned_-_align-content:  flex-start;;
-
-    --layout-end-aligned_-_-ms-flex-line-pack:  end; --layout-end-aligned_-_-ms-align-content:  flex-end; --layout-end-aligned_-_-webkit-align-content:  flex-end; --layout-end-aligned_-_align-content:  flex-end;;
-
-    --layout-center-aligned_-_-ms-flex-line-pack:  center; --layout-center-aligned_-_-ms-align-content:  center; --layout-center-aligned_-_-webkit-align-content:  center; --layout-center-aligned_-_align-content:  center;;
-
-    --layout-between-aligned_-_-ms-flex-line-pack:  justify; --layout-between-aligned_-_-ms-align-content:  space-between; --layout-between-aligned_-_-webkit-align-content:  space-between; --layout-between-aligned_-_align-content:  space-between;;
-
-    --layout-around-aligned_-_-ms-flex-line-pack:  distribute; --layout-around-aligned_-_-ms-align-content:  space-around; --layout-around-aligned_-_-webkit-align-content:  space-around; --layout-around-aligned_-_align-content:  space-around;;
-
-    
-
-    --layout-block_-_display:  block;;
-
-    --layout-invisible_-_visibility:  hidden !important;;
-
-    --layout-relative_-_position:  relative;;
-
-    --layout-fit_-_position:  absolute; --layout-fit_-_top:  0; --layout-fit_-_right:  0; --layout-fit_-_bottom:  0; --layout-fit_-_left:  0;;
-
-    --layout-scroll_-_-webkit-overflow-scrolling:  touch; --layout-scroll_-_overflow:  auto;;
-
-    --layout-fullbleed_-_margin:  0; --layout-fullbleed_-_height:  100vh;;
-
-    
-
-    --layout-fixed-top_-_position:  fixed; --layout-fixed-top_-_top:  0; --layout-fixed-top_-_left:  0; --layout-fixed-top_-_right:  0;;
-
-    --layout-fixed-right_-_position:  fixed; --layout-fixed-right_-_top:  0; --layout-fixed-right_-_right:  0; --layout-fixed-right_-_bottom:  0;;
-
-    --layout-fixed-bottom_-_position:  fixed; --layout-fixed-bottom_-_right:  0; --layout-fixed-bottom_-_bottom:  0; --layout-fixed-bottom_-_left:  0;;
-
-    --layout-fixed-left_-_position:  fixed; --layout-fixed-left_-_top:  0; --layout-fixed-left_-_bottom:  0; --layout-fixed-left_-_left:  0;;
-}
-
-</style><dom-module id="iron-icon" assetpath="chrome://resources/polymer/v1_0/iron-icon/" css-build="shadow">
-  <template>
-    <style scope="iron-icon">:host {
-  display: var(--layout-inline_-_display);
-        -ms-flex-align: var(--layout-center-center_-_-ms-flex-align); -webkit-align-items: var(--layout-center-center_-_-webkit-align-items); align-items: var(--layout-center-center_-_align-items); -ms-flex-pack: var(--layout-center-center_-_-ms-flex-pack); -webkit-justify-content: var(--layout-center-center_-_-webkit-justify-content); justify-content: var(--layout-center-center_-_justify-content);
-        position: relative;
-
-        vertical-align: middle;
-
-        fill: var(--iron-icon-fill-color, currentcolor);
-        stroke: var(--iron-icon-stroke-color, none);
-
-        width: var(--iron-icon-width, 24px);
-        height: var(--iron-icon-height, 24px);
-        ;
-}
-
-</style>
-  </template>
-
-  </dom-module>
-<dom-module id="paper-ripple" assetpath="chrome://resources/polymer/v1_0/paper-ripple/" css-build="shadow">
-
-  <template>
-    <style scope="paper-ripple">:host {
-  display: block;
-        position: absolute;
-        border-radius: inherit;
-        overflow: hidden;
-        top: 0;
-        left: 0;
-        right: 0;
-        bottom: 0;
-
-        
-        pointer-events: none;
-}
-
-:host([animating]) {
-  -webkit-transform: translate(0, 0);
-        transform: translate3d(0, 0, 0);
-}
-
-#background, #waves, .wave-container, .wave {
-  pointer-events: none;
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-}
-
-#background, .wave {
-  opacity: 0;
-}
-
-#waves, .wave {
-  overflow: hidden;
-}
-
-.wave-container, .wave {
-  border-radius: 50%;
-}
-
-:host(.circle) #background, :host(.circle) #waves {
-  border-radius: 50%;
-}
-
-:host(.circle) .wave-container {
-  overflow: hidden;
-}
-
-</style>
-
-    <div id="background"></div>
-    <div id="waves"></div>
-  </template>
-</dom-module>
-<style is="custom-style" css-build="shadow">html {
-  --shadow-transition_-_transition:  box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1);;
-
-    --shadow-none_-_box-shadow:  none;;
-
-    
-
-    --shadow-elevation-2dp_-_box-shadow:  0 2px 2px 0 rgba(0, 0, 0, 0.14),
-                  0 1px 5px 0 rgba(0, 0, 0, 0.12),
-                  0 3px 1px -2px rgba(0, 0, 0, 0.2);;
-
-    --shadow-elevation-3dp_-_box-shadow:  0 3px 4px 0 rgba(0, 0, 0, 0.14),
-                  0 1px 8px 0 rgba(0, 0, 0, 0.12),
-                  0 3px 3px -2px rgba(0, 0, 0, 0.4);;
-
-    --shadow-elevation-4dp_-_box-shadow:  0 4px 5px 0 rgba(0, 0, 0, 0.14),
-                  0 1px 10px 0 rgba(0, 0, 0, 0.12),
-                  0 2px 4px -1px rgba(0, 0, 0, 0.4);;
-
-    --shadow-elevation-6dp_-_box-shadow:  0 6px 10px 0 rgba(0, 0, 0, 0.14),
-                  0 1px 18px 0 rgba(0, 0, 0, 0.12),
-                  0 3px 5px -1px rgba(0, 0, 0, 0.4);;
-
-    --shadow-elevation-8dp_-_box-shadow:  0 8px 10px 1px rgba(0, 0, 0, 0.14),
-                  0 3px 14px 2px rgba(0, 0, 0, 0.12),
-                  0 5px 5px -3px rgba(0, 0, 0, 0.4);;
-
-    --shadow-elevation-12dp_-_box-shadow:  0 12px 16px 1px rgba(0, 0, 0, 0.14),
-                  0 4px 22px 3px rgba(0, 0, 0, 0.12),
-                  0 6px 7px -4px rgba(0, 0, 0, 0.4);;
-
-    --shadow-elevation-16dp_-_box-shadow:  0 16px 24px 2px rgba(0, 0, 0, 0.14),
-                  0  6px 30px 5px rgba(0, 0, 0, 0.12),
-                  0  8px 10px -5px rgba(0, 0, 0, 0.4);;
-}
-
-</style><dom-module id="paper-material-shared-styles" assetpath="chrome://resources/polymer/v1_0/paper-material/" css-build="shadow">
-  <template>
-    <style scope="paper-material-shared-styles">:host {
-  display: block;
-        position: relative;
-}
-
-:host([elevation="1"]) {
-  box-shadow: var(--shadow-elevation-2dp_-_box-shadow);
-}
-
-:host([elevation="2"]) {
-  box-shadow: var(--shadow-elevation-4dp_-_box-shadow);
-}
-
-:host([elevation="3"]) {
-  box-shadow: var(--shadow-elevation-6dp_-_box-shadow);
-}
-
-:host([elevation="4"]) {
-  box-shadow: var(--shadow-elevation-8dp_-_box-shadow);
-}
-
-:host([elevation="5"]) {
-  box-shadow: var(--shadow-elevation-16dp_-_box-shadow);
-}
-
-</style>
-  </template>
-</dom-module>
-<dom-module id="paper-button" assetpath="chrome://resources/polymer/v1_0/paper-button/" css-build="shadow">
-  <template strip-whitespace="">
-    <style scope="paper-button">:host {
-  display: block;
-        position: relative;
-}
-
-:host([elevation="1"]) {
-  box-shadow: var(--shadow-elevation-2dp_-_box-shadow);
-}
-
-:host([elevation="2"]) {
-  box-shadow: var(--shadow-elevation-4dp_-_box-shadow);
-}
-
-:host([elevation="3"]) {
-  box-shadow: var(--shadow-elevation-6dp_-_box-shadow);
-}
-
-:host([elevation="4"]) {
-  box-shadow: var(--shadow-elevation-8dp_-_box-shadow);
-}
-
-:host([elevation="5"]) {
-  box-shadow: var(--shadow-elevation-16dp_-_box-shadow);
-}
-
-:host {
-  display: var(--layout-inline_-_display);
-        -ms-flex-align: var(--layout-center-center_-_-ms-flex-align); -webkit-align-items: var(--layout-center-center_-_-webkit-align-items); align-items: var(--layout-center-center_-_align-items); -ms-flex-pack: var(--layout-center-center_-_-ms-flex-pack); -webkit-justify-content: var(--layout-center-center_-_-webkit-justify-content); justify-content: var(--layout-center-center_-_justify-content);
-        position: relative;
-        box-sizing: border-box;
-        min-width: 5.14em;
-        margin: 0 0.29em;
-        background: transparent;
-        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-        -webkit-tap-highlight-color: transparent;
-        font: inherit;
-        text-transform: uppercase;
-        outline-width: 0;
-        border-radius: 3px;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        -webkit-user-select: none;
-        user-select: none;
-        cursor: pointer;
-        z-index: 0;
-        padding: 0.7em 0.57em;
-
-        font-family: var(--paper-font-common-base_-_font-family); -webkit-font-smoothing: var(--paper-font-common-base_-_-webkit-font-smoothing);
-        ;
-}
-
-:host([hidden]) {
-  display: none !important;
-}
-
-:host([raised].keyboard-focus) {
-  font-weight: bold;
-        ;
-}
-
-:host(:not([raised]).keyboard-focus) {
-  font-weight: bold;
-        ;
-}
-
-:host([disabled]) {
-  background: #eaeaea;
-        color: #a8a8a8;
-        cursor: auto;
-        pointer-events: none;
-
-        ;
-}
-
-:host([animated]) {
-  transition: var(--shadow-transition_-_transition);
-}
-
-paper-ripple {
-  color: var(--paper-button-ink-color);
-}
-
-</style>
-
-    <content></content>
-  </template>
-
-  </dom-module>
-<dom-module id="paper-icon-button-light" assetpath="chrome://resources/polymer/v1_0/paper-icon-button/" css-build="shadow">
-  <template strip-whitespace="">
-    <style scope="paper-icon-button-light">:host {
-  vertical-align: middle;
-        color: inherit;
-        outline: none;
-        width: 24px;
-        height: 24px;
-        background: none;
-        margin: 0;
-        border: none;
-        padding: 0;
-
-        position: relative;
-        cursor: pointer;
-
-        
-        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-        -webkit-tap-highlight-color: transparent;
-}
-
-:host([disabled]) {
-  color: #9b9b9b;
-        pointer-events: none;
-        cursor: auto;
-}
-
-paper-ripple {
-  opacity: 0.6;
-        color: currentColor;
-}
-
-</style>
-    <content></content>
-  </template>
-  </dom-module>
-<style is="custom-style" css-build="shadow">html {
-  --google-red-100: #f4c7c3;
-    --google-red-300: #e67c73;
-    --google-red-500: #db4437;
-    --google-red-700: #c53929;
-
-    --google-blue-100: #c6dafc;
-    --google-blue-300: #7baaf7;
-    --google-blue-500: #4285f4;
-    --google-blue-700: #3367d6;
-
-    --google-green-100: #b7e1cd;
-    --google-green-300: #57bb8a;
-    --google-green-500: #0f9d58;
-    --google-green-700: #0b8043;
-
-    --google-yellow-100: #fce8b2;
-    --google-yellow-300: #f7cb4d;
-    --google-yellow-500: #f4b400;
-    --google-yellow-700: #f09300;
-
-    --google-grey-100: #f5f5f5;
-    --google-grey-300: #e0e0e0;
-    --google-grey-500: #9e9e9e;
-    --google-grey-700: #616161;
-    
-    
-
-    --paper-red-50: #ffebee;
-    --paper-red-100: #ffcdd2;
-    --paper-red-200: #ef9a9a;
-    --paper-red-300: #e57373;
-    --paper-red-400: #ef5350;
-    --paper-red-500: #f44336;
-    --paper-red-600: #e53935;
-    --paper-red-700: #d32f2f;
-    --paper-red-800: #c62828;
-    --paper-red-900: #b71c1c;
-    --paper-red-a100: #ff8a80;
-    --paper-red-a200: #ff5252;
-    --paper-red-a400: #ff1744;
-    --paper-red-a700: #d50000;
- 
-    --paper-pink-50: #fce4ec;
-    --paper-pink-100: #f8bbd0;
-    --paper-pink-200: #f48fb1;
-    --paper-pink-300: #f06292;
-    --paper-pink-400: #ec407a;
-    --paper-pink-500: #e91e63;
-    --paper-pink-600: #d81b60;
-    --paper-pink-700: #c2185b;
-    --paper-pink-800: #ad1457;
-    --paper-pink-900: #880e4f;
-    --paper-pink-a100: #ff80ab;
-    --paper-pink-a200: #ff4081;
-    --paper-pink-a400: #f50057;
-    --paper-pink-a700: #c51162;
- 
-    --paper-purple-50: #f3e5f5;
-    --paper-purple-100: #e1bee7;
-    --paper-purple-200: #ce93d8;
-    --paper-purple-300: #ba68c8;
-    --paper-purple-400: #ab47bc;
-    --paper-purple-500: #9c27b0;
-    --paper-purple-600: #8e24aa;
-    --paper-purple-700: #7b1fa2;
-    --paper-purple-800: #6a1b9a;
-    --paper-purple-900: #4a148c;
-    --paper-purple-a100: #ea80fc;
-    --paper-purple-a200: #e040fb;
-    --paper-purple-a400: #d500f9;
-    --paper-purple-a700: #aa00ff;
- 
-    --paper-deep-purple-50: #ede7f6;
-    --paper-deep-purple-100: #d1c4e9;
-    --paper-deep-purple-200: #b39ddb;
-    --paper-deep-purple-300: #9575cd;
-    --paper-deep-purple-400: #7e57c2;
-    --paper-deep-purple-500: #673ab7;
-    --paper-deep-purple-600: #5e35b1;
-    --paper-deep-purple-700: #512da8;
-    --paper-deep-purple-800: #4527a0;
-    --paper-deep-purple-900: #311b92;
-    --paper-deep-purple-a100: #b388ff;
-    --paper-deep-purple-a200: #7c4dff;
-    --paper-deep-purple-a400: #651fff;
-    --paper-deep-purple-a700: #6200ea;
- 
-    --paper-indigo-50: #e8eaf6;
-    --paper-indigo-100: #c5cae9;
-    --paper-indigo-200: #9fa8da;
-    --paper-indigo-300: #7986cb;
-    --paper-indigo-400: #5c6bc0;
-    --paper-indigo-500: #3f51b5;
-    --paper-indigo-600: #3949ab;
-    --paper-indigo-700: #303f9f;
-    --paper-indigo-800: #283593;
-    --paper-indigo-900: #1a237e;
-    --paper-indigo-a100: #8c9eff;
-    --paper-indigo-a200: #536dfe;
-    --paper-indigo-a400: #3d5afe;
-    --paper-indigo-a700: #304ffe;
- 
-    --paper-blue-50: #e3f2fd;
-    --paper-blue-100: #bbdefb;
-    --paper-blue-200: #90caf9;
-    --paper-blue-300: #64b5f6;
-    --paper-blue-400: #42a5f5;
-    --paper-blue-500: #2196f3;
-    --paper-blue-600: #1e88e5;
-    --paper-blue-700: #1976d2;
-    --paper-blue-800: #1565c0;
-    --paper-blue-900: #0d47a1;
-    --paper-blue-a100: #82b1ff;
-    --paper-blue-a200: #448aff;
-    --paper-blue-a400: #2979ff;
-    --paper-blue-a700: #2962ff;
- 
-    --paper-light-blue-50: #e1f5fe;
-    --paper-light-blue-100: #b3e5fc;
-    --paper-light-blue-200: #81d4fa;
-    --paper-light-blue-300: #4fc3f7;
-    --paper-light-blue-400: #29b6f6;
-    --paper-light-blue-500: #03a9f4;
-    --paper-light-blue-600: #039be5;
-    --paper-light-blue-700: #0288d1;
-    --paper-light-blue-800: #0277bd;
-    --paper-light-blue-900: #01579b;
-    --paper-light-blue-a100: #80d8ff;
-    --paper-light-blue-a200: #40c4ff;
-    --paper-light-blue-a400: #00b0ff;
-    --paper-light-blue-a700: #0091ea;
- 
-    --paper-cyan-50: #e0f7fa;
-    --paper-cyan-100: #b2ebf2;
-    --paper-cyan-200: #80deea;
-    --paper-cyan-300: #4dd0e1;
-    --paper-cyan-400: #26c6da;
-    --paper-cyan-500: #00bcd4;
-    --paper-cyan-600: #00acc1;
-    --paper-cyan-700: #0097a7;
-    --paper-cyan-800: #00838f;
-    --paper-cyan-900: #006064;
-    --paper-cyan-a100: #84ffff;
-    --paper-cyan-a200: #18ffff;
-    --paper-cyan-a400: #00e5ff;
-    --paper-cyan-a700: #00b8d4;
- 
-    --paper-teal-50: #e0f2f1;
-    --paper-teal-100: #b2dfdb;
-    --paper-teal-200: #80cbc4;
-    --paper-teal-300: #4db6ac;
-    --paper-teal-400: #26a69a;
-    --paper-teal-500: #009688;
-    --paper-teal-600: #00897b;
-    --paper-teal-700: #00796b;
-    --paper-teal-800: #00695c;
-    --paper-teal-900: #004d40;
-    --paper-teal-a100: #a7ffeb;
-    --paper-teal-a200: #64ffda;
-    --paper-teal-a400: #1de9b6;
-    --paper-teal-a700: #00bfa5;
- 
-    --paper-green-50: #e8f5e9;
-    --paper-green-100: #c8e6c9;
-    --paper-green-200: #a5d6a7;
-    --paper-green-300: #81c784;
-    --paper-green-400: #66bb6a;
-    --paper-green-500: #4caf50;
-    --paper-green-600: #43a047;
-    --paper-green-700: #388e3c;
-    --paper-green-800: #2e7d32;
-    --paper-green-900: #1b5e20;
-    --paper-green-a100: #b9f6ca;
-    --paper-green-a200: #69f0ae;
-    --paper-green-a400: #00e676;
-    --paper-green-a700: #00c853;
- 
-    --paper-light-green-50: #f1f8e9;
-    --paper-light-green-100: #dcedc8;
-    --paper-light-green-200: #c5e1a5;
-    --paper-light-green-300: #aed581;
-    --paper-light-green-400: #9ccc65;
-    --paper-light-green-500: #8bc34a;
-    --paper-light-green-600: #7cb342;
-    --paper-light-green-700: #689f38;
-    --paper-light-green-800: #558b2f;
-    --paper-light-green-900: #33691e;
-    --paper-light-green-a100: #ccff90;
-    --paper-light-green-a200: #b2ff59;
-    --paper-light-green-a400: #76ff03;
-    --paper-light-green-a700: #64dd17;
- 
-    --paper-lime-50: #f9fbe7;
-    --paper-lime-100: #f0f4c3;
-    --paper-lime-200: #e6ee9c;
-    --paper-lime-300: #dce775;
-    --paper-lime-400: #d4e157;
-    --paper-lime-500: #cddc39;
-    --paper-lime-600: #c0ca33;
-    --paper-lime-700: #afb42b;
-    --paper-lime-800: #9e9d24;
-    --paper-lime-900: #827717;
-    --paper-lime-a100: #f4ff81;
-    --paper-lime-a200: #eeff41;
-    --paper-lime-a400: #c6ff00;
-    --paper-lime-a700: #aeea00;
- 
-    --paper-yellow-50: #fffde7;
-    --paper-yellow-100: #fff9c4;
-    --paper-yellow-200: #fff59d;
-    --paper-yellow-300: #fff176;
-    --paper-yellow-400: #ffee58;
-    --paper-yellow-500: #ffeb3b;
-    --paper-yellow-600: #fdd835;
-    --paper-yellow-700: #fbc02d;
-    --paper-yellow-800: #f9a825;
-    --paper-yellow-900: #f57f17;
-    --paper-yellow-a100: #ffff8d;
-    --paper-yellow-a200: #ffff00;
-    --paper-yellow-a400: #ffea00;
-    --paper-yellow-a700: #ffd600;
- 
-    --paper-amber-50: #fff8e1;
-    --paper-amber-100: #ffecb3;
-    --paper-amber-200: #ffe082;
-    --paper-amber-300: #ffd54f;
-    --paper-amber-400: #ffca28;
-    --paper-amber-500: #ffc107;
-    --paper-amber-600: #ffb300;
-    --paper-amber-700: #ffa000;
-    --paper-amber-800: #ff8f00;
-    --paper-amber-900: #ff6f00;
-    --paper-amber-a100: #ffe57f;
-    --paper-amber-a200: #ffd740;
-    --paper-amber-a400: #ffc400;
-    --paper-amber-a700: #ffab00;
- 
-    --paper-orange-50: #fff3e0;
-    --paper-orange-100: #ffe0b2;
-    --paper-orange-200: #ffcc80;
-    --paper-orange-300: #ffb74d;
-    --paper-orange-400: #ffa726;
-    --paper-orange-500: #ff9800;
-    --paper-orange-600: #fb8c00;
-    --paper-orange-700: #f57c00;
-    --paper-orange-800: #ef6c00;
-    --paper-orange-900: #e65100;
-    --paper-orange-a100: #ffd180;
-    --paper-orange-a200: #ffab40;
-    --paper-orange-a400: #ff9100;
-    --paper-orange-a700: #ff6500;
- 
-    --paper-deep-orange-50: #fbe9e7;
-    --paper-deep-orange-100: #ffccbc;
-    --paper-deep-orange-200: #ffab91;
-    --paper-deep-orange-300: #ff8a65;
-    --paper-deep-orange-400: #ff7043;
-    --paper-deep-orange-500: #ff5722;
-    --paper-deep-orange-600: #f4511e;
-    --paper-deep-orange-700: #e64a19;
-    --paper-deep-orange-800: #d84315;
-    --paper-deep-orange-900: #bf360c;
-    --paper-deep-orange-a100: #ff9e80;
-    --paper-deep-orange-a200: #ff6e40;
-    --paper-deep-orange-a400: #ff3d00;
-    --paper-deep-orange-a700: #dd2c00;
- 
-    --paper-brown-50: #efebe9;
-    --paper-brown-100: #d7ccc8;
-    --paper-brown-200: #bcaaa4;
-    --paper-brown-300: #a1887f;
-    --paper-brown-400: #8d6e63;
-    --paper-brown-500: #795548;
-    --paper-brown-600: #6d4c41;
-    --paper-brown-700: #5d4037;
-    --paper-brown-800: #4e342e;
-    --paper-brown-900: #3e2723;
- 
-    --paper-grey-50: #fafafa;
-    --paper-grey-100: #f5f5f5;
-    --paper-grey-200: #eeeeee;
-    --paper-grey-300: #e0e0e0;
-    --paper-grey-400: #bdbdbd;
-    --paper-grey-500: #9e9e9e;
-    --paper-grey-600: #757575;
-    --paper-grey-700: #616161;
-    --paper-grey-800: #424242;
-    --paper-grey-900: #212121;
- 
-    --paper-blue-grey-50: #eceff1;
-    --paper-blue-grey-100: #cfd8dc;
-    --paper-blue-grey-200: #b0bec5;
-    --paper-blue-grey-300: #90a4ae;
-    --paper-blue-grey-400: #78909c;
-    --paper-blue-grey-500: #607d8b;
-    --paper-blue-grey-600: #546e7a;
-    --paper-blue-grey-700: #455a64;
-    --paper-blue-grey-800: #37474f;
-    --paper-blue-grey-900: #263238;
-
-    
-    --dark-divider-opacity: 0.12;
-    --dark-disabled-opacity: 0.38; 
-    --dark-secondary-opacity: 0.54;
-    --dark-primary-opacity: 0.87;
-
-    
-    --light-divider-opacity: 0.12;
-    --light-disabled-opacity: 0.3; 
-    --light-secondary-opacity: 0.7;
-    --light-primary-opacity: 1.0;
-}
-
-</style><dom-module id="paper-progress" assetpath="chrome://resources/polymer/v1_0/paper-progress/" css-build="shadow">
-  <template>
-    <style scope="paper-progress">:host {
-  display: block;
-        width: 200px;
-        position: relative;
-        overflow: hidden;
-}
-
-:host([hidden]) {
-  display: none !important;
-}
-
-#progressContainer {
-  ;
-        position: relative;
-}
-
-#progressContainer, .indeterminate::after {
-  height: var(--paper-progress-height, 4px);
-}
-
-#primaryProgress, #secondaryProgress, .indeterminate::after {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-}
-
-#progressContainer, .indeterminate::after {
-  background: var(--paper-progress-container-color,var(--google-grey-300));
-}
-
-:host(.transiting) #primaryProgress, :host(.transiting) #secondaryProgress {
-  -webkit-transition-property: -webkit-transform;
-        transition-property: transform;
-
-        
-        -webkit-transition-duration: var(--paper-progress-transition-duration, 0.08s);
-        transition-duration: var(--paper-progress-transition-duration, 0.08s);
-
-        
-        -webkit-transition-timing-function: var(--paper-progress-transition-timing-function, ease);
-        transition-timing-function: var(--paper-progress-transition-timing-function, ease);
-
-        
-        -webkit-transition-delay: var(--paper-progress-transition-delay, 0s);
-        transition-delay: var(--paper-progress-transition-delay, 0s);
-}
-
-#primaryProgress, #secondaryProgress {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-        -webkit-transform-origin: left center;
-        transform-origin: left center;
-        -webkit-transform: scaleX(0);
-        transform: scaleX(0);
-        will-change: transform;
-}
-
-#primaryProgress {
-  background: var(--paper-progress-active-color,var(--google-green-500));
-}
-
-#secondaryProgress {
-  background: var(--paper-progress-secondary-color,var(--google-green-100));
-}
-
-:host([disabled]) #primaryProgress {
-  background: var(--paper-progress-disabled-active-color,var(--google-grey-500));
-}
-
-:host([disabled]) #secondaryProgress {
-  background: var(--paper-progress-disabled-secondary-color,var(--google-grey-300));
-}
-
-:host(:not([disabled])) #primaryProgress.indeterminate {
-  -webkit-transform-origin: right center;
-        transform-origin: right center;
-        -webkit-animation: indeterminate-bar var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
-        animation: indeterminate-bar var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
-}
-
-:host(:not([disabled])) #primaryProgress.indeterminate::after {
-  content: "";
-        -webkit-transform-origin: center center;
-        transform-origin: center center;
-
-        -webkit-animation: indeterminate-splitter var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
-        animation: indeterminate-splitter var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
-}
-
-@-webkit-keyframes indeterminate-bar {
-0% {
-  -webkit-transform: scaleX(1) translateX(-100%);
-}
-
-50% {
-  -webkit-transform: scaleX(1) translateX(0%);
-}
-
-75% {
-  -webkit-transform: scaleX(1) translateX(0%);
-          -webkit-animation-timing-function: cubic-bezier(.28,.62,.37,.91);
-}
-
-100% {
-  -webkit-transform: scaleX(0) translateX(0%);
-}
-
-}
-
-@-webkit-keyframes indeterminate-splitter {
-0% {
-  -webkit-transform: scaleX(.75) translateX(-125%);
-}
-
-30% {
-  -webkit-transform: scaleX(.75) translateX(-125%);
-          -webkit-animation-timing-function: cubic-bezier(.42,0,.6,.8);
-}
-
-90% {
-  -webkit-transform: scaleX(.75) translateX(125%);
-}
-
-100% {
-  -webkit-transform: scaleX(.75) translateX(125%);
-}
-
-}
-
-@keyframes indeterminate-bar {
-0% {
-  transform: scaleX(1) translateX(-100%);
-}
-
-50% {
-  transform: scaleX(1) translateX(0%);
-}
-
-75% {
-  transform: scaleX(1) translateX(0%);
-          animation-timing-function: cubic-bezier(.28,.62,.37,.91);
-}
-
-100% {
-  transform: scaleX(0) translateX(0%);
-}
-
-}
-
-@keyframes indeterminate-splitter {
-0% {
-  transform: scaleX(.75) translateX(-125%);
-}
-
-30% {
-  transform: scaleX(.75) translateX(-125%);
-          animation-timing-function: cubic-bezier(.42,0,.6,.8);
-}
-
-90% {
-  transform: scaleX(.75) translateX(125%);
-}
-
-100% {
-  transform: scaleX(.75) translateX(125%);
-}
-
-}
-
-</style>
-
-    <div id="progressContainer">
-      <div id="secondaryProgress" hidden$="[[_hideSecondaryProgress(secondaryRatio)]]"></div>
-      <div id="primaryProgress"></div>
-    </div>
-  </template>
-</dom-module>
-
-<iron-iconset-svg name="downloads" size="24">
-  <svg>
-    <defs>
-      
-      <g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g>
-    </defs>
-  </svg>
-</iron-iconset-svg>
-<dom-module id="downloads-item" assetpath="chrome://downloads/" css-build="shadow">
-  <template>
-    <style scope="downloads-item">[is='action-link'] {
-  cursor: pointer;
-  display: inline-block;
-  text-decoration: none;
-}
-
-[is='action-link']:hover {
-  text-decoration: underline;
-}
-
-[is='action-link']:active {
-  color: rgb(5, 37, 119);
-  text-decoration: underline;
-}
-
-[is='action-link'][disabled] {
-  color: #999;
-  cursor: default;
-  pointer-events: none;
-  text-decoration: none;
-}
-
-[is='action-link'].no-outline {
-  outline: none;
-}
-
-:host {
-  display: flex;
-        flex-direction: column;
-}
-
-[hidden] {
-  display: none !important;
-}
-
-paper-button {
-  font-weight: 500;
-        margin: 0;
-        min-width: auto;
-}
-
-#date {
-  color: var(--paper-grey-700);
-        font-size: 100%;
-        font-weight: 500;
-        margin: 24px auto 10px;
-        width: var(--downloads-card-width);
-}
-
-#date:empty {
-  display: none;
-}
-
-#content {
-  background: white;
-        border-radius: 2px;
-        display: flex;
-        flex: none;
-        margin: 6px auto;
-        min-height: 103px;
-        position: relative;
-        width: var(--downloads-card-width);
-}
-
-#content.is-active {
-  box-shadow: var(--shadow-elevation-2dp_-_box-shadow);
-}
-
-#content:not(.is-active) {
-  background: rgba(255, 255, 255, .6);
-        box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .03),
-                    0 1px 4px 0 rgba(0, 0, 0, .048),
-                    0 3px 1px -2px rgba(0, 0, 0, .12);
-}
-
-#details {
-  -webkit-border-start: 1px #d8d8d8 solid;
-        -webkit-padding-end: 16px;
-        -webkit-padding-start: var(--downloads-card-margin);
-        display: flex;
-        flex: 1;
-        flex-direction: column;
-        min-width: 0;  
-        padding-bottom: 12px;
-        padding-top: 16px;
-}
-
-#content:not(.is-active) #details {
-  color: rgba(27, 27, 27, .6);
-}
-
-#content:not(.is-active) #name {
-  text-decoration: line-through;
-}
-
-.icon-wrapper {
-  align-self: center;
-        flex: none;
-        justify-content: center;
-        margin: 0 24px;
-}
-
-.icon {
-  height: 32px;
-        width: 32px;
-}
-
-#content:-webkit-any(.show-progress, .dangerous) #file-icon-wrapper {
-  align-self: flex-start;
-        padding-top: 16px;
-}
-
-#content:not(.is-active) .icon {
-  -webkit-filter: grayscale(100%);
-        opacity: .5;
-}
-
-#danger-icon {
-  height: 32px;
-        width: 32px;
-}
-
-#danger-icon[icon='cr:warning'], .dangerous #description {
-  color: var(--google-red-700);
-}
-
-#name, #file-link, #url {
-  max-width: 100%;
-}
-
-#name, #file-link {
-  font-weight: 500;
-        word-break: break-all;
-}
-
-#name {
-  -webkit-margin-end: 12px;
-}
-
-#pause-or-resume, .is-active :-webkit-any(#name, #file-link, #show) {
-  color: rgb(51, 103, 214);
-}
-
-#tag {
-  color: #5a5a5a;
-        font-weight: 500;
-}
-
-#url {
-  color: inherit;
-        margin-top: 6px;
-        min-height: 0;
-        overflow: hidden;
-        text-decoration: none;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-}
-
-.is-active #url {
-  color: var(--paper-grey-600);
-}
-
-#progress, #description:not(:empty), .controls {
-  margin-top: 16px;
-}
-
-.is-active #description {
-  color: #616161;
-}
-
-#progress {
-  --paper-progress-active-color: rgb(54, 126, 237);
-        --paper-progress-container-color: rgb(223, 222, 223);
-        width: auto;
-}
-
-.controls {
-  -webkit-margin-start: -.57em;
-}
-
-#cancel, #retry, .keep, .discard {
-  color: #5a5a5a;
-}
-
-#show {
-  margin: .7em .57em;
-}
-
-#controlled-by {
-  -webkit-margin-start: 8px;
-}
-
-#controlled-by, #controlled-by a {
-  color: #5a5a5a;
-}
-
-.is-active #controlled-by {
-  color: #333;
-}
-
-.is-active #controlled-by a {
-  color: rgb(51, 103, 214);
-}
-
-#remove-wrapper {
-  align-self: flex-start;
-        margin: 0;
-}
-
-#remove {
-  color: var(--paper-grey-700);
-        font-size: 16px;
-        height: 32px;
-        line-height: 17px;  
-        width: 32px;
-}
-
-#incognito {
-  bottom: 20px;
-        content: -webkit-image-set(
-            url("chrome://downloads/1x/incognito_marker.png") 1x,
-            url("chrome://downloads/2x/incognito_marker.png") 2x);
-        position: absolute;
-        right: 10px;
-}
-
-</style>
-
-    <h3 id="date">[[computeDate_(data.hideDate, data.since_string, data.date_string)]]</h3>
-
-    <div id="content" on-dragstart="onDragStart_" class$="[[computeClass_(isActive_, isDangerous_, showProgress_)]]">
-      <div id="file-icon-wrapper" class="icon-wrapper">
-        <img class="icon" id="file-icon" alt="" hidden="[[isDangerous_]]">
-        <iron-icon id="danger-icon" icon$="[[computeDangerIcon_(isDangerous_, data.danger_type)]]" hidden="[[!isDangerous_]]"></iron-icon>
-      </div>
-
-      <div id="details">
-        <div id="title-area"><a is="action-link" id="file-link" href="[[data.url]]" on-tap="onFileLinkTap_" hidden="[[!completelyOnDisk_]]">[[data.file_name]]</a><span id="name" hidden="[[completelyOnDisk_]]">[[data.file_name]]</span>
-          <span id="tag">[[computeTag_(data.state, data.last_reason_text, data.file_externally_removed)]]</span>
-        </div>
-
-        <a id="url" target="_blank">[[chopUrl_(data.url)]]</a>
-
-        <div id="description">[[computeDescription_(data.state, data.danger_type, data.file_name, data.progress_status_text)]]</div>
-
-        <template is="dom-if" if="[[showProgress_]]">
-          <paper-progress id="progress" indeterminate="[[isIndeterminate_(data.percent)]]" value="[[data.percent]]"></paper-progress>
-        </template>
-
-        <div id="safe" class="controls" hidden="[[isDangerous_]]">
-          <a is="action-link" id="show" on-tap="onShowTap_" hidden="[[!completelyOnDisk_]]">$i18n{controlShowInFolder}</a>
-          <template is="dom-if" if="[[data.retry]]">
-            <paper-button id="retry" on-tap="onRetryTap_">
-              $i18n{controlRetry}
-            </paper-button>
-          </template>
-          <template is="dom-if" if="[[pauseOrResumeText_]]">
-            <paper-button id="pause-or-resume" on-tap="onPauseOrResumeTap_">
-              [[pauseOrResumeText_]]
-            </paper-button>
-          </template>
-          <template is="dom-if" if="[[showCancel_]]">
-            <paper-button id="cancel" on-tap="onCancelTap_">
-              $i18n{controlCancel}
-            </paper-button>
-          </template>
-          <span id="controlled-by"></span>
-        </div>
-
-        <template is="dom-if" if="[[isDangerous_]]">
-          <div id="dangerous" class="controls">
-            
-            <template is="dom-if" if="[[!isMalware_]]">
-              <paper-button id="discard" on-tap="onDiscardDangerousTap_" class="discard">$i18n{dangerDiscard}</paper-button>
-              <paper-button id="save" on-tap="onSaveDangerousTap_" class="keep">$i18n{dangerSave}</paper-button>
-            </template>
-
-            
-            <template is="dom-if" if="[[isMalware_]]">
-              <paper-button id="danger-remove" on-tap="onDiscardDangerousTap_" class="discard">$i18n{controlRemoveFromList}</paper-button>
-              <paper-button id="restore" on-tap="onSaveDangerousTap_" class="keep">$i18n{dangerRestore}</paper-button>
-            </template>
-          </div>
-        </template>
-      </div>
-
-      <div id="remove-wrapper" class="icon-wrapper">
-        <button is="paper-icon-button-light" id="remove" title="$i18n{controlRemoveFromList}" style$="[[computeRemoveStyle_(isDangerous_, showCancel_)]]" on-tap="onRemoveTap_">✕</button>
-      </div>
-
-      <div id="incognito" title="$i18n{inIncognito}" hidden="[[!data.otr]]">
-      </div>
-    </div>
-
-  </template>
-  
-  </dom-module>
-
-
-
-
-<style is="custom-style" css-build="shadow">html {
-  --primary-text-color: var(--light-theme-text-color);
-    --primary-background-color: var(--light-theme-background-color);
-    --secondary-text-color: var(--light-theme-secondary-color);
-    --disabled-text-color: var(--light-theme-disabled-color);
-    --divider-color: var(--light-theme-divider-color);
-    --error-color: var(--paper-deep-orange-a700);
-
-    
-    --primary-color: var(--paper-indigo-500);
-    --light-primary-color: var(--paper-indigo-100);
-    --dark-primary-color: var(--paper-indigo-700);
-
-    --accent-color: var(--paper-pink-a200);
-    --light-accent-color: var(--paper-pink-a100);
-    --dark-accent-color: var(--paper-pink-a400);
-
-
-    
-    --light-theme-background-color: #ffffff;
-    --light-theme-base-color: #000000;
-    --light-theme-text-color: var(--paper-grey-900);
-    --light-theme-secondary-color: #737373;  
-    --light-theme-disabled-color: #9b9b9b;  
-    --light-theme-divider-color: #dbdbdb;
-
-    
-    --dark-theme-background-color: var(--paper-grey-900);
-    --dark-theme-base-color: #ffffff;
-    --dark-theme-text-color: #ffffff;
-    --dark-theme-secondary-color: #bcbcbc;  
-    --dark-theme-disabled-color: #646464;  
-    --dark-theme-divider-color: #3c3c3c;
-
-    
-    --text-primary-color: var(--dark-theme-text-color);
-    --default-primary-color: var(--primary-color);
-}
-
-</style><style>
-/* 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. */
-
-<if expr="not chromeos and not is_android">
-@font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 400;
-  src: local('Roboto'), local('Roboto-Regular'),
-      url("chrome://resources/roboto/roboto-regular.woff2") format('woff2');
-}
-
-@font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 500;
-  src: local('Roboto Medium'), local('Roboto-Medium'),
-      url("chrome://resources/roboto/roboto-medium.woff2") format('woff2');
-}
-
-@font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 700;
-  src: local('Roboto Bold'), local('Roboto-Bold'),
-      url("chrome://resources/roboto/roboto-bold.woff2") format('woff2');
-}
-</if>
-
-</style>
-<style is="custom-style" css-build="shadow">html {
-  --paper-font-common-base_-_font-family:  'Roboto', 'Noto', sans-serif; --paper-font-common-base_-_-webkit-font-smoothing:  antialiased;;
-
-    --paper-font-common-code_-_font-family:  'Roboto Mono', 'Consolas', 'Menlo', monospace; --paper-font-common-code_-_-webkit-font-smoothing:  antialiased;;
-
-    --paper-font-common-expensive-kerning_-_text-rendering:  optimizeLegibility;;
-
-    --paper-font-common-nowrap_-_white-space:  nowrap; --paper-font-common-nowrap_-_overflow:  hidden; --paper-font-common-nowrap_-_text-overflow:  ellipsis;;
-
-    
-
-    --paper-font-display4_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-display4_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-display4_-_white-space:  var(--paper-font-common-nowrap_-_white-space); --paper-font-display4_-_overflow:  var(--paper-font-common-nowrap_-_overflow); --paper-font-display4_-_text-overflow:  var(--paper-font-common-nowrap_-_text-overflow); --paper-font-display4_-_font-size:  112px; --paper-font-display4_-_font-weight:  300; --paper-font-display4_-_letter-spacing:  -.044em; --paper-font-display4_-_line-height:  120px;;
-
-    --paper-font-display3_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-display3_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-display3_-_white-space:  var(--paper-font-common-nowrap_-_white-space); --paper-font-display3_-_overflow:  var(--paper-font-common-nowrap_-_overflow); --paper-font-display3_-_text-overflow:  var(--paper-font-common-nowrap_-_text-overflow); --paper-font-display3_-_font-size:  56px; --paper-font-display3_-_font-weight:  400; --paper-font-display3_-_letter-spacing:  -.026em; --paper-font-display3_-_line-height:  60px;;
-
-    --paper-font-display2_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-display2_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-display2_-_font-size:  45px; --paper-font-display2_-_font-weight:  400; --paper-font-display2_-_letter-spacing:  -.018em; --paper-font-display2_-_line-height:  48px;;
-
-    --paper-font-display1_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-display1_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-display1_-_font-size:  34px; --paper-font-display1_-_font-weight:  400; --paper-font-display1_-_letter-spacing:  -.01em; --paper-font-display1_-_line-height:  40px;;
-
-    --paper-font-headline_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-headline_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-headline_-_font-size:  24px; --paper-font-headline_-_font-weight:  400; --paper-font-headline_-_letter-spacing:  -.012em; --paper-font-headline_-_line-height:  32px;;
-
-    --paper-font-title_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-title_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-title_-_white-space:  var(--paper-font-common-nowrap_-_white-space); --paper-font-title_-_overflow:  var(--paper-font-common-nowrap_-_overflow); --paper-font-title_-_text-overflow:  var(--paper-font-common-nowrap_-_text-overflow); --paper-font-title_-_font-size:  20px; --paper-font-title_-_font-weight:  500; --paper-font-title_-_line-height:  28px;;
-
-    --paper-font-subhead_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-subhead_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-subhead_-_font-size:  16px; --paper-font-subhead_-_font-weight:  400; --paper-font-subhead_-_line-height:  24px;;
-
-    --paper-font-body2_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-body2_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-body2_-_font-size:  14px; --paper-font-body2_-_font-weight:  500; --paper-font-body2_-_line-height:  24px;;
-
-    --paper-font-body1_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-body1_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-body1_-_font-size:  14px; --paper-font-body1_-_font-weight:  400; --paper-font-body1_-_line-height:  20px;;
-
-    --paper-font-caption_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-caption_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-caption_-_white-space:  var(--paper-font-common-nowrap_-_white-space); --paper-font-caption_-_overflow:  var(--paper-font-common-nowrap_-_overflow); --paper-font-caption_-_text-overflow:  var(--paper-font-common-nowrap_-_text-overflow); --paper-font-caption_-_font-size:  12px; --paper-font-caption_-_font-weight:  400; --paper-font-caption_-_letter-spacing:  0.011em; --paper-font-caption_-_line-height:  20px;;
-
-    --paper-font-menu_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-menu_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-menu_-_white-space:  var(--paper-font-common-nowrap_-_white-space); --paper-font-menu_-_overflow:  var(--paper-font-common-nowrap_-_overflow); --paper-font-menu_-_text-overflow:  var(--paper-font-common-nowrap_-_text-overflow); --paper-font-menu_-_font-size:  13px; --paper-font-menu_-_font-weight:  500; --paper-font-menu_-_line-height:  24px;;
-
-    --paper-font-button_-_font-family:  var(--paper-font-common-base_-_font-family); --paper-font-button_-_-webkit-font-smoothing:  var(--paper-font-common-base_-_-webkit-font-smoothing); --paper-font-button_-_white-space:  var(--paper-font-common-nowrap_-_white-space); --paper-font-button_-_overflow:  var(--paper-font-common-nowrap_-_overflow); --paper-font-button_-_text-overflow:  var(--paper-font-common-nowrap_-_text-overflow); --paper-font-button_-_font-size:  14px; --paper-font-button_-_font-weight:  500; --paper-font-button_-_letter-spacing:  0.018em; --paper-font-button_-_line-height:  24px; --paper-font-button_-_text-transform:  uppercase;;
-
-    --paper-font-code2_-_font-family:  var(--paper-font-common-code_-_font-family); --paper-font-code2_-_-webkit-font-smoothing:  var(--paper-font-common-code_-_-webkit-font-smoothing); --paper-font-code2_-_font-size:  14px; --paper-font-code2_-_font-weight:  700; --paper-font-code2_-_line-height:  20px;;
-
-    --paper-font-code1_-_font-family:  var(--paper-font-common-code_-_font-family); --paper-font-code1_-_-webkit-font-smoothing:  var(--paper-font-common-code_-_-webkit-font-smoothing); --paper-font-code1_-_font-size:  14px; --paper-font-code1_-_font-weight:  500; --paper-font-code1_-_line-height:  20px;;
-}
-
-</style><dom-module id="paper-item-shared-styles" assetpath="chrome://resources/polymer/v1_0/paper-item/" css-build="shadow">
-  <template>
-    <style scope="paper-item-shared-styles">:host, .paper-item {
-  display: block;
-        position: relative;
-        min-height: var(--paper-item-min-height, 48px);
-        padding: 0px 16px;
-}
-
-.paper-item {
-  font-family: var(--paper-font-subhead_-_font-family); -webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing); font-size: var(--paper-font-subhead_-_font-size); font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height);
-        border:none;
-        outline: none;
-        background: white;
-        width: 100%;
-        text-align: left;
-}
-
-:host([hidden]), .paper-item[hidden] {
-  display: none !important;
-}
-
-:host(.iron-selected), .paper-item.iron-selected {
-  font-weight: var(--paper-item-selected-weight, bold);
-
-        ;
-}
-
-:host([disabled]), .paper-item[disabled] {
-  color: var(--paper-item-disabled-color,var(--disabled-text-color));
-
-        ;
-}
-
-:host(:focus), .paper-item:focus {
-  position: relative;
-        outline: 0;
-
-        ;
-}
-
-:host(:focus):before, .paper-item:focus:before {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-
-        background: currentColor;
-        content: '';
-        opacity: var(--dark-divider-opacity);
-        pointer-events: none;
-
-        ;
-}
-
-</style>
-  </template>
-</dom-module>
-<dom-module id="paper-item" assetpath="chrome://resources/polymer/v1_0/paper-item/" css-build="shadow">
-  <template>
-    
-    <style scope="paper-item">:host, .paper-item {
-  display: block;
-        position: relative;
-        min-height: var(--paper-item-min-height, 48px);
-        padding: 0px 16px;
-}
-
-.paper-item {
-  font-family: var(--paper-font-subhead_-_font-family); -webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing); font-size: var(--paper-font-subhead_-_font-size); font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height);
-        border:none;
-        outline: none;
-        background: white;
-        width: 100%;
-        text-align: left;
-}
-
-:host([hidden]), .paper-item[hidden] {
-  display: none !important;
-}
-
-:host(.iron-selected), .paper-item.iron-selected {
-  font-weight: var(--paper-item-selected-weight, bold);
-
-        ;
-}
-
-:host([disabled]), .paper-item[disabled] {
-  color: var(--paper-item-disabled-color,var(--disabled-text-color));
-
-        ;
-}
-
-:host(:focus), .paper-item:focus {
-  position: relative;
-        outline: 0;
-
-        ;
-}
-
-:host(:focus):before, .paper-item:focus:before {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-
-        background: currentColor;
-        content: '';
-        opacity: var(--dark-divider-opacity);
-        pointer-events: none;
-
-        ;
-}
-
-:host {
-  display: var(--layout-horizontal_-_display); -ms-flex-direction: var(--layout-horizontal_-_-ms-flex-direction); -webkit-flex-direction: var(--layout-horizontal_-_-webkit-flex-direction); flex-direction: var(--layout-horizontal_-_flex-direction);
-        -ms-flex-align: var(--layout-center_-_-ms-flex-align); -webkit-align-items: var(--layout-center_-_-webkit-align-items); align-items: var(--layout-center_-_align-items);
-        font-family: var(--paper-font-subhead_-_font-family); -webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing); font-size: var(--paper-font-subhead_-_font-size); font-weight: var(--paper-font-subhead_-_font-weight); line-height: var(--paper-font-subhead_-_line-height);
-
-        ;
-}
-
-</style>
-
-    <content></content>
-  </template>
-
-  </dom-module>
-<dom-module id="paper-menu-shared-styles" assetpath="chrome://resources/polymer/v1_0/paper-menu/" css-build="shadow">
-  <template>
-    <style scope="paper-menu-shared-styles">.selectable-content > ::content > .iron-selected {
-  font-weight: bold;
-
-        font-weight: var(--paper-menu-selected-item_-_font-weight, bold);
-}
-
-.selectable-content > ::content > [disabled] {
-  color: var(--paper-menu-disabled-color,var(--disabled-text-color));
-}
-
-.selectable-content > ::content > *:focus {
-  position: relative;
-        outline: 0;
-
-        ;
-}
-
-.selectable-content > ::content > *:focus:after {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-        background: currentColor;
-        opacity: var(--dark-divider-opacity);
-        content: '';
-        pointer-events: none;
-
-        ;
-}
-
-.selectable-content > ::content > *[colored]:focus:after {
-  opacity: 0.26;
-}
-
-</style>
-  </template>
-</dom-module>
-<dom-module id="paper-menu" assetpath="chrome://resources/polymer/v1_0/paper-menu/" css-build="shadow">
-  <template>
-    
-    <style scope="paper-menu">.selectable-content > ::content > .iron-selected {
-  font-weight: bold;
-
-        font-weight: var(--paper-menu-selected-item_-_font-weight, bold);
-}
-
-.selectable-content > ::content > [disabled] {
-  color: var(--paper-menu-disabled-color,var(--disabled-text-color));
-}
-
-.selectable-content > ::content > *:focus {
-  position: relative;
-        outline: 0;
-
-        ;
-}
-
-.selectable-content > ::content > *:focus:after {
-  position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left);
-        background: currentColor;
-        opacity: var(--dark-divider-opacity);
-        content: '';
-        pointer-events: none;
-
-        ;
-}
-
-.selectable-content > ::content > *[colored]:focus:after {
-  opacity: 0.26;
-}
-
-:host {
-  display: block;
-        padding: 8px 0;
-
-        background: var(--paper-menu-background-color,var(--primary-background-color));
-        color: var(--paper-menu-color,var(--primary-text-color));
-
-        ;
-}
-
-</style>
-
-    <div class="selectable-content">
-      <content></content>
-    </div>
-  </template>
-
-  </dom-module>
-<dom-module id="iron-overlay-backdrop" assetpath="" css-build="shadow">
-
-  <template>
-    <style scope="iron-overlay-backdrop">:host {
-  position: fixed;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-color: var(--iron-overlay-backdrop-background-color, #000);
-        opacity: 0;
-        transition: opacity 0.2s;
-        pointer-events: none;
-        ;
-}
-
-:host(.opened) {
-  opacity: var(--iron-overlay-backdrop-opacity, 0.6);
-        pointer-events: auto;
-        ;
-}
-
-</style>
-
-    <content></content>
-  </template>
-
-</dom-module>
-
-<script src="chrome://resources/polymer/v1_0/web-animations-js/web-animations-next-lite.min.js"></script>
-<dom-module id="iron-dropdown" assetpath="chrome://resources/polymer/v1_0/iron-dropdown/" css-build="shadow">
-  <template>
-    <style scope="iron-dropdown">:host {
-  position: fixed;
-}
-
-#contentWrapper ::content > * {
-  overflow: auto;
-}
-
-#contentWrapper.animating ::content > * {
-  overflow: hidden;
-}
-
-</style>
-
-    <div id="contentWrapper">
-      <content id="content" select=".dropdown-content"></content>
-    </div>
-  </template>
-
-  </dom-module>
-<dom-module id="paper-menu-button" assetpath="chrome://resources/polymer/v1_0/paper-menu-button/" css-build="shadow">
-  <template>
-    <style scope="paper-menu-button">:host {
-  display: inline-block;
-        position: relative;
-        padding: 8px;
-        outline: none;
-
-        padding: var(--paper-menu-button_-_padding, 8px);
-}
-
-:host([disabled]) {
-  cursor: auto;
-        color: var(--disabled-text-color);
-
-        ;
-}
-
-iron-dropdown {
-  ;
-}
-
-.dropdown-content {
-  box-shadow: var(--shadow-elevation-2dp_-_box-shadow);
-
-        position: relative;
-        border-radius: 2px;
-        background-color: var(--paper-menu-button-dropdown-background,var(--primary-background-color));
-
-        ;
-}
-
-:host([vertical-align="top"]) .dropdown-content {
-  margin-bottom: 20px;
-        margin-top: -10px;
-        top: 10px;
-}
-
-:host([vertical-align="bottom"]) .dropdown-content {
-  bottom: 10px;
-        margin-bottom: -10px;
-        margin-top: 20px;
-}
-
-#trigger {
-  cursor: pointer;
-}
-
-</style>
-
-    <div id="trigger" on-tap="toggle">
-      <content select=".dropdown-trigger"></content>
-    </div>
-
-    <iron-dropdown id="dropdown" opened="{{opened}}" horizontal-align="[[horizontalAlign]]" vertical-align="[[verticalAlign]]" dynamic-align="[[dynamicAlign]]" horizontal-offset="[[horizontalOffset]]" vertical-offset="[[verticalOffset]]" no-overlap="[[noOverlap]]" open-animation-config="[[openAnimationConfig]]" close-animation-config="[[closeAnimationConfig]]" no-animations="[[noAnimations]]" focus-target="[[_dropdownContent]]" allow-outside-scroll="[[allowOutsideScroll]]" restore-focus-on-close="[[restoreFocusOnClose]]" on-iron-overlay-canceled="__onIronOverlayCanceled">
-      <div class="dropdown-content">
-        <content id="content" select=".dropdown-content"></content>
-      </div>
-    </iron-dropdown>
-  </template>
-
-  </dom-module>
-<dom-module id="paper-icon-button" assetpath="chrome://resources/polymer/v1_0/paper-icon-button/" css-build="shadow">
-  <template strip-whitespace="">
-    <style scope="paper-icon-button">:host {
-  display: inline-block;
-        position: relative;
-        padding: 8px;
-        outline: none;
-        -webkit-user-select: none;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        user-select: none;
-        cursor: pointer;
-        z-index: 0;
-        line-height: 1;
-
-        width: 40px;
-        height: 40px;
-
-        
-        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-        -webkit-tap-highlight-color: transparent;
-
-        
-        box-sizing: border-box !important;
-
-        height: var(--paper-icon-button_-_height, 40px); padding: var(--paper-icon-button_-_padding, 8px); width: var(--paper-icon-button_-_width, 40px);
-}
-
-:host #ink {
-  color: var(--paper-icon-button-ink-color,var(--primary-text-color));
-        opacity: 0.6;
-}
-
-:host([disabled]) {
-  color: var(--paper-icon-button-disabled-text,var(--disabled-text-color));
-        pointer-events: none;
-        cursor: auto;
-
-        ;
-}
-
-:host(:hover) {
-  ;
-}
-
-iron-icon {
-  --iron-icon-width: 100%;
-        --iron-icon-height: 100%;
-}
-
-</style>
-
-    <iron-icon id="icon" src="[[src]]" icon="[[icon]]" alt$="[[alt]]"></iron-icon>
-  </template>
-
-  </dom-module>
-<dom-module id="paper-spinner-styles" assetpath="chrome://resources/polymer/v1_0/paper-spinner/" css-build="shadow">
-  <template>
-    <style scope="paper-spinner-styles">:host {
-  display: inline-block;
-        position: relative;
-        width: 28px;
-        height: 28px;
-
-        
-        --paper-spinner-container-rotation-duration: 1568ms;
-
-        
-        --paper-spinner-expand-contract-duration: 1333ms;
-
-        
-        --paper-spinner-full-cycle-duration: 5332ms;
-
-        
-        --paper-spinner-cooldown-duration: 400ms;
-}
-
-#spinnerContainer {
-  width: 100%;
-        height: 100%;
-
-        
-        direction: ltr;
-}
-
-#spinnerContainer.active {
-  -webkit-animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite;
-        animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite;
-}
-
-@-webkit-keyframes container-rotate {
-to {
-  -webkit-transform: rotate(360deg)
-}
-
-}
-
-@keyframes container-rotate {
-to {
-  transform: rotate(360deg)
-}
-
-}
-
-.spinner-layer {
-  position: absolute;
-        width: 100%;
-        height: 100%;
-        opacity: 0;
-        white-space: nowrap;
-        border-color: var(--paper-spinner-color,var(--google-blue-500));
-}
-
-.layer-1 {
-  border-color: var(--paper-spinner-layer-1-color,var(--google-blue-500));
-}
-
-.layer-2 {
-  border-color: var(--paper-spinner-layer-2-color,var(--google-red-500));
-}
-
-.layer-3 {
-  border-color: var(--paper-spinner-layer-3-color,var(--google-yellow-500));
-}
-
-.layer-4 {
-  border-color: var(--paper-spinner-layer-4-color,var(--google-green-500));
-}
-
-.active .spinner-layer {
-  -webkit-animation-name: fill-unfill-rotate;
-        -webkit-animation-duration: var(--paper-spinner-full-cycle-duration);
-        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        -webkit-animation-iteration-count: infinite;
-        animation-name: fill-unfill-rotate;
-        animation-duration: var(--paper-spinner-full-cycle-duration);
-        animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        animation-iteration-count: infinite;
-        opacity: 1;
-}
-
-.active .spinner-layer.layer-1 {
-  -webkit-animation-name: fill-unfill-rotate, layer-1-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-1-fade-in-out;
-}
-
-.active .spinner-layer.layer-2 {
-  -webkit-animation-name: fill-unfill-rotate, layer-2-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-2-fade-in-out;
-}
-
-.active .spinner-layer.layer-3 {
-  -webkit-animation-name: fill-unfill-rotate, layer-3-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-3-fade-in-out;
-}
-
-.active .spinner-layer.layer-4 {
-  -webkit-animation-name: fill-unfill-rotate, layer-4-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-4-fade-in-out;
-}
-
-@-webkit-keyframes fill-unfill-rotate {
-12.5% {
-  -webkit-transform: rotate(135deg)
-}
-
-25% {
-  -webkit-transform: rotate(270deg)
-}
-
-37.5% {
-  -webkit-transform: rotate(405deg)
-}
-
-50% {
-  -webkit-transform: rotate(540deg)
-}
-
-62.5% {
-  -webkit-transform: rotate(675deg)
-}
-
-75% {
-  -webkit-transform: rotate(810deg)
-}
-
-87.5% {
-  -webkit-transform: rotate(945deg)
-}
-
-to {
-  -webkit-transform: rotate(1080deg)
-}
-
-}
-
-@keyframes fill-unfill-rotate {
-12.5% {
-  transform: rotate(135deg)
-}
-
-25% {
-  transform: rotate(270deg)
-}
-
-37.5% {
-  transform: rotate(405deg)
-}
-
-50% {
-  transform: rotate(540deg)
-}
-
-62.5% {
-  transform: rotate(675deg)
-}
-
-75% {
-  transform: rotate(810deg)
-}
-
-87.5% {
-  transform: rotate(945deg)
-}
-
-to {
-  transform: rotate(1080deg)
-}
-
-}
-
-@-webkit-keyframes layer-1-fade-in-out {
-0% {
-  opacity: 1
-}
-
-25% {
-  opacity: 1
-}
-
-26% {
-  opacity: 0
-}
-
-89% {
-  opacity: 0
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 1
-}
-
-}
-
-@keyframes layer-1-fade-in-out {
-0% {
-  opacity: 1
-}
-
-25% {
-  opacity: 1
-}
-
-26% {
-  opacity: 0
-}
-
-89% {
-  opacity: 0
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 1
-}
-
-}
-
-@-webkit-keyframes layer-2-fade-in-out {
-0% {
-  opacity: 0
-}
-
-15% {
-  opacity: 0
-}
-
-25% {
-  opacity: 1
-}
-
-50% {
-  opacity: 1
-}
-
-51% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes layer-2-fade-in-out {
-0% {
-  opacity: 0
-}
-
-15% {
-  opacity: 0
-}
-
-25% {
-  opacity: 1
-}
-
-50% {
-  opacity: 1
-}
-
-51% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@-webkit-keyframes layer-3-fade-in-out {
-0% {
-  opacity: 0
-}
-
-40% {
-  opacity: 0
-}
-
-50% {
-  opacity: 1
-}
-
-75% {
-  opacity: 1
-}
-
-76% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes layer-3-fade-in-out {
-0% {
-  opacity: 0
-}
-
-40% {
-  opacity: 0
-}
-
-50% {
-  opacity: 1
-}
-
-75% {
-  opacity: 1
-}
-
-76% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@-webkit-keyframes layer-4-fade-in-out {
-0% {
-  opacity: 0
-}
-
-65% {
-  opacity: 0
-}
-
-75% {
-  opacity: 1
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes layer-4-fade-in-out {
-0% {
-  opacity: 0
-}
-
-65% {
-  opacity: 0
-}
-
-75% {
-  opacity: 1
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-.circle-clipper {
-  display: inline-block;
-        position: relative;
-        width: 50%;
-        height: 100%;
-        overflow: hidden;
-        border-color: inherit;
-}
-
-.spinner-layer::after {
-  left: 45%;
-        width: 10%;
-        border-top-style: solid;
-}
-
-.spinner-layer::after, .circle-clipper::after {
-  content: '';
-        box-sizing: border-box;
-        position: absolute;
-        top: 0;
-        border-width: var(--paper-spinner-stroke-width, 3px);
-        border-color: inherit;
-        border-radius: 50%;
-}
-
-.circle-clipper::after {
-  bottom: 0;
-        width: 200%;
-        border-style: solid;
-        border-bottom-color: transparent !important;
-}
-
-.circle-clipper.left::after {
-  left: 0;
-        border-right-color: transparent !important;
-        -webkit-transform: rotate(129deg);
-        transform: rotate(129deg);
-}
-
-.circle-clipper.right::after {
-  left: -100%;
-        border-left-color: transparent !important;
-        -webkit-transform: rotate(-129deg);
-        transform: rotate(-129deg);
-}
-
-.active .gap-patch::after, .active .circle-clipper::after {
-  -webkit-animation-duration: var(--paper-spinner-expand-contract-duration);
-        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        -webkit-animation-iteration-count: infinite;
-        animation-duration: var(--paper-spinner-expand-contract-duration);
-        animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        animation-iteration-count: infinite;
-}
-
-.active .circle-clipper.left::after {
-  -webkit-animation-name: left-spin;
-        animation-name: left-spin;
-}
-
-.active .circle-clipper.right::after {
-  -webkit-animation-name: right-spin;
-        animation-name: right-spin;
-}
-
-@-webkit-keyframes left-spin {
-0% {
-  -webkit-transform: rotate(130deg)
-}
-
-50% {
-  -webkit-transform: rotate(-5deg)
-}
-
-to {
-  -webkit-transform: rotate(130deg)
-}
-
-}
-
-@keyframes left-spin {
-0% {
-  transform: rotate(130deg)
-}
-
-50% {
-  transform: rotate(-5deg)
-}
-
-to {
-  transform: rotate(130deg)
-}
-
-}
-
-@-webkit-keyframes right-spin {
-0% {
-  -webkit-transform: rotate(-130deg)
-}
-
-50% {
-  -webkit-transform: rotate(5deg)
-}
-
-to {
-  -webkit-transform: rotate(-130deg)
-}
-
-}
-
-@keyframes right-spin {
-0% {
-  transform: rotate(-130deg)
-}
-
-50% {
-  transform: rotate(5deg)
-}
-
-to {
-  transform: rotate(-130deg)
-}
-
-}
-
-#spinnerContainer.cooldown {
-  -webkit-animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezier(0.4, 0.0, 0.2, 1);
-        animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezier(0.4, 0.0, 0.2, 1);
-}
-
-@-webkit-keyframes fade-out {
-0% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes fade-out {
-0% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-</style>
-  </template>
-</dom-module>
-<dom-module id="paper-spinner-lite" assetpath="chrome://resources/polymer/v1_0/paper-spinner/" css-build="shadow">
-  <template strip-whitespace="">
-    <style scope="paper-spinner-lite">:host {
-  display: inline-block;
-        position: relative;
-        width: 28px;
-        height: 28px;
-
-        
-        --paper-spinner-container-rotation-duration: 1568ms;
-
-        
-        --paper-spinner-expand-contract-duration: 1333ms;
-
-        
-        --paper-spinner-full-cycle-duration: 5332ms;
-
-        
-        --paper-spinner-cooldown-duration: 400ms;
-}
-
-#spinnerContainer {
-  width: 100%;
-        height: 100%;
-
-        
-        direction: ltr;
-}
-
-#spinnerContainer.active {
-  -webkit-animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite;
-        animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite;
-}
-
-@-webkit-keyframes container-rotate {
-to {
-  -webkit-transform: rotate(360deg)
-}
-
-}
-
-@keyframes container-rotate {
-to {
-  transform: rotate(360deg)
-}
-
-}
-
-.spinner-layer {
-  position: absolute;
-        width: 100%;
-        height: 100%;
-        opacity: 0;
-        white-space: nowrap;
-        border-color: var(--paper-spinner-color,var(--google-blue-500));
-}
-
-.layer-1 {
-  border-color: var(--paper-spinner-layer-1-color,var(--google-blue-500));
-}
-
-.layer-2 {
-  border-color: var(--paper-spinner-layer-2-color,var(--google-red-500));
-}
-
-.layer-3 {
-  border-color: var(--paper-spinner-layer-3-color,var(--google-yellow-500));
-}
-
-.layer-4 {
-  border-color: var(--paper-spinner-layer-4-color,var(--google-green-500));
-}
-
-.active .spinner-layer {
-  -webkit-animation-name: fill-unfill-rotate;
-        -webkit-animation-duration: var(--paper-spinner-full-cycle-duration);
-        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        -webkit-animation-iteration-count: infinite;
-        animation-name: fill-unfill-rotate;
-        animation-duration: var(--paper-spinner-full-cycle-duration);
-        animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        animation-iteration-count: infinite;
-        opacity: 1;
-}
-
-.active .spinner-layer.layer-1 {
-  -webkit-animation-name: fill-unfill-rotate, layer-1-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-1-fade-in-out;
-}
-
-.active .spinner-layer.layer-2 {
-  -webkit-animation-name: fill-unfill-rotate, layer-2-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-2-fade-in-out;
-}
-
-.active .spinner-layer.layer-3 {
-  -webkit-animation-name: fill-unfill-rotate, layer-3-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-3-fade-in-out;
-}
-
-.active .spinner-layer.layer-4 {
-  -webkit-animation-name: fill-unfill-rotate, layer-4-fade-in-out;
-        animation-name: fill-unfill-rotate, layer-4-fade-in-out;
-}
-
-@-webkit-keyframes fill-unfill-rotate {
-12.5% {
-  -webkit-transform: rotate(135deg)
-}
-
-25% {
-  -webkit-transform: rotate(270deg)
-}
-
-37.5% {
-  -webkit-transform: rotate(405deg)
-}
-
-50% {
-  -webkit-transform: rotate(540deg)
-}
-
-62.5% {
-  -webkit-transform: rotate(675deg)
-}
-
-75% {
-  -webkit-transform: rotate(810deg)
-}
-
-87.5% {
-  -webkit-transform: rotate(945deg)
-}
-
-to {
-  -webkit-transform: rotate(1080deg)
-}
-
-}
-
-@keyframes fill-unfill-rotate {
-12.5% {
-  transform: rotate(135deg)
-}
-
-25% {
-  transform: rotate(270deg)
-}
-
-37.5% {
-  transform: rotate(405deg)
-}
-
-50% {
-  transform: rotate(540deg)
-}
-
-62.5% {
-  transform: rotate(675deg)
-}
-
-75% {
-  transform: rotate(810deg)
-}
-
-87.5% {
-  transform: rotate(945deg)
-}
-
-to {
-  transform: rotate(1080deg)
-}
-
-}
-
-@-webkit-keyframes layer-1-fade-in-out {
-0% {
-  opacity: 1
-}
-
-25% {
-  opacity: 1
-}
-
-26% {
-  opacity: 0
-}
-
-89% {
-  opacity: 0
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 1
-}
-
-}
-
-@keyframes layer-1-fade-in-out {
-0% {
-  opacity: 1
-}
-
-25% {
-  opacity: 1
-}
-
-26% {
-  opacity: 0
-}
-
-89% {
-  opacity: 0
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 1
-}
-
-}
-
-@-webkit-keyframes layer-2-fade-in-out {
-0% {
-  opacity: 0
-}
-
-15% {
-  opacity: 0
-}
-
-25% {
-  opacity: 1
-}
-
-50% {
-  opacity: 1
-}
-
-51% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes layer-2-fade-in-out {
-0% {
-  opacity: 0
-}
-
-15% {
-  opacity: 0
-}
-
-25% {
-  opacity: 1
-}
-
-50% {
-  opacity: 1
-}
-
-51% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@-webkit-keyframes layer-3-fade-in-out {
-0% {
-  opacity: 0
-}
-
-40% {
-  opacity: 0
-}
-
-50% {
-  opacity: 1
-}
-
-75% {
-  opacity: 1
-}
-
-76% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes layer-3-fade-in-out {
-0% {
-  opacity: 0
-}
-
-40% {
-  opacity: 0
-}
-
-50% {
-  opacity: 1
-}
-
-75% {
-  opacity: 1
-}
-
-76% {
-  opacity: 0
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@-webkit-keyframes layer-4-fade-in-out {
-0% {
-  opacity: 0
-}
-
-65% {
-  opacity: 0
-}
-
-75% {
-  opacity: 1
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes layer-4-fade-in-out {
-0% {
-  opacity: 0
-}
-
-65% {
-  opacity: 0
-}
-
-75% {
-  opacity: 1
-}
-
-90% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-.circle-clipper {
-  display: inline-block;
-        position: relative;
-        width: 50%;
-        height: 100%;
-        overflow: hidden;
-        border-color: inherit;
-}
-
-.spinner-layer::after {
-  left: 45%;
-        width: 10%;
-        border-top-style: solid;
-}
-
-.spinner-layer::after, .circle-clipper::after {
-  content: '';
-        box-sizing: border-box;
-        position: absolute;
-        top: 0;
-        border-width: var(--paper-spinner-stroke-width, 3px);
-        border-color: inherit;
-        border-radius: 50%;
-}
-
-.circle-clipper::after {
-  bottom: 0;
-        width: 200%;
-        border-style: solid;
-        border-bottom-color: transparent !important;
-}
-
-.circle-clipper.left::after {
-  left: 0;
-        border-right-color: transparent !important;
-        -webkit-transform: rotate(129deg);
-        transform: rotate(129deg);
-}
-
-.circle-clipper.right::after {
-  left: -100%;
-        border-left-color: transparent !important;
-        -webkit-transform: rotate(-129deg);
-        transform: rotate(-129deg);
-}
-
-.active .gap-patch::after, .active .circle-clipper::after {
-  -webkit-animation-duration: var(--paper-spinner-expand-contract-duration);
-        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        -webkit-animation-iteration-count: infinite;
-        animation-duration: var(--paper-spinner-expand-contract-duration);
-        animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        animation-iteration-count: infinite;
-}
-
-.active .circle-clipper.left::after {
-  -webkit-animation-name: left-spin;
-        animation-name: left-spin;
-}
-
-.active .circle-clipper.right::after {
-  -webkit-animation-name: right-spin;
-        animation-name: right-spin;
-}
-
-@-webkit-keyframes left-spin {
-0% {
-  -webkit-transform: rotate(130deg)
-}
-
-50% {
-  -webkit-transform: rotate(-5deg)
-}
-
-to {
-  -webkit-transform: rotate(130deg)
-}
-
-}
-
-@keyframes left-spin {
-0% {
-  transform: rotate(130deg)
-}
-
-50% {
-  transform: rotate(-5deg)
-}
-
-to {
-  transform: rotate(130deg)
-}
-
-}
-
-@-webkit-keyframes right-spin {
-0% {
-  -webkit-transform: rotate(-130deg)
-}
-
-50% {
-  -webkit-transform: rotate(5deg)
-}
-
-to {
-  -webkit-transform: rotate(-130deg)
-}
-
-}
-
-@keyframes right-spin {
-0% {
-  transform: rotate(-130deg)
-}
-
-50% {
-  transform: rotate(5deg)
-}
-
-to {
-  transform: rotate(-130deg)
-}
-
-}
-
-#spinnerContainer.cooldown {
-  -webkit-animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezier(0.4, 0.0, 0.2, 1);
-        animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezier(0.4, 0.0, 0.2, 1);
-}
-
-@-webkit-keyframes fade-out {
-0% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-@keyframes fade-out {
-0% {
-  opacity: 1
-}
-
-to {
-  opacity: 0
-}
-
-}
-
-</style>
-
-    <div id="spinnerContainer" class-name="[[__computeContainerClasses(active, __coolingDown)]]">
-      <div class="spinner-layer">
-        <div class="circle-clipper left"></div>
-        <div class="circle-clipper right"></div>
-      </div>
-    </div>
-  </template>
-
-  </dom-module>
-<iron-iconset-svg name="cr" size="24">
-  <svg>
-    <defs>
-      
-      <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
-      <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g>
-      <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
-      <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g>
-<if expr="chromeos">
-      <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
-</if>
-      <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
-      <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
-      <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
-      <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></g>
-      <g id="domain"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"></path></g>
-      <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path></g>
-      <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path></g>
-      <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"></path></g>
-      <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
-      <g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path></g>
-      <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g>
-      <g id="group"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"></path></g>
-      <g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g>
-      <g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
-      <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path></g>
-      <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
-      <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
-      <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
-      <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
-      <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
-      <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
-    </defs>
-  </svg>
-</iron-iconset-svg>
-<dom-module id="cr-toolbar-search-field" assetpath="chrome://resources/cr_elements/cr_toolbar/" css-build="shadow">
-  <template>
-    <style scope="cr-toolbar-search-field">:host {
-  align-items: center;
-        display: flex;
-        height: 40px;
-        transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
-            width 150ms cubic-bezier(0.4, 0, 0.2, 1);
-        width: 44px;
-}
-
-[hidden] {
-  display: none !important;
-}
-
-paper-icon-button {
-  height: 32px;
-        margin: 6px;
-        min-width: 32px;
-        padding: 6px;
-        width: 32px;
-}
-
-#icon {
-  --paper-icon-button-ink-color: white;
-        transition: margin 150ms, opacity 200ms;
-}
-
-#prompt {
-  opacity: 0;
-}
-
-paper-spinner-lite {
-  ;
-        --paper-spinner-color: white;
-        margin: 0 6px;
-        opacity: 0;
-        padding: 6px;
-        position: absolute;
-}
-
-paper-spinner-lite[active] {
-  opacity: 1;
-}
-
-#prompt, paper-spinner-lite {
-  transition: opacity 200ms;
-}
-
-#searchTerm {
-  -webkit-font-smoothing: antialiased;
-        -webkit-margin-start: 2px;
-        flex: 1;
-        line-height: 185%;
-        position: relative;
-}
-
-label {
-  bottom: 0;
-        cursor: text;
-        left: 0;
-        overflow: hidden;
-        position: absolute;
-        right: 0;
-        top: 0;
-        white-space: nowrap;
-}
-
-:host([has-search-text]) label {
-  visibility: hidden;
-}
-
-input {
-  -webkit-appearance: none;
-        background: transparent;
-        border: none;
-        color: white;
-        font: inherit;
-        outline: none;
-        padding: 0;
-        position: relative;
-        width: 100%;
-}
-
-input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button, input[type='search']::-webkit-search-results-button {
-  -webkit-appearance: none;
-}
-
-:host(:not([narrow])) {
-  -webkit-padding-end: 0;
-        background: rgba(0, 0, 0, 0.22);
-        border-radius: 2px;
-        cursor: text;
-        width: var(--cr-toolbar-field-width);
-}
-
-:host(:not([narrow]):not([showing-search])) #icon, :host(:not([narrow])) #prompt {
-  opacity: 0.7;
-}
-
-:host([narrow]:not([showing-search])) #searchTerm {
-  display: none;
-}
-
-:host([showing-search][spinner-active]) #icon {
-  opacity: 0;
-}
-
-:host([narrow][showing-search]) {
-  width: 100%;
-}
-
-:host([narrow][showing-search]) #icon, :host([narrow][showing-search]) paper-spinner-lite {
-  -webkit-margin-start: 18px;
-}
-
-</style>
-    <template is="dom-if" if="[[isSpinnerShown_]]">
-      <paper-spinner-lite active="">
-      </paper-spinner-lite>
-    </template>
-    <paper-icon-button id="icon" icon="cr:search" title="[[label]]" tabindex$="[[computeIconTabIndex_(narrow)]]">
-    </paper-icon-button>
-    <div id="searchTerm">
-      <label id="prompt" for="searchInput">[[label]]</label>
-      <input id="searchInput" type="search" on-input="onSearchTermInput" on-search="onSearchTermSearch" on-keydown="onSearchTermKeydown_" on-focus="onInputFocus_" on-blur="onInputBlur_" incremental="" autofocus="">
-      
-    </div>
-    <template is="dom-if" if="[[hasSearchText]]">
-      <paper-icon-button icon="cr:cancel" id="clearSearch" title="[[clearLabel]]" on-tap="clearSearch_">
-      </paper-icon-button>
-    </template>
-  </template>
-  </dom-module>
-<dom-module id="cr-toolbar" assetpath="chrome://resources/cr_elements/cr_toolbar/" css-build="shadow">
-  <template>
-    <style scope="cr-toolbar">:host {
-  --cr-toolbar-field-width: 580px;
-        --cr-toolbar-height: 56px;
-        align-items: center;
-        color: #fff;
-        display: flex;
-        height: var(--cr-toolbar-height);
-}
-
-h1 {
-  -webkit-margin-start: 6px;
-        -webkit-padding-end: 12px;
-        flex: 1;
-        font-size: 123%;
-        font-weight: 400;
-        text-overflow: ellipsis;
-        overflow: hidden;
-        white-space: nowrap;
-}
-
-#leftContent {
-  -webkit-margin-start: 12px;
-        position: relative;
-        transition: opacity 100ms;
-}
-
-#leftSpacer {
-  -webkit-margin-start: 6px;
-        align-items: center;
-        display: flex;
-}
-
-#menuButton {
-  height: 32px;
-        margin-bottom: 6px;
-        margin-top: 6px;
-        min-width: 32px;
-        padding: 6px;
-        width: 32px;
-}
-
-#centeredContent {
-  display: flex;
-        flex: 1 1 0;
-        justify-content: center;
-}
-
-#rightContent {
-  -webkit-margin-end: 12px;
-}
-
-:host([narrow_]) #centeredContent {
-  justify-content: flex-end;
-}
-
-:host([narrow_][showing-search_]) #leftContent {
-  position: absolute;
-        opacity: 0;
-}
-
-:host(:not([narrow_])) #leftContent {
-  flex: 1 1 var(--cr-toolbar-field-margin, 0);
-}
-
-:host(:not([narrow_])) #rightContent {
-  flex: 1 1 0;
-        text-align: end;
-}
-
-#menuPromo {
-  -webkit-padding-end: 12px;
-        -webkit-padding-start: 8px;
-        align-items: center;
-        background: #616161;
-        border-radius: 2px;
-        color: white;
-        display: flex;
-        font-size: 92.3%;
-        font-weight: 500;
-        opacity: 0;
-        padding-bottom: 6px;
-        padding-top: 6px;
-        position: absolute;
-        top: var(--cr-toolbar-height);
-        white-space: nowrap;
-        z-index: 2;
-}
-
-#menuPromo::before {
-  background: inherit;
-        
-        clip-path: polygon(0 105%, 100% 105%, 50% 0);
-        content: '';
-        display: block;
-        left: 10px;
-        height: 6px;
-        position: absolute;
-        top: -6px;
-        width: 12px;
-}
-
-:host-context([dir=rtl]) #menuPromo::before {
-  left: auto;
-        right: 10px;
-}
-
-#closePromo {
-  -webkit-appearance: none;
-        -webkit-margin-start: 12px;
-        background: none;
-        border: none;
-        color: inherit;
-        font-size: 20px;  
-        line-height: 20px;
-        padding: 0;
-        width: 20px;
-}
-
-</style>
-    <div id="leftContent">
-      <div id="leftSpacer">
-        
-        <template is="dom-if" if="[[showMenu]]" restamp="">
-          <paper-icon-button id="menuButton" icon="cr:menu" on-tap="onMenuTap_" title="[[titleIfNotShowMenuPromo_(menuLabel, showMenuPromo)]]" aria-label$="[[menuLabel]]">
-          </paper-icon-button>
-          <template is="dom-if" if="[[showMenuPromo]]">
-            <div id="menuPromo" role="tooltip">
-              [[menuPromo]]
-              <button id="closePromo" on-tap="onClosePromoTap_" aria-label$="[[closeMenuPromo]]">✕</button>
-            
-          </div></template>
-        </template>
-        <h1>[[pageName]]</h1>
-      </div>
-    </div>
-
-    <div id="centeredContent">
-      <cr-toolbar-search-field id="search" narrow="[[narrow_]]" label="[[searchPrompt]]" clear-label="[[clearLabel]]" spinner-active="[[spinnerActive]]" showing-search="{{showingSearch_}}">
-      </cr-toolbar-search-field>
-      <iron-media-query query="(max-width: 900px)" query-matches="{{narrow_}}">
-      </iron-media-query>
-    </div>
-
-    <div id="rightContent">
-      <content select=".more-actions"></content>
-    </div>
-  </template>
-  </dom-module>
-<dom-module id="downloads-toolbar" assetpath="chrome://downloads/" css-build="shadow">
-  <template>
-    <style scope="downloads-toolbar">:host {
-  align-items: center;
-        background: var(--md-toolbar-color);
-        color: white;
-        display: flex;
-        min-height: 56px;
-}
-
-[hidden] {
-  display: none !important;
-}
-
-#toolbar {
-  --cr-toolbar-field-width: var(--downloads-card-width);
-        flex: 1;
-}
-
-paper-icon-button {
-  --iron-icon-height: 20px;
-        --iron-icon-width: 20px;
-        --paper-icon-button_-_height:  32px; --paper-icon-button_-_padding:  6px; --paper-icon-button_-_width:  32px;;
-}
-
-#more {
-  --paper-menu-button_-_padding:  6px;;
-}
-
-paper-menu {
-  --paper-menu-selected-item_-_font-weight:  normal;;
-}
-
-paper-item {
-  -webkit-user-select: none;
-        cursor: pointer;
-        font: inherit;
-        min-height: 40px;
-        
-        white-space: nowrap;
-}
-
-</style>
-    <cr-toolbar id="toolbar" page-name="$i18n{title}" search-prompt="$i18n{search}" clear-label="$i18n{clearSearch}" spinner-active="{{spinnerActive}}" on-search-changed="onSearchChanged_">
-      <div class="more-actions">
-        <paper-menu-button id="more" horizontal-align="right" allow-outside-scroll="">
-          <paper-icon-button icon="cr:more-vert" title="$i18n{moreActions}" class="dropdown-trigger"></paper-icon-button>
-          <paper-menu class="dropdown-content">
-            <paper-item class="clear-all" on-tap="onClearAllTap_" role="menuitem" on-blur="onItemBlur_">
-              $i18n{clearAll}
-            </paper-item>
-            <paper-item on-tap="onOpenDownloadsFolderTap_" role="menuitem" on-blur="onItemBlur_">
-              $i18n{openDownloadsFolder}
-            </paper-item>
-          </paper-menu>
-        </paper-menu-button>
-      </div>
-    </cr-toolbar>
-  </template>
-  </dom-module>
-<style>
-/* Copyright 2016 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. */
-
-:root {
-  /* This is a custom, Chrome-specific color that does not have a --paper or
-   * --google equivalent. */
-  --md-background-color: #f1f1f1;
-  --md-loading-message-color: #6e6e6e;
-  /* This is --google-blue-700, rewritten as a native custom property for speed.
-   */
-  --md-toolbar-color: rgb(51, 103, 214);
-}
-
-</style><dom-module id="downloads-manager" assetpath="chrome://downloads/" css-build="shadow">
-  <template>
-    <style scope="downloads-manager">:host {
-  display: flex;
-        flex: 1 0;
-        flex-direction: column;
-        height: 100%;
-        z-index: 0;
-}
-
-[hidden] {
-  display: none !important;
-}
-
-@media screen and (max-width: 1024px) {
-:host {
-  flex-basis: calc(
-              var(--downloads-card-width) + 2 * var(--downloads-card-margin));
-}
-
-}
-
-#toolbar {
-  position: relative;
-        z-index: 1;
-}
-
-#toolbar::after {
-  box-shadow: inset 0 5px 6px -3px rgba(0, 0, 0, 0.4);
-        content: '';
-        display: block;
-        height: 6px;
-        opacity: 0;
-        position: absolute;
-        top: 100%;
-        transition: opacity 500ms;
-        width: 100%;
-}
-
-:host([has-shadow_]) #toolbar::after {
-  opacity: 1;
-}
-
-#downloads-list {
-  overflow-y: overlay !important;
-}
-
-#no-downloads, #downloads-list {
-  flex: 1;
-}
-
-:host([loading]) #no-downloads, :host([loading]) #downloads-list {
-  display: none;
-}
-
-#no-downloads {
-  align-items: center;
-        color: #6e6e6e;
-        display: flex;
-        font-size: 123.1%;
-        font-weight: 500;
-        justify-content: center;
-        
-        min-height: min-content;
-}
-
-#no-downloads .illustration {
-  background: -webkit-image-set(
-            url("chrome://downloads/1x/no_downloads.png") 1x,
-            url("chrome://downloads/2x/no_downloads.png") 2x)
-            no-repeat center center;
-        height: 144px;  
-        margin-bottom: 32px;
-}
-
-</style>
-
-    <downloads-toolbar id="toolbar" spinner-active="{{spinnerActive_}}">
-    </downloads-toolbar>
-    <iron-list id="downloads-list" items="{{items_}}" hidden="[[!hasDownloads_]]">
-      <template>
-        <downloads-item data="[[item]]"></downloads-item>
-      </template>
-    </iron-list>
-    <div id="no-downloads" hidden="[[hasDownloads_]]">
-      <div>
-        <div class="illustration"></div>
-        <span>[[noDownloadsText_(inSearchMode_)]]</span>
-      </div>
-    </div>
-  </template>
-  </dom-module>
-</div><script src="crisper.js"></script></body></html>
\ No newline at end of file
diff --git a/chrome/browser/resources/unpack_pak.py b/chrome/browser/resources/unpack_pak.py
new file mode 100755
index 0000000..ce6a993
--- /dev/null
+++ b/chrome/browser/resources/unpack_pak.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# Copyright 2016 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.
+
+import os
+import re
+import sys
+
+
+_HERE_PATH = os.path.join(os.path.dirname(__file__))
+
+
+_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..'))
+sys.path.append(os.path.join(_SRC_PATH, 'tools', 'grit'))
+from grit.format import data_pack
+
+
+def unpack(pak_path, out_path):
+  pak_dir = os.path.dirname(pak_path)
+  pak_id = os.path.splitext(os.path.basename(pak_path))[0]
+
+  data = data_pack.DataPack.ReadDataPack(pak_path)
+
+  # Associate numerical grit IDs to strings.
+  # For example 120045 -> 'IDR_SETTINGS_ABOUT_PAGE_HTML'
+  resource_ids = dict()
+  resources_path = os.path.join(pak_dir, 'grit', pak_id + '.h')
+  with open(resources_path) as resources_file:
+    for line in resources_file:
+      res = re.match('#define ([^ ]+) (\d+)', line)
+      if res:
+        resource_ids[int(res.group(2))] = res.group(1)
+  assert resource_ids
+
+  # Associate numerical string IDs to files.
+  resource_filenames = dict()
+  resources_map_path = os.path.join(pak_dir, 'grit', pak_id + '_map.cc')
+  with open(resources_map_path) as resources_map:
+    for line in resources_map:
+      res = re.match('  {"([^"]+)", ([^}]+)', line)
+      if res:
+        resource_filenames[res.group(2)] = res.group(1)
+  assert resource_filenames
+
+  # Extract packed files, while preserving directory structure.
+  for (resource_id, text) in data.resources.iteritems():
+    filename = resource_filenames[resource_ids[resource_id]]
+    dirname = os.path.join(out_path, os.path.dirname(filename))
+    if not os.path.exists(dirname):
+      os.makedirs(dirname)
+    with open(os.path.join(out_path, filename), 'w') as file:
+      file.write(text)
diff --git a/chrome/browser/resources/vulcanize.gni b/chrome/browser/resources/vulcanize.gni
new file mode 100644
index 0000000..c9f9dbe
--- /dev/null
+++ b/chrome/browser/resources/vulcanize.gni
@@ -0,0 +1,54 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+template("vulcanize") {
+  action(target_name) {
+    script = "//chrome/browser/resources/vulcanize_gn.py"
+
+    # Declare dependencies to all involved tools.
+    inputs = [
+      "//chrome/browser/resources/unpack_pak.py",
+      "//third_party/node/node_modules.tar.gz.sha1",
+    ]
+
+    if (is_linux) {
+      inputs += [ "//third_party/node/linux/node-linux-x64.tar.gz.sha1" ]
+    }
+    if (is_win) {
+      inputs += [ "//third_party/node/win/node.exe.sha1" ]
+    }
+    if (is_mac) {
+      inputs += [ "//third_party/node/mac/node-darwin-x64.tar.gz.sha1" ]
+    }
+
+    depfile = "${target_gen_dir}/${target_name}.d"
+
+    outputs = [
+      "$target_gen_dir/${invoker.html_out_file}",
+      "$target_gen_dir/${invoker.js_out_file}",
+    ]
+    deps = invoker.deps
+
+    # Note that we have to manually pass the sources to our script if the
+    # script needs them as inputs.
+    args = [
+      "--host",
+      invoker.host,
+      "--html_in_file",
+      invoker.html_in_file,
+      "--html_out_file",
+      invoker.html_out_file,
+      "--js_out_file",
+      invoker.js_out_file,
+      "--input_type",
+      invoker.input_type,
+      "--input",
+      invoker.input,
+      "--out_folder",
+      rebase_path(target_gen_dir, root_build_dir),
+      "--depfile",
+      rebase_path(depfile, root_build_dir),
+    ]
+  }
+}
diff --git a/chrome/browser/resources/vulcanize_gn.py b/chrome/browser/resources/vulcanize_gn.py
new file mode 100755
index 0000000..0b2df59a
--- /dev/null
+++ b/chrome/browser/resources/vulcanize_gn.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python
+# Copyright 2016 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.
+
+import argparse
+import itertools
+import os
+import platform
+import re
+import subprocess
+import sys
+import tempfile
+
+
+_HERE_PATH = os.path.dirname(__file__)
+_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..'))
+_CWD = os.getcwd()
+
+sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
+import node
+import node_modules
+
+
+_RESOURCES_PATH = os.path.join(_SRC_PATH, 'ui', 'webui', 'resources')
+
+
+_CR_ELEMENTS_PATH = os.path.join(_RESOURCES_PATH, 'cr_elements')
+
+
+_CSS_RESOURCES_PATH = os.path.join(_RESOURCES_PATH, 'css')
+
+
+_HTML_RESOURCES_PATH = os.path.join(_RESOURCES_PATH, 'html')
+
+
+_JS_RESOURCES_PATH = os.path.join(_RESOURCES_PATH, 'js')
+
+
+_POLYMER_PATH = os.path.join(
+    _SRC_PATH, 'third_party', 'polymer', 'v1_0', 'components-chromium')
+
+
+_VULCANIZE_BASE_ARGS = [
+  '--exclude', 'crisper.js',
+
+  # These files are already combined and minified.
+  '--exclude', 'chrome://resources/html/polymer.html',
+  '--exclude', 'web-animations-next-lite.min.js',
+
+  # These files are dynamically created by C++.
+  '--exclude', 'load_time_data.js',
+  '--exclude', 'strings.js',
+  '--exclude', 'text_defaults.css',
+  '--exclude', 'text_defaults_md.css',
+
+  '--inline-css',
+  '--inline-scripts',
+  '--strip-comments',
+]
+
+
+_URL_MAPPINGS = [
+    ('chrome://resources/cr_elements/', _CR_ELEMENTS_PATH),
+    ('chrome://resources/css/', _CSS_RESOURCES_PATH),
+    ('chrome://resources/html/', _HTML_RESOURCES_PATH),
+    ('chrome://resources/js/', _JS_RESOURCES_PATH),
+    ('chrome://resources/polymer/v1_0/', _POLYMER_PATH)
+]
+
+
+_VULCANIZE_REDIRECT_ARGS = list(itertools.chain.from_iterable(map(
+    lambda m: ['--redirect', '"%s|%s"' % (m[0], m[1])], _URL_MAPPINGS)))
+
+
+_REQUEST_LIST_FILE = 'request_list.txt'
+
+
+_PAK_UNPACK_FOLDER = 'flattened'
+
+
+def _run_node(cmd_parts, stdout=None):
+  cmd = " ".join([node.GetBinaryPath()] + cmd_parts)
+  process = subprocess.Popen(
+      cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+  stdout, stderr = process.communicate()
+
+  if stderr:
+    print >> sys.stderr, '%s failed: %s' % (cmd, stderr)
+    raise
+
+  return stdout
+
+
+def _undo_mapping(mappings, url):
+  for (redirect_url, file_path) in mappings:
+    if url.startswith(redirect_url):
+      return url.replace(redirect_url, file_path + os.sep)
+  return url
+
+
+# Get a list of all files that were bundled with Vulcanize and update the
+# depfile accordingly such that Ninja knows when to trigger re-vulcanization.
+def _update_dep_file(in_folder, args):
+  in_path = os.path.join(_CWD, in_folder)
+  out_path = os.path.join(_CWD, args.out_folder)
+
+  # Prior call to vulcanize already generated the deps list, grab it from there.
+  request_list = open(os.path.join(
+      out_path, _REQUEST_LIST_FILE), 'r').read().splitlines()
+
+  # Undo the URL mappings applied by vulcanize to get file paths relative to
+  # current working directory.
+  url_mappings = _URL_MAPPINGS + [
+      ('/', os.path.relpath(in_path, _CWD)),
+      ('chrome://%s/' % args.host, os.path.relpath(in_path, _CWD)),
+  ]
+
+  dependencies = map(
+      lambda url: _undo_mapping(url_mappings, url), request_list)
+
+  # If the input was a .pak file, the generated depfile should not list files
+  # already in the .pak file.
+  filtered_dependencies = dependencies
+  if (args.input_type == 'PAK_FILE'):
+    filter_url = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER)
+    filtered_dependencies = filter(
+        lambda url: not url.startswith(filter_url), dependencies)
+
+  with open(os.path.join(_CWD, args.depfile), 'w') as f:
+    f.write(os.path.join(
+        args.out_folder, args.html_out_file) + ': ' + ' '.join(
+            filtered_dependencies))
+
+
+def _vulcanize(in_folder, out_folder, host, html_in_file,
+               html_out_file, js_out_file):
+  in_path = os.path.normpath(os.path.join(_CWD, in_folder))
+  out_path = os.path.join(_CWD, out_folder)
+
+  html_out_path = os.path.join(out_path, html_out_file)
+  js_out_path = os.path.join(out_path, js_out_file)
+
+  output = _run_node(
+      [node_modules.PathToVulcanize()] +
+      _VULCANIZE_BASE_ARGS + _VULCANIZE_REDIRECT_ARGS +
+      ['--out-request-list', os.path.join(out_path, _REQUEST_LIST_FILE),
+       '--redirect', '"/|%s"' % in_path,
+       '--redirect', '"chrome://%s/|%s"' % (host, in_path),
+       # TODO(dpapad): Figure out why vulcanize treats the input path
+       # differently on Windows VS Linux/Mac.
+       os.path.join(
+           in_path if platform.system() == 'Windows' else os.sep,
+           html_in_file)])
+
+  with tempfile.NamedTemporaryFile(mode='wt+', delete=False) as tmp:
+    # Grit includes are not supported, use HTML imports instead.
+    tmp.write(output.replace(
+        '<include src="', '<include src-disabled="'))
+
+  try:
+    _run_node([node_modules.PathToCrisper(),
+             '--source', tmp.name,
+             '--script-in-head', 'false',
+             '--html', html_out_path,
+             '--js', js_out_path])
+
+    # TODO(tsergeant): Remove when JS resources are minified by default:
+    # crbug.com/619091.
+    _run_node([node_modules.PathToUglifyJs(), js_out_path,
+              '--comments', '"/Copyright|license|LICENSE|\<\/?if/"',
+              '--output', js_out_path])
+  finally:
+    os.remove(tmp.name)
+
+
+def _css_build(out_folder, files):
+  out_path = os.path.join(_CWD, out_folder)
+  paths = map(lambda f: os.path.join(out_path, f), files)
+
+  _run_node([node_modules.PathToPolymerCssBuild()] + paths)
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--depfile')
+  parser.add_argument('--host')
+  parser.add_argument('--html_in_file')
+  parser.add_argument('--html_out_file')
+  parser.add_argument('--input')
+  parser.add_argument('--input_type')
+  parser.add_argument('--js_out_file')
+  parser.add_argument('--out_folder')
+  args = parser.parse_args()
+  args.input = os.path.normpath(args.input)
+
+  vulcanize_input_folder = args.input
+
+  # If a .pak file was specified, unpack that file first and pass the output to
+  # vulcanize.
+  if (args.input_type == 'PAK_FILE'):
+    import unpack_pak
+    input_folder = os.path.join(_CWD, args.input)
+    output_folder = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER)
+    unpack_pak.unpack(args.input, output_folder)
+    vulcanize_input_folder = output_folder
+
+  _vulcanize(vulcanize_input_folder, args.out_folder, args.host,
+             args.html_in_file, args.html_out_file, args.js_out_file)
+  _css_build(args.out_folder, files=[args.html_out_file])
+
+  _update_dep_file(vulcanize_input_folder, args)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc
index 615a7b6..7259e6b5 100644
--- a/chrome/browser/safe_browsing/local_database_manager.cc
+++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -271,7 +271,6 @@
     const scoped_refptr<SafeBrowsingService>& service)
     : sb_service_(service),
       database_(NULL),
-      enabled_(false),
       enable_download_protection_(false),
       enable_csd_whitelist_(false),
       enable_download_whitelist_(false),
@@ -692,12 +691,13 @@
 
 void LocalSafeBrowsingDatabaseManager::StopOnIOThread(bool shutdown) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  SafeBrowsingDatabaseManager::StopOnIOThread(shutdown);
 
   DoStopOnIOThread();
   if (shutdown) {
     sb_service_ = NULL;
   }
+
+  SafeBrowsingDatabaseManager::StopOnIOThread(shutdown);
 }
 
 void LocalSafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished(
diff --git a/chrome/browser/safe_browsing/local_database_manager.h b/chrome/browser/safe_browsing/local_database_manager.h
index 9a27a8e..c03fff31 100644
--- a/chrome/browser/safe_browsing/local_database_manager.h
+++ b/chrome/browser/safe_browsing/local_database_manager.h
@@ -330,10 +330,6 @@
   // Lock used to prevent possible data races due to compiler optimizations.
   mutable base::Lock database_lock_;
 
-  // Whether the service is running. 'enabled_' is used by the
-  // SafeBrowsingDatabaseManager on the IO thread during normal operations.
-  bool enabled_;
-
   // Indicate if download_protection is enabled by command switch
   // so we allow this feature to be exercised.
   bool enable_download_protection_;
diff --git a/chrome/browser/ui/views/find_bar_host.cc b/chrome/browser/ui/views/find_bar_host.cc
index 3554aed..5f51653 100644
--- a/chrome/browser/ui/views/find_bar_host.cc
+++ b/chrome/browser/ui/views/find_bar_host.cc
@@ -58,13 +58,11 @@
   if (!contents)
     return false;
 
-  content::RenderViewHost* render_view_host = contents->GetRenderViewHost();
-
   // Make sure we don't have a text field element interfering with keyboard
   // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
-  render_view_host->ClearFocusedElement();
+  contents->ClearFocusedElement();
   NativeWebKeyboardEvent event(key_event);
-  render_view_host->GetWidget()->ForwardKeyboardEvent(event);
+  contents->GetRenderViewHost()->GetWidget()->ForwardKeyboardEvent(event);
   return true;
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 73ece483..9ebe8c7 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1211,10 +1211,9 @@
     translate::TranslateErrors::Type error_type,
     bool is_user_gesture) {
   if (contents_web_view_->HasFocus() &&
-      !GetLocationBarView()->IsMouseHovered()) {
-    content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
-    if (rvh->IsFocusedElementEditable())
-      return ShowTranslateBubbleResult::EDITABLE_FIELD_IS_ACTIVE;
+      !GetLocationBarView()->IsMouseHovered() &&
+      web_contents->IsFocusedElementEditable()) {
+    return ShowTranslateBubbleResult::EDITABLE_FIELD_IS_ACTIVE;
   }
 
   translate::LanguageState& language_state =
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
index b625633..27543b4e 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
@@ -30,7 +30,7 @@
 void LocationBarBubbleDelegateView::WebContentMouseHandler::OnKeyEvent(
     ui::KeyEvent* event) {
   if ((event->key_code() == ui::VKEY_ESCAPE ||
-       web_contents_->GetRenderViewHost()->IsFocusedElementEditable()) &&
+       web_contents_->IsFocusedElementEditable()) &&
       event->type() == ui::ET_KEY_PRESSED)
     bubble_->CloseBubble();
 }
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
index c37cf06..5bb18d38 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
@@ -259,7 +259,7 @@
   EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(web_contents->GetRenderViewHost()->IsFocusedElementEditable());
+  EXPECT_TRUE(web_contents->IsFocusedElementEditable());
   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_K,
       false, false, false, false));
   EXPECT_FALSE(IsBubbleShowing());
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 02139e37..abd1edaf 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -24,6 +24,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/google/core/browser/google_util.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui.h"
@@ -47,11 +48,10 @@
       : content::WebContentsObserver(web_contents), is_md_(is_md) {}
   ~ExtensionWebUiTimer() override {}
 
-  void DidStartProvisionalLoadForFrame(
-      content::RenderFrameHost* render_frame_host,
-      const GURL& validated_url,
-      bool is_error_page) override {
-    timer_.reset(new base::ElapsedTimer());
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override {
+    if (navigation_handle->IsInMainFrame() && !navigation_handle->IsSamePage())
+      timer_.reset(new base::ElapsedTimer());
   }
 
   void DocumentLoadedInFrame(
@@ -70,12 +70,13 @@
   }
 
   void DocumentOnLoadCompletedInMainFrame() override {
-    // Sometimes*, DidStartProvisionalLoadForFrame() isn't called before this
-    // or DocumentLoadedInFrame(). Don't log anything in those cases.
-    // *This appears to be for in-page navigations like hash changes.
     // TODO(devlin): The usefulness of these metrics remains to be seen.
-    if (!timer_)
+    if (!timer_) {
+      // This object could have been created for a child RenderFrameHost so it
+      // would never get a DidStartNavigation with the main frame. However it
+      // will receive this current callback.
       return;
+    }
     if (is_md_) {
       UMA_HISTOGRAM_TIMES("Extensions.WebUi.LoadCompletedInMainFrame.MD",
                           timer_->Elapsed());
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 47316642..1c3d935 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -320,9 +320,7 @@
 
 void NetErrorHelper::LoadPageFromCache(const GURL& page_url) {
   blink::WebFrame* web_frame = render_frame()->GetWebFrame();
-  DCHECK(!base::EqualsASCII(
-      base::StringPiece16(web_frame->dataSource()->getRequest().httpMethod()),
-      "POST"));
+  DCHECK_NE("POST", web_frame->dataSource()->getRequest().httpMethod().ascii());
 
   blink::WebURLRequest request(page_url);
   request.setCachePolicy(blink::WebCachePolicy::ReturnCacheDataDontLoad);
diff --git a/chrome/renderer/safe_browsing/phishing_classifier.cc b/chrome/renderer/safe_browsing/phishing_classifier.cc
index d5babf6..a2246d5 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier.cc
@@ -135,9 +135,7 @@
   }
 
   blink::WebDataSource* ds = frame->dataSource();
-  if (!ds ||
-      !base::EqualsASCII(base::StringPiece16(ds->getRequest().httpMethod()),
-                         "GET")) {
+  if (!ds || ds->getRequest().httpMethod().ascii() != "GET") {
     if (ds)
       RecordReasonForSkippingClassificationToUMA(SKIP_NONE_GET);
     RunFailureCallback();
diff --git a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
index a0ac57c..ad85540 100644
--- a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
@@ -93,14 +93,14 @@
   // this issue.
   blink::WebURL CompleteURL(const blink::WebElement& element,
                             const blink::WebString& partial_url) override {
-    GURL parsed_url(GURL(partial_url.utf8()));
+    GURL parsed_url = blink::WebStringToGURL(partial_url);
     GURL full_url;
     if (parsed_url.has_scheme()) {
       // This is already a complete URL.
-      full_url = GURL(blink::WebStringToGURL(partial_url));
+      full_url = parsed_url;
     } else if (!base_domain_.empty()) {
       // This is a partial URL and only one frame in testing html.
-      full_url = GURL("http://" + base_domain_).Resolve(partial_url);
+      full_url = GURL("http://" + base_domain_).Resolve(partial_url.utf8());
     } else {
       auto it = url_to_frame_domain_map_.find(partial_url.utf8());
       if (it != url_to_frame_domain_map_.end()) {
diff --git a/chrome/test/data/webui/md_downloads/downloads_browsertest.js b/chrome/test/data/webui/md_downloads/downloads_browsertest.js
index 7b793ab4..b0c6979 100644
--- a/chrome/test/data/webui/md_downloads/downloads_browsertest.js
+++ b/chrome/test/data/webui/md_downloads/downloads_browsertest.js
@@ -15,10 +15,26 @@
  * @constructor
  * @extends {PolymerTest}
  */
+function DownloadsTest() {}
+
+DownloadsTest.prototype = {
+  __proto__: PolymerTest.prototype,
+
+  /** @override */
+  setUp: function() {
+    PolymerTest.prototype.setUp.call(this);
+    this.accessibilityAuditConfig.ignoreSelectors('humanLangMissing', 'html');
+  },
+};
+
+/**
+ * @constructor
+ * @extends {DownloadsTest}
+ */
 function DownloadsItemTest() {}
 
 DownloadsItemTest.prototype = {
-  __proto__: PolymerTest.prototype,
+  __proto__: DownloadsTest.prototype,
 
   /** @override */
   browsePreload: 'chrome://downloads/item.html',
@@ -33,18 +49,17 @@
   mocha.run();
 });
 
-
 /**
  * @constructor
- * @extends {PolymerTest}
+ * @extends {DownloadsTest}
  */
 function DownloadsLayoutTest() {}
 
 DownloadsLayoutTest.prototype = {
-  __proto__: PolymerTest.prototype,
+  __proto__: DownloadsTest.prototype,
 
   /** @override */
-  browsePreload: 'chrome://downloads/manager.html',
+  browsePreload: 'chrome://downloads/',
 
   /** @override */
   extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
@@ -58,12 +73,12 @@
 
 /**
  * @constructor
- * @extends {PolymerTest}
+ * @extends {DownloadsTest}
  */
 function DownloadsToolbarTest() {}
 
 DownloadsToolbarTest.prototype = {
-  __proto__: PolymerTest.prototype,
+  __proto__: DownloadsTest.prototype,
 
   /** @override */
   browsePreload: 'chrome://downloads/toolbar.html',
diff --git a/chrome/test/data/webui/md_downloads/toolbar_tests.js b/chrome/test/data/webui/md_downloads/toolbar_tests.js
index 5729be5..7f287c3 100644
--- a/chrome/test/data/webui/md_downloads/toolbar_tests.js
+++ b/chrome/test/data/webui/md_downloads/toolbar_tests.js
@@ -26,11 +26,11 @@
   });
 
   test('resize closes more options menu', function() {
-    MockInteractions.tap(toolbar.$$('paper-icon-button'));
-    assertTrue(toolbar.$.more.opened);
+    MockInteractions.tap(toolbar.$.moreActions);
+    assertTrue(toolbar.$.moreActionsMenu.open);
 
     window.dispatchEvent(new CustomEvent('resize'));
-    assertFalse(toolbar.$.more.opened);
+    assertFalse(toolbar.$.moreActionsMenu.open);
   });
 
   test('search starts spinner', function() {
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 9ffc7305..7f6700a 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -126,6 +126,7 @@
 
 mojom("arc_bindings") {
   sources = [
+    "common/accessibility_helper.mojom",
     "common/app.mojom",
     "common/arc_bridge.mojom",
     "common/audio.mojom",
diff --git a/components/arc/arc_bridge_host_impl.cc b/components/arc/arc_bridge_host_impl.cc
index b22068e5..437aa1a4 100644
--- a/components/arc/arc_bridge_host_impl.cc
+++ b/components/arc/arc_bridge_host_impl.cc
@@ -83,6 +83,12 @@
   OnClosed();
 }
 
+void ArcBridgeHostImpl::OnAccessibilityHelperInstanceReady(
+    mojom::AccessibilityHelperInstancePtr accessibility_helper_ptr) {
+  OnInstanceReady(arc_bridge_service_->accessibility_helper(),
+                  std::move(accessibility_helper_ptr));
+}
+
 void ArcBridgeHostImpl::OnAppInstanceReady(mojom::AppInstancePtr app_ptr) {
   OnInstanceReady(arc_bridge_service_->app(), std::move(app_ptr));
 }
diff --git a/components/arc/arc_bridge_host_impl.h b/components/arc/arc_bridge_host_impl.h
index b420725..9ee3664 100644
--- a/components/arc/arc_bridge_host_impl.h
+++ b/components/arc/arc_bridge_host_impl.h
@@ -38,6 +38,8 @@
   ~ArcBridgeHostImpl() override;
 
   // ArcBridgeHost overrides.
+  void OnAccessibilityHelperInstanceReady(
+      mojom::AccessibilityHelperInstancePtr accessibility_helper_ptr) override;
   void OnAppInstanceReady(mojom::AppInstancePtr app_ptr) override;
   void OnAudioInstanceReady(mojom::AudioInstancePtr audio_ptr) override;
   void OnAuthInstanceReady(mojom::AuthInstancePtr auth_ptr) override;
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h
index 3f4a5f5a3..b4b9fb1 100644
--- a/components/arc/arc_bridge_service.h
+++ b/components/arc/arc_bridge_service.h
@@ -21,6 +21,7 @@
 
 // Instead of including components/arc/common/arc_bridge.mojom.h, list all the
 // instance classes here for faster build.
+class AccessibilityHelperInstance;
 class AppInstance;
 class AudioInstance;
 class AuthInstance;
@@ -61,6 +62,9 @@
   // Returns true if ARC is available on the current board.
   static bool GetAvailable(const base::CommandLine* command_line);
 
+  InstanceHolder<mojom::AccessibilityHelperInstance>* accessibility_helper() {
+    return &accessibility_helper_;
+  }
   InstanceHolder<mojom::AppInstance>* app() { return &app_; }
   InstanceHolder<mojom::AudioInstance>* audio() { return &audio_; }
   InstanceHolder<mojom::AuthInstance>* auth() { return &auth_; }
@@ -103,6 +107,7 @@
   InstanceHolder<mojom::WallpaperInstance>* wallpaper() { return &wallpaper_; }
 
  private:
+  InstanceHolder<mojom::AccessibilityHelperInstance> accessibility_helper_;
   InstanceHolder<mojom::AppInstance> app_;
   InstanceHolder<mojom::AudioInstance> audio_;
   InstanceHolder<mojom::AuthInstance> auth_;
diff --git a/components/arc/arc_session.cc b/components/arc/arc_session.cc
index c3dc195..92940393 100644
--- a/components/arc/arc_session.cc
+++ b/components/arc/arc_session.cc
@@ -9,6 +9,7 @@
 #include <poll.h>
 #include <unistd.h>
 
+#include <string>
 #include <utility>
 
 #include "base/files/file_path.h"
@@ -221,10 +222,10 @@
 
   // Synchronously accepts a connection on |socket_fd| and then processes the
   // connected socket's file descriptor.
-  static mojo::edk::ScopedPlatformHandle ConnectMojo(
+  static mojo::ScopedMessagePipeHandle ConnectMojo(
       mojo::edk::ScopedPlatformHandle socket_fd,
       base::ScopedFD cancel_fd);
-  void OnMojoConnected(mojo::edk::ScopedPlatformHandle fd);
+  void OnMojoConnected(mojo::ScopedMessagePipeHandle server_pipe);
 
   // Request to stop ARC instance via DBus.
   void StopArcInstance();
@@ -422,44 +423,52 @@
 }
 
 // static
-mojo::edk::ScopedPlatformHandle ArcSessionImpl::ConnectMojo(
+mojo::ScopedMessagePipeHandle ArcSessionImpl::ConnectMojo(
     mojo::edk::ScopedPlatformHandle socket_fd,
     base::ScopedFD cancel_fd) {
   if (!WaitForSocketReadable(socket_fd.get().handle, cancel_fd.get())) {
     VLOG(1) << "Mojo connection was cancelled.";
-    return mojo::edk::ScopedPlatformHandle();
+    return mojo::ScopedMessagePipeHandle();
   }
 
   mojo::edk::ScopedPlatformHandle scoped_fd;
   if (!mojo::edk::ServerAcceptConnection(socket_fd.get(), &scoped_fd,
                                          /* check_peer_user = */ false) ||
       !scoped_fd.is_valid()) {
-    return mojo::edk::ScopedPlatformHandle();
+    return mojo::ScopedMessagePipeHandle();
   }
 
   // Hardcode pid 0 since it is unused in mojo.
   const base::ProcessHandle kUnusedChildProcessHandle = 0;
   mojo::edk::PlatformChannelPair channel_pair;
+  std::string child_token = mojo::edk::GenerateRandomToken();
   mojo::edk::ChildProcessLaunched(kUnusedChildProcessHandle,
-                                  channel_pair.PassServerHandle(),
-                                  mojo::edk::GenerateRandomToken());
+                                  channel_pair.PassServerHandle(), child_token);
 
   mojo::edk::ScopedPlatformHandleVectorPtr handles(
       new mojo::edk::PlatformHandleVector{
           channel_pair.PassClientHandle().release()});
 
-  struct iovec iov = {const_cast<char*>(""), 1};
+  std::string token = mojo::edk::GenerateRandomToken();
+  // We need to send the length of the message as a single byte, so make sure it
+  // fits.
+  DCHECK_LT(token.size(), 256u);
+  uint8_t message_length = static_cast<uint8_t>(token.size());
+  struct iovec iov[] = {{&message_length, sizeof(message_length)},
+                        {const_cast<char*>(token.c_str()), token.size()}};
   ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
-      scoped_fd.get(), &iov, 1, handles->data(), handles->size());
+      scoped_fd.get(), iov, sizeof(iov) / sizeof(iov[0]), handles->data(),
+      handles->size());
   if (result == -1) {
     PLOG(ERROR) << "sendmsg";
-    return mojo::edk::ScopedPlatformHandle();
+    return mojo::ScopedMessagePipeHandle();
   }
 
-  return scoped_fd;
+  return mojo::edk::CreateParentMessagePipe(token, child_token);
 }
 
-void ArcSessionImpl::OnMojoConnected(mojo::edk::ScopedPlatformHandle fd) {
+void ArcSessionImpl::OnMojoConnected(
+    mojo::ScopedMessagePipeHandle server_pipe) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (state_ == State::STOPPED) {
@@ -477,14 +486,6 @@
     return;
   }
 
-  if (!fd.is_valid()) {
-    LOG(ERROR) << "Invalid handle";
-    StopArcInstance();
-    return;
-  }
-
-  mojo::ScopedMessagePipeHandle server_pipe =
-      mojo::edk::CreateMessagePipe(std::move(fd));
   if (!server_pipe.is_valid()) {
     LOG(ERROR) << "Invalid pipe";
     StopArcInstance();
diff --git a/components/arc/common/accessibility_helper.mojom b/components/arc/common/accessibility_helper.mojom
new file mode 100644
index 0000000..325006dc
--- /dev/null
+++ b/components/arc/common/accessibility_helper.mojom
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Next MinVersion: 1
+
+module arc.mojom;
+
+import "screen_rect.mojom";
+
+// AccessibilityEventType is a enum which corresponds to event types of
+// AccessibilityEvent in Android.
+// https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent.html
+[Extensible]
+enum AccessibilityEventType {
+  VIEW_FOCUSED,
+};
+
+// AccessibilityNodeInfoData is a struct to contain info of
+// AccessibilityNodeInfo in Android.
+// https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo.html
+struct AccessibilityNodeInfoData {
+  ScreenRect boundsInScreen;
+};
+
+// Next method ID: 1
+interface AccessibilityHelperHost {
+  // OnAccessibilityEvent is called when a converted Android accessibility event
+  // is sent from Android.
+  OnAccessibilityEvent@0(AccessibilityEventType eventType,
+                         AccessibilityNodeInfoData? eventSource);
+};
+
+// Next method ID: 1
+interface AccessibilityHelperInstance {
+  Init@0(AccessibilityHelperHost host);
+};
diff --git a/components/arc/common/arc_bridge.mojom b/components/arc/common/arc_bridge.mojom
index 94b0aa8..7b8a9c52 100644
--- a/components/arc/common/arc_bridge.mojom
+++ b/components/arc/common/arc_bridge.mojom
@@ -4,6 +4,7 @@
 
 module arc.mojom;
 
+import "accessibility_helper.mojom";
 import "app.mojom";
 import "audio.mojom";
 import "auth.mojom";
@@ -29,14 +30,18 @@
 import "video.mojom";
 import "wallpaper.mojom";
 
-// Next MinVersion: 21
+// Next MinVersion: 22
 // Deprecated method IDs: 101, 105
-// Next method ID: 127
+// Next method ID: 128
 interface ArcBridgeHost {
   // Keep the entries alphabetical. In order to do so without breaking
   // compatibility with the ARC instance, explicitly assign each interface a
   // unique ordinal.
 
+  // Notifies Chrome that the AccessibilityHelperInstance interface is ready.
+  [MinVersion=21] OnAccessibilityHelperInstanceReady@127(
+      AccessibilityHelperInstance instance_ptr);
+
   // Notifies Chrome that the AppInstance interface is ready.
   OnAppInstanceReady@100(AppInstance instance_ptr);
 
diff --git a/components/safe_browsing_db/database_manager.cc b/components/safe_browsing_db/database_manager.cc
index 91e4d7b6..0155efc 100644
--- a/components/safe_browsing_db/database_manager.cc
+++ b/components/safe_browsing_db/database_manager.cc
@@ -15,7 +15,7 @@
 
 namespace safe_browsing {
 
-SafeBrowsingDatabaseManager::SafeBrowsingDatabaseManager() {}
+SafeBrowsingDatabaseManager::SafeBrowsingDatabaseManager() : enabled_(false) {}
 
 SafeBrowsingDatabaseManager::~SafeBrowsingDatabaseManager() {
   DCHECK(!v4_get_hash_protocol_manager_);
@@ -37,8 +37,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(v4_get_hash_protocol_manager_);
 
-  // Make sure we can check this url.
-  if (!(url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme))) {
+  // Make sure we can check this url and that the service is enabled.
+  if (!enabled_ ||
+      !(url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme))) {
     return true;
   }
 
diff --git a/components/safe_browsing_db/database_manager.h b/components/safe_browsing_db/database_manager.h
index 018bf15..9399f78 100644
--- a/components/safe_browsing_db/database_manager.h
+++ b/components/safe_browsing_db/database_manager.h
@@ -196,12 +196,16 @@
 
   // Called to initialize objects that are used on the io_thread, such as the
   // v4 protocol manager.  This may be called multiple times during the life of
-  // the DatabaseManager. Must be called on IO thread.
+  // the DatabaseManager. Must be called on IO thread. All subclasses should
+  // override this method, set enabled_ to true and call the base class method
+  // at the top of it.
   virtual void StartOnIOThread(
       net::URLRequestContextGetter* request_context_getter,
       const V4ProtocolConfig& config);
 
-  // Called to stop or shutdown operations on the io_thread.
+  // Called to stop or shutdown operations on the io_thread. All subclasses
+  // should override this method, set enabled_ to false and call the base class
+  // method at the bottom of it.
   virtual void StopOnIOThread(bool shutdown);
 
  protected:
@@ -262,6 +266,10 @@
   // responsible for deleting them when removing from the set.
   ApiCheckSet api_checks_;
 
+  // Whether the service is running. 'enabled_' is used by the
+  // SafeBrowsingDatabaseManager on the IO thread during normal operations.
+  bool enabled_;
+
   // Created and destroyed via StartOnIOThread/StopOnIOThread.
   std::unique_ptr<V4GetHashProtocolManager> v4_get_hash_protocol_manager_;
 
diff --git a/components/safe_browsing_db/remote_database_manager.cc b/components/safe_browsing_db/remote_database_manager.cc
index 87f3c416..256c511 100644
--- a/components/safe_browsing_db/remote_database_manager.cc
+++ b/components/safe_browsing_db/remote_database_manager.cc
@@ -98,8 +98,7 @@
 //
 
 // TODO(nparker): Add more tests for this class
-RemoteSafeBrowsingDatabaseManager::RemoteSafeBrowsingDatabaseManager()
-    : enabled_(false) {
+RemoteSafeBrowsingDatabaseManager::RemoteSafeBrowsingDatabaseManager() {
   // Decide which resource types to check. These two are the minimum.
   resource_types_to_check_.insert(content::RESOURCE_TYPE_MAIN_FRAME);
   resource_types_to_check_.insert(content::RESOURCE_TYPE_SUB_FRAME);
diff --git a/components/safe_browsing_db/remote_database_manager.h b/components/safe_browsing_db/remote_database_manager.h
index 8ae6663..3327081 100644
--- a/components/safe_browsing_db/remote_database_manager.h
+++ b/components/safe_browsing_db/remote_database_manager.h
@@ -72,7 +72,6 @@
 
   // Requests currently outstanding.  This owns the ptrs.
   std::vector<ClientRequest*> current_requests_;
-  bool enabled_;
 
   std::set<content::ResourceType> resource_types_to_check_;
 
diff --git a/components/safe_browsing_db/test_database_manager.cc b/components/safe_browsing_db/test_database_manager.cc
index 3209bb39..b6805ac0 100644
--- a/components/safe_browsing_db/test_database_manager.cc
+++ b/components/safe_browsing_db/test_database_manager.cc
@@ -114,4 +114,16 @@
   return false;
 }
 
+void TestSafeBrowsingDatabaseManager::StartOnIOThread(
+    net::URLRequestContextGetter* request_context_getter,
+    const V4ProtocolConfig& config) {
+  SafeBrowsingDatabaseManager::StartOnIOThread(request_context_getter, config);
+  enabled_ = true;
+}
+
+void TestSafeBrowsingDatabaseManager::StopOnIOThread(bool shutdown) {
+  enabled_ = false;
+  SafeBrowsingDatabaseManager::StopOnIOThread(shutdown);
+}
+
 }  // namespace safe_browsing
diff --git a/components/safe_browsing_db/test_database_manager.h b/components/safe_browsing_db/test_database_manager.h
index 3dbf275..870807f 100644
--- a/components/safe_browsing_db/test_database_manager.h
+++ b/components/safe_browsing_db/test_database_manager.h
@@ -41,6 +41,9 @@
   bool IsDownloadProtectionEnabled() const override;
   bool IsMalwareKillSwitchOn() override;
   bool IsSupported() const override;
+  void StartOnIOThread(net::URLRequestContextGetter* request_context_getter,
+                       const V4ProtocolConfig& config) override;
+  void StopOnIOThread(bool shutdown) override;
 
  protected:
   ~TestSafeBrowsingDatabaseManager() override {};
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.cc b/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
index a1a640d..eba742b 100644
--- a/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
+++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
@@ -121,7 +121,7 @@
 
 const char kPermission[] = "permission";
 const char kPhaPatternType[] = "pha_pattern_type";
-const char kMalwarePatternType[] = "malware_pattern_type";
+const char kMalwareThreatType[] = "malware_threat_type";
 const char kSePatternType[] = "se_pattern_type";
 const char kLanding[] = "LANDING";
 const char kDistribution[] = "DISTRIBUTION";
@@ -593,7 +593,7 @@
              match.threat_type() == POTENTIALLY_HARMFUL_APPLICATION) {
     for (const ThreatEntryMetadata::MetadataEntry& m :
          match.threat_entry_metadata().entries()) {
-      if (m.key() == kPhaPatternType || m.key() == kMalwarePatternType) {
+      if (m.key() == kPhaPatternType || m.key() == kMalwareThreatType) {
         if (m.value() == kLanding) {
           metadata->threat_pattern_type = ThreatPatternType::MALWARE_LANDING;
           break;
diff --git a/components/safe_browsing_db/v4_local_database_manager.cc b/components/safe_browsing_db/v4_local_database_manager.cc
index ffef84e..58f7ae8 100644
--- a/components/safe_browsing_db/v4_local_database_manager.cc
+++ b/components/safe_browsing_db/v4_local_database_manager.cc
@@ -138,7 +138,6 @@
 
 V4LocalDatabaseManager::V4LocalDatabaseManager(const base::FilePath& base_path)
     : base_path_(base_path),
-      enabled_(false),
       list_infos_(GetListInfos()),
       weak_factory_(this) {
   DCHECK(!base_path_.empty());
diff --git a/components/safe_browsing_db/v4_local_database_manager.h b/components/safe_browsing_db/v4_local_database_manager.h
index 7db100dc..12d63a8 100644
--- a/components/safe_browsing_db/v4_local_database_manager.h
+++ b/components/safe_browsing_db/v4_local_database_manager.h
@@ -265,9 +265,6 @@
   // ready to process next update.
   DatabaseUpdatedCallback db_updated_callback_;
 
-  // Whether the service is running.
-  bool enabled_;
-
   // The list of stores to manage (for hash prefixes and full hashes). Each
   // element contains the identifier for the store, the corresponding
   // SBThreatType, whether to fetch hash prefixes for that store, and the
diff --git a/components/ukm/ukm_service.cc b/components/ukm/ukm_service.cc
index 823bff5..cbab848 100644
--- a/components/ukm/ukm_service.cc
+++ b/components/ukm/ukm_service.cc
@@ -126,9 +126,6 @@
 void UkmService::EnableReporting() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DVLOG(1) << "UkmService::EnableReporting";
-#if defined(OFFICIAL_BUILD)
-  CHECK(false);  // Remove this once UKM checks sync state.
-#endif
   if (!initialize_started_)
     Initialize();
   scheduler_->Start();
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
index 9d870e3a..3da5b3b 100644
--- a/content/browser/presentation/presentation_service_impl.cc
+++ b/content/browser/presentation/presentation_service_impl.cc
@@ -109,7 +109,9 @@
     const PresentationServiceImpl::NewSessionCallback& callback) {
   callback.Run(blink::mojom::PresentationSessionInfoPtr(),
                blink::mojom::PresentationError::From(PresentationError(
-                   PRESENTATION_ERROR_UNKNOWN, "Internal error")));
+                   PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS,
+                   "There is already an unsettled Promise from a previous call "
+                   "to start.")));
 }
 
 }  // namespace
diff --git a/content/browser/presentation/presentation_type_converters.cc b/content/browser/presentation/presentation_type_converters.cc
index 827897cb..086ec7c 100644
--- a/content/browser/presentation/presentation_type_converters.cc
+++ b/content/browser/presentation/presentation_type_converters.cc
@@ -17,6 +17,8 @@
       return blink::mojom::PresentationErrorType::SESSION_REQUEST_CANCELLED;
     case content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND:
       return blink::mojom::PresentationErrorType::NO_PRESENTATION_FOUND;
+    case content::PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS:
+      return blink::mojom::PresentationErrorType::PREVIOUS_START_IN_PROGRESS;
     case content::PRESENTATION_ERROR_UNKNOWN:
       return blink::mojom::PresentationErrorType::UNKNOWN;
   }
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index ebd54ca..752f7234 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -43,7 +43,7 @@
 #include "cc/surfaces/direct_compositor_frame_sink.h"
 #include "cc/surfaces/display.h"
 #include "cc/surfaces/display_scheduler.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "components/display_compositor/compositor_overlay_candidate_validator_android.h"
 #include "components/display_compositor/gl_helper.h"
@@ -435,13 +435,13 @@
 
   animation_host_ = cc::AnimationHost::CreateMainInstance();
 
-  cc::LayerTreeHostInProcess::InitParams params;
+  cc::LayerTreeHost::InitParams params;
   params.client = this;
   params.task_graph_runner = g_task_graph_runner.Pointer();
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.settings = &settings;
   params.mutator_host = animation_host_.get();
-  host_ = cc::LayerTreeHostInProcess::CreateSingleThreaded(this, &params);
+  host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
   DCHECK(!host_->IsVisible());
   host_->GetLayerTree()->SetRootLayer(root_window_->GetLayer());
   host_->SetFrameSinkId(frame_sink_id_);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 8fc8bde..6cfdebc 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1193,10 +1193,6 @@
   auto registry = base::MakeUnique<service_manager::InterfaceRegistry>(
       service_manager::mojom::kServiceManager_ConnectorSpec);
 
-  channel_->AddAssociatedInterface(
-      base::Bind(&RenderProcessHostImpl::OnRouteProviderRequest,
-                 base::Unretained(this)));
-
   channel_->AddAssociatedInterfaceForIOThread(
       base::Bind(&IndexedDBDispatcherHost::AddBinding, indexed_db_factory_));
 
@@ -2065,6 +2061,21 @@
   return listener->OnMessageReceived(msg);
 }
 
+void RenderProcessHostImpl::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  if (interface_name == mojom::RouteProvider::Name_) {
+    if (route_provider_binding_.is_bound())
+      return;
+    mojom::RouteProviderAssociatedRequest request;
+    request.Bind(std::move(handle));
+    route_provider_binding_.Bind(std::move(request));
+  } else {
+    LOG(ERROR) << "Request for unknown Channel-associated interface: "
+               << interface_name;
+  }
+}
+
 void RenderProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
   channel_connected_ = true;
   if (IsReady()) {
@@ -2653,13 +2664,6 @@
       shm_handle, metrics_allocator_->shared_memory()->mapped_size()));
 }
 
-void RenderProcessHostImpl::OnRouteProviderRequest(
-    mojom::RouteProviderAssociatedRequest request) {
-  if (route_provider_binding_.is_bound())
-    return;
-  route_provider_binding_.Bind(std::move(request));
-}
-
 void RenderProcessHostImpl::ProcessDied(bool already_dead,
                                         RendererClosedDetails* known_details) {
   // Our child process has died.  If we didn't expect it, it's a crash.
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 75895e1..dc269f2 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -186,6 +186,9 @@
 
   // IPC::Listener via RenderProcessHost.
   bool OnMessageReceived(const IPC::Message& msg) override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
   void OnChannelConnected(int32_t peer_pid) override;
   void OnChannelError() override;
   void OnBadMessageReceived(const IPC::Message& message) override;
@@ -371,8 +374,6 @@
   // Handle termination of our process.
   void ProcessDied(bool already_dead, RendererClosedDetails* known_details);
 
-  void OnRouteProviderRequest(mojom::RouteProviderAssociatedRequest request);
-
   // GpuSwitchingObserver implementation.
   void OnGpuSwitched() override;
 
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc
index 9b260626..6efcbf3 100644
--- a/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -120,10 +120,10 @@
   GURL test_url = embedded_test_server()->GetURL("/touch_selection.html");
   NavigateToURL(shell(), test_url);
 
-  RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
-  EXPECT_FALSE(rvh->IsFocusedElementEditable());
+  WebContents* contents = shell()->web_contents();
+  EXPECT_FALSE(contents->IsFocusedElementEditable());
   EXPECT_TRUE(ExecuteScript(shell(), "focus_textfield();"));
-  EXPECT_TRUE(rvh->IsFocusedElementEditable());
+  EXPECT_TRUE(contents->IsFocusedElementEditable());
 }
 
 // Flaky on Linux (https://crbug.com/559192).
diff --git a/content/browser/renderer_host/render_view_host_delegate.cc b/content/browser/renderer_host/render_view_host_delegate.cc
index f202685c..3d5853c 100644
--- a/content/browser/renderer_host/render_view_host_delegate.cc
+++ b/content/browser/renderer_host/render_view_host_delegate.cc
@@ -61,8 +61,4 @@
   return false;
 }
 
-bool RenderViewHostDelegate::IsFocusedElementEditable() {
-  return false;
-}
-
 }  // namespace content
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index a6864b4..2e1dda41 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -190,14 +190,6 @@
   // Whether download UI should be hidden.
   virtual bool HideDownloadUI() const;
 
-  // Whether the focused element on the page is editable. This returns true iff
-  // the focused frame has a focused editable element.
-  virtual bool IsFocusedElementEditable();
-
-  // Asks the delegate to clear the focused element. This will lead to an IPC to
-  // the focused RenderWidget.
-  virtual void ClearFocusedElement() {}
-
  protected:
   virtual ~RenderViewHostDelegate() {}
 };
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 6be34a6c..6cca925 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -950,19 +950,6 @@
   updating_web_preferences_ = false;
 }
 
-void RenderViewHostImpl::ClearFocusedElement() {
-  // TODO(ekaramad): We should move this to WebContents instead
-  // (https://crbug.com/675975).
-  if (delegate_)
-    delegate_->ClearFocusedElement();
-}
-
-bool RenderViewHostImpl::IsFocusedElementEditable() {
-  // TODO(ekaramad): We should move this to WebContents instead
-  // (https://crbug.com/675975).
-  return delegate_ && delegate_->IsFocusedElementEditable();
-}
-
 void RenderViewHostImpl::DisableScrollbarsForThreshold(const gfx::Size& size) {
   Send(new ViewMsg_DisableScrollbarsForSmallWindows(GetRoutingID(), size));
 }
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index a2a0359..88b7ea9a 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -87,8 +87,6 @@
   int GetRoutingID() const override;
   RenderFrameHost* GetMainFrame() override;
   void AllowBindings(int binding_flags) override;
-  void ClearFocusedElement() override;
-  bool IsFocusedElementEditable() override;
   void DirectoryEnumerationFinished(
       int request_id,
       const std::vector<base::FilePath>& files) override;
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index af61d9c..76e9c2d 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -380,10 +380,7 @@
   DCHECK_EQ(original_registration->id(), registration_id);
   scoped_refptr<ServiceWorkerVersion> new_version =
       original_registration->installing_version();
-  new_version->ReportError(
-      SERVICE_WORKER_OK,
-      "ServiceWorker was updated because \"Force update on page load\" was "
-      "checked in DevTools Source tab.");
+  new_version->ReportForceUpdateToDevTools();
   new_version->set_skip_waiting(true);
   new_version->RegisterStatusChangeCallback(base::Bind(
       &self::OnUpdatedVersionStatusChanged, weak_factory_.GetWeakPtr(),
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 1cbb5348..d9fe5df 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -76,6 +76,9 @@
     "Failed to claim clients due to Service Worker system shutdown.";
 
 const char kNotRespondingErrorMesage[] = "Service Worker is not responding.";
+const char kForceUpdateInfoMessage[] =
+    "Service Worker was updated because \"Update on load\" was "
+    "checked in DevTools Service Workers toolbar.";
 
 void RunSoon(const base::Closure& callback) {
   if (!callback.is_null())
@@ -749,6 +752,11 @@
   }
 }
 
+void ServiceWorkerVersion::ReportForceUpdateToDevTools() {
+  embedded_worker_->AddMessageToConsole(blink::WebConsoleMessage::LevelWarning,
+                                        kForceUpdateInfoMessage);
+}
+
 void ServiceWorkerVersion::SetStartWorkerStatusCode(
     ServiceWorkerStatusCode status) {
   start_worker_status_ = status;
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index a892ac6..f6b3e02 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -354,6 +354,8 @@
   void ReportError(ServiceWorkerStatusCode status,
                    const std::string& status_message);
 
+  void ReportForceUpdateToDevTools();
+
   // Sets the status code to pass to StartWorker callbacks if start fails.
   void SetStartWorkerStatusCode(ServiceWorkerStatusCode status);
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index fce4361..fcd0937 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -410,6 +410,8 @@
   void OnAllPasswordInputsHiddenOnHttp() override;
   void OnCreditCardInputShownOnHttp() override;
   void SetIsOverlayContent(bool is_overlay_content) override;
+  bool IsFocusedElementEditable() override;
+  void ClearFocusedElement() override;
 
 #if defined(OS_ANDROID)
   base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
@@ -557,8 +559,6 @@
   bool IsOverridingUserAgent() override;
   bool IsJavaScriptDialogShowing() const override;
   bool HideDownloadUI() const override;
-  bool IsFocusedElementEditable() override;
-  void ClearFocusedElement() override;
 
   // NavigatorDelegate ---------------------------------------------------------
 
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index 2666ba2..dd7af71 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -538,10 +538,6 @@
     channel_->AddFilter(startup_filter);
   }
 
-  channel_->AddAssociatedInterface(
-      base::Bind(&ChildThreadImpl::OnRouteProviderRequest,
-                 base::Unretained(this)));
-
   ConnectChannel();
 
   // This must always be done after ConnectChannel, because ConnectChannel() may
@@ -754,6 +750,20 @@
   return router_.OnMessageReceived(msg);
 }
 
+void ChildThreadImpl::OnAssociatedInterfaceRequest(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle handle) {
+  if (interface_name == mojom::RouteProvider::Name_) {
+    DCHECK(!route_provider_binding_.is_bound());
+    mojom::RouteProviderAssociatedRequest request;
+    request.Bind(std::move(handle));
+    route_provider_binding_.Bind(std::move(request));
+  } else {
+    LOG(ERROR) << "Request for unknown Channel-associated interface: "
+               << interface_name;
+  }
+}
+
 void ChildThreadImpl::StartServiceManagerConnection() {
   DCHECK(service_manager_connection_);
   service_manager_connection_->Start();
@@ -842,12 +852,6 @@
   base::Process::Current().Terminate(0, false);
 }
 
-void ChildThreadImpl::OnRouteProviderRequest(
-    mojom::RouteProviderAssociatedRequest request) {
-  DCHECK(!route_provider_binding_.is_bound());
-  route_provider_binding_.Bind(std::move(request));
-}
-
 void ChildThreadImpl::GetRoute(
     int32_t routing_id,
     mojom::AssociatedInterfaceProviderAssociatedRequest request) {
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index 6dc64263..a9ce450 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -198,6 +198,9 @@
 
   // IPC::Listener implementation:
   bool OnMessageReceived(const IPC::Message& msg) override;
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override;
   void OnChannelConnected(int32_t peer_pid) override;
   void OnChannelError() override;
 
@@ -235,8 +238,6 @@
 
   void EnsureConnected();
 
-  void OnRouteProviderRequest(mojom::RouteProviderAssociatedRequest request);
-
   // mojom::RouteProvider:
   void GetRoute(
       int32_t routing_id,
diff --git a/content/common/associated_interface_registry_impl.cc b/content/common/associated_interface_registry_impl.cc
index 67b5b0e..468dc9966 100644
--- a/content/common/associated_interface_registry_impl.cc
+++ b/content/common/associated_interface_registry_impl.cc
@@ -14,6 +14,11 @@
 
 AssociatedInterfaceRegistryImpl::~AssociatedInterfaceRegistryImpl() {}
 
+bool AssociatedInterfaceRegistryImpl::CanBindRequest(
+    const std::string& interface_name) const {
+  return interfaces_.find(interface_name) != interfaces_.end();
+}
+
 void AssociatedInterfaceRegistryImpl::BindRequest(
     const std::string& interface_name,
     mojo::ScopedInterfaceEndpointHandle handle) {
diff --git a/content/common/associated_interface_registry_impl.h b/content/common/associated_interface_registry_impl.h
index 1f624a2f..4f7431c 100644
--- a/content/common/associated_interface_registry_impl.h
+++ b/content/common/associated_interface_registry_impl.h
@@ -19,6 +19,7 @@
   AssociatedInterfaceRegistryImpl();
   ~AssociatedInterfaceRegistryImpl() override;
 
+  bool CanBindRequest(const std::string& interface_name) const;
   void BindRequest(const std::string& interface_name,
                    mojo::ScopedInterfaceEndpointHandle handle);
 
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index 9cfd41a..f392f276 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -285,7 +285,10 @@
 void GpuChildThread::OnAssociatedInterfaceRequest(
     const std::string& name,
     mojo::ScopedInterfaceEndpointHandle handle) {
-  associated_interfaces_.BindRequest(name, std::move(handle));
+  if (associated_interfaces_.CanBindRequest(name))
+    associated_interfaces_.BindRequest(name, std::move(handle));
+  else
+    ChildThreadImpl::OnAssociatedInterfaceRequest(name, std::move(handle));
 }
 
 void GpuChildThread::CreateGpuService(
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h
index faa7ad0..04841375 100644
--- a/content/public/browser/render_view_host.h
+++ b/content/public/browser/render_view_host.h
@@ -90,12 +90,6 @@
   // should be a combination of values from BindingsPolicy.
   virtual void AllowBindings(int binding_flags) = 0;
 
-  // Tells the renderer to clear the focused element (if any).
-  virtual void ClearFocusedElement() = 0;
-
-  // Returns true if the current focused element is editable.
-  virtual bool IsFocusedElementEditable() = 0;
-
   // Notifies the listener that a directory enumeration is complete.
   virtual void DirectoryEnumerationFinished(
       int request_id,
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index a5e2535..98c79247 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -731,6 +731,12 @@
   virtual int GetCurrentlyPlayingVideoCount() = 0;
   virtual bool IsFullscreen() = 0;
 
+  // Tells the renderer to clear the focused element (if any).
+  virtual void ClearFocusedElement() = 0;
+
+  // Returns true if the current focused element is editable.
+  virtual bool IsFocusedElementEditable() = 0;
+
 #if defined(OS_ANDROID)
   CONTENT_EXPORT static WebContents* FromJavaWebContents(
       const base::android::JavaRef<jobject>& jweb_contents_android);
diff --git a/content/public/common/presentation_session.h b/content/public/common/presentation_session.h
index 87bafb4b..c57913a75 100644
--- a/content/public/common/presentation_session.h
+++ b/content/public/common/presentation_session.h
@@ -44,6 +44,7 @@
   PRESENTATION_ERROR_NO_AVAILABLE_SCREENS,
   PRESENTATION_ERROR_SESSION_REQUEST_CANCELLED,
   PRESENTATION_ERROR_NO_PRESENTATION_FOUND,
+  PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS,
   PRESENTATION_ERROR_UNKNOWN,
 };
 
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 8bf87802..8b17f64 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -44,7 +44,7 @@
 #include "cc/resources/single_release_callback.h"
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/trees/latency_info_swap_promise_monitor.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_mutator.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/layer_tree_settings_factory.h"
@@ -236,7 +236,7 @@
 
   std::unique_ptr<cc::LayerTreeHost> layer_tree_host;
 
-  cc::LayerTreeHostInProcess::InitParams params;
+  cc::LayerTreeHost::InitParams params;
   params.client = client;
   params.settings = &settings;
   params.task_graph_runner = deps->GetTaskGraphRunner();
@@ -251,10 +251,10 @@
   }
   if (!is_threaded) {
     // Single-threaded layout tests.
-    layer_tree_host = cc::LayerTreeHostInProcess::CreateSingleThreaded(
-        single_thread_client, &params);
+    layer_tree_host =
+        cc::LayerTreeHost::CreateSingleThreaded(single_thread_client, &params);
   } else {
-    layer_tree_host = cc::LayerTreeHostInProcess::CreateThreaded(
+    layer_tree_host = cc::LayerTreeHost::CreateThreaded(
         deps->GetCompositorImplThreadTaskRunner(), &params);
   }
 
diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc
index e5d3c51..594fdde 100644
--- a/content/renderer/presentation/presentation_dispatcher.cc
+++ b/content/renderer/presentation/presentation_dispatcher.cc
@@ -54,6 +54,8 @@
       return blink::WebPresentationError::ErrorTypeSessionRequestCancelled;
     case blink::mojom::PresentationErrorType::NO_PRESENTATION_FOUND:
       return blink::WebPresentationError::ErrorTypeNoPresentationFound;
+    case blink::mojom::PresentationErrorType::PREVIOUS_START_IN_PROGRESS:
+      return blink::WebPresentationError::ErrorTypePreviousStartInProgress;
     case blink::mojom::PresentationErrorType::UNKNOWN:
     default:
       return blink::WebPresentationError::ErrorTypeUnknown;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 1dcaaa6f..e374de41 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1485,7 +1485,10 @@
 void RenderThreadImpl::OnAssociatedInterfaceRequest(
     const std::string& name,
     mojo::ScopedInterfaceEndpointHandle handle) {
-  associated_interfaces_.BindRequest(name, std::move(handle));
+  if (associated_interfaces_.CanBindRequest(name))
+    associated_interfaces_.BindRequest(name, std::move(handle));
+  else
+    ChildThreadImpl::OnAssociatedInterfaceRequest(name, std::move(handle));
 }
 
 bool RenderThreadImpl::IsGpuRasterizationForced() {
diff --git a/extensions/browser/api/execute_code_function.cc b/extensions/browser/api/execute_code_function.cc
index d1b1ee3..0f2dd5f 100644
--- a/extensions/browser/api/execute_code_function.cc
+++ b/extensions/browser/api/execute_code_function.cc
@@ -163,7 +163,13 @@
 }
 
 bool ExecuteCodeFunction::RunAsync() {
-  EXTENSION_FUNCTION_VALIDATE(Init());
+  InitResult init_result = Init();
+  EXTENSION_FUNCTION_VALIDATE(init_result != VALIDATION_FAILURE);
+  if (init_result == FAILURE) {
+    if (init_error_)
+      SetError(init_error_.value());
+    return false;
+  }
 
   if (!details_->code.get() && !details_->file.get()) {
     error_ = kNoCodeOrFileToExecuteError;
diff --git a/extensions/browser/api/execute_code_function.h b/extensions/browser/api/execute_code_function.h
index dbf8639..13df3dd 100644
--- a/extensions/browser/api/execute_code_function.h
+++ b/extensions/browser/api/execute_code_function.h
@@ -6,6 +6,7 @@
 #define EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_H_
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "extensions/browser/extension_function.h"
 #include "extensions/browser/script_executor.h"
 #include "extensions/common/api/extension_types.h"
@@ -27,8 +28,23 @@
   bool HasPermission() override;
   bool RunAsync() override;
 
-  // Initialize |details_| if it hasn't already been.
-  virtual bool Init() = 0;
+  enum InitResult {
+    // ExtensionFunction validation failure.
+    // Warning: Validation failures kill the renderer and should only be used
+    // for circumstances that should never happen.
+    VALIDATION_FAILURE,
+    // Failure other than validation.
+    // Failures return an error to the extension function and should be used
+    // when an error situation occurs: e.g. trying to execute script during
+    // browser shutdown.
+    FAILURE,
+    SUCCESS
+  };
+
+  // Initializes |details_| and other variables if they haven't already been.
+  // Returns whether or not it succeeded. Failure can be tolerable (FAILURE), or
+  // fatal (VALIDATION_FAILURE).
+  virtual InitResult Init() = 0;
   virtual bool ShouldInsertCSS() const = 0;
   virtual bool CanExecuteScriptOnPage() = 0;
   virtual ScriptExecutor* GetScriptExecutor() = 0;
@@ -48,8 +64,20 @@
   const HostID& host_id() const { return host_id_; }
   void set_host_id(const HostID& host_id) { host_id_ = host_id; }
 
+  InitResult set_init_result(InitResult init_result) {
+    init_result_ = init_result;
+    return init_result_.value();
+  }
+  InitResult set_init_result_error(const std::string& error) {
+    init_error_ = error;
+    return set_init_result(FAILURE);
+  }
+
   // The injection details.
   std::unique_ptr<api::extension_types::InjectDetails> details_;
+  base::Optional<InitResult> init_result_;
+  // Set iff |init_result_| == FAILURE, holds the error string.
+  base::Optional<std::string> init_error_;
 
  private:
   // Retrieves the file url for the given |extension_path| and optionally
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
index 790f767..179e68e 100644
--- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
+++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -365,19 +365,16 @@
 WebViewInternalExecuteCodeFunction::~WebViewInternalExecuteCodeFunction() {
 }
 
-bool WebViewInternalExecuteCodeFunction::Init() {
-  if (details_.get())
-    return true;
+ExecuteCodeFunction::InitResult WebViewInternalExecuteCodeFunction::Init() {
+  if (init_result_)
+    return init_result_.value();
 
-  if (!args_->GetInteger(0, &guest_instance_id_))
-    return false;
-
-  if (!guest_instance_id_)
-    return false;
+  if (!args_->GetInteger(0, &guest_instance_id_) || !guest_instance_id_)
+    return set_init_result(VALIDATION_FAILURE);
 
   std::string src;
   if (!args_->GetString(1, &src))
-    return false;
+    return set_init_result(VALIDATION_FAILURE);
 
   // Set |guest_src_| here, but do not return false if it is invalid.
   // Instead, let it continue with the normal page load sequence,
@@ -387,25 +384,25 @@
 
   base::DictionaryValue* details_value = NULL;
   if (!args_->GetDictionary(2, &details_value))
-    return false;
+    return set_init_result(VALIDATION_FAILURE);
   std::unique_ptr<InjectDetails> details(new InjectDetails());
   if (!InjectDetails::Populate(*details_value, details.get()))
-    return false;
+    return set_init_result(VALIDATION_FAILURE);
 
   details_ = std::move(details);
 
   if (extension()) {
     set_host_id(HostID(HostID::EXTENSIONS, extension()->id()));
-    return true;
+    return set_init_result(SUCCESS);
   }
 
   WebContents* web_contents = GetSenderWebContents();
   if (web_contents && web_contents->GetWebUI()) {
     const GURL& url = render_frame_host()->GetSiteInstance()->GetSiteURL();
     set_host_id(HostID(HostID::WEBUI, url.spec()));
-    return true;
+    return set_init_result(SUCCESS);
   }
-  return false;
+  return set_init_result_error("");  // TODO(lazyboy): error?
 }
 
 bool WebViewInternalExecuteCodeFunction::ShouldInsertCSS() const {
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
index 3c5bf2aa..486bc03 100644
--- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
+++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
@@ -97,7 +97,7 @@
   ~WebViewInternalExecuteCodeFunction() override;
 
   // Initialize |details_| if it hasn't already been.
-  bool Init() override;
+  InitResult Init() override;
   bool ShouldInsertCSS() const override;
   bool CanExecuteScriptOnPage() override;
   // Guarded by a process ID check.
diff --git a/extensions/renderer/api/automation/automation_api_helper.cc b/extensions/renderer/api/automation/automation_api_helper.cc
index 42a493b..8ffd54a7 100644
--- a/extensions/renderer/api/automation/automation_api_helper.cc
+++ b/extensions/renderer/api/automation/automation_api_helper.cc
@@ -74,7 +74,7 @@
       start_node = start_acc_obj.node();
     }
   }
-  blink::WebString web_selector(selector);
+  blink::WebString web_selector = blink::WebString::fromUTF16(selector);
   blink::WebElement result_element = start_node.querySelector(web_selector);
   int result_acc_obj_id = 0;
   if (!result_element.isNull()) {
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 2a9986c..014d9f1 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -267,7 +267,7 @@
   RenderThread::Get()->RegisterExtension(SafeBuiltins::CreateV8Extension());
 
   // Register WebSecurityPolicy whitelists for the chrome-extension:// scheme.
-  WebString extension_scheme(base::ASCIIToUTF16(kExtensionScheme));
+  WebString extension_scheme(WebString::fromASCII(kExtensionScheme));
 
   // Resources should bypass Content Security Policy checks when included in
   // protected resources. TODO(kalman): What are "protected resources"?
diff --git a/extensions/renderer/dom_activity_logger.cc b/extensions/renderer/dom_activity_logger.cc
index 13d960b..5f74d785 100644
--- a/extensions/renderer/dom_activity_logger.cc
+++ b/extensions/renderer/dom_activity_logger.cc
@@ -63,7 +63,8 @@
 void DOMActivityLogger::logGetter(const WebString& api_name,
                                   const WebURL& url,
                                   const WebString& title) {
-  SendDomActionMessage(api_name.utf8(), url, title, DomActionType::GETTER,
+  SendDomActionMessage(api_name.utf8(), url, title.utf16(),
+                       DomActionType::GETTER,
                        std::unique_ptr<base::ListValue>(new base::ListValue()));
 }
 
@@ -84,7 +85,7 @@
   AppendV8Value(api_name_utf8, new_value, args.get());
   if (!old_value.IsEmpty())
     AppendV8Value(api_name_utf8, old_value, args.get());
-  SendDomActionMessage(api_name_utf8, url, title, DomActionType::SETTER,
+  SendDomActionMessage(api_name_utf8, url, title.utf16(), DomActionType::SETTER,
                        std::move(args));
 }
 
@@ -97,7 +98,7 @@
   std::string api_name_utf8 = api_name.utf8();
   for (int i = 0; i < argc; ++i)
     AppendV8Value(api_name_utf8, argv[i], args.get());
-  SendDomActionMessage(api_name_utf8, url, title, DomActionType::METHOD,
+  SendDomActionMessage(api_name_utf8, url, title.utf16(), DomActionType::METHOD,
                        std::move(args));
 }
 
@@ -109,9 +110,9 @@
   std::unique_ptr<base::ListValue> args(new base::ListValue);
   std::string event_name_utf8 = event_name.utf8();
   for (int i = 0; i < argc; ++i)
-    args->AppendString(argv[i]);
-  SendDomActionMessage(event_name_utf8, url, title, DomActionType::METHOD,
-                       std::move(args));
+    args->AppendString(argv[i].utf16());
+  SendDomActionMessage(event_name_utf8, url, title.utf16(),
+                       DomActionType::METHOD, std::move(args));
 }
 
 void DOMActivityLogger::SendDomActionMessage(
diff --git a/extensions/renderer/extension_frame_helper.cc b/extensions/renderer/extension_frame_helper.cc
index 91d38c3..c737aa55 100644
--- a/extensions/renderer/extension_frame_helper.cc
+++ b/extensions/renderer/extension_frame_helper.cc
@@ -50,10 +50,8 @@
   blink::WebSecurityOrigin origin =
       frame_helper->render_frame()->GetWebFrame()->getSecurityOrigin();
   if (origin.isUnique() ||
-      !base::EqualsASCII(base::StringPiece16(origin.protocol()),
-                         kExtensionScheme) ||
-      !base::EqualsASCII(base::StringPiece16(origin.host()),
-                         match_extension_id.c_str()))
+      !base::EqualsASCII(origin.protocol().utf16(), kExtensionScheme) ||
+      !base::EqualsASCII(origin.host().utf16(), match_extension_id.c_str()))
     return false;
 
   if (match_window_id != extension_misc::kUnknownWindowId &&
diff --git a/ios/chrome/app/tests_fake_hook.mm b/ios/chrome/app/tests_fake_hook.mm
index e4031757..c3125688 100644
--- a/ios/chrome/app/tests_fake_hook.mm
+++ b/ios/chrome/app/tests_fake_hook.mm
@@ -12,6 +12,9 @@
 bool DisableFirstRun() {
   return false;
 }
+bool DisableGeolocation() {
+  return false;
+}
 bool DisableSigninRecallPromo() {
   return false;
 }
diff --git a/ios/chrome/app/tests_hook.h b/ios/chrome/app/tests_hook.h
index 3a63b93..7b39c521 100644
--- a/ios/chrome/app/tests_hook.h
+++ b/ios/chrome/app/tests_hook.h
@@ -15,6 +15,10 @@
 // run unimpeded.
 bool DisableFirstRun();
 
+// Returns true if the geolocation should be disabled to avoid the user location
+// prompt displaying for the omnibox.
+bool DisableGeolocation();
+
 // Returns true if the signin recall promo should be disabled to allow other
 // tests to run unimpeded.
 bool DisableSigninRecallPromo();
diff --git a/ios/chrome/browser/geolocation/BUILD.gn b/ios/chrome/browser/geolocation/BUILD.gn
index 30306a6..b38a267 100644
--- a/ios/chrome/browser/geolocation/BUILD.gn
+++ b/ios/chrome/browser/geolocation/BUILD.gn
@@ -23,6 +23,7 @@
     "//base",
     "//components/prefs",
     "//components/strings",
+    "//ios/chrome/app:tests_hook",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/geolocation/location_manager.mm b/ios/chrome/browser/geolocation/location_manager.mm
index e9daf6e..10c5ce0 100644
--- a/ios/chrome/browser/geolocation/location_manager.mm
+++ b/ios/chrome/browser/geolocation/location_manager.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/geolocation/location_manager.h"
 
+#include "ios/chrome/app/tests_hook.h"
 #import "ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h"
 #import "ios/chrome/browser/geolocation/location_manager+Testing.h"
 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
@@ -91,7 +92,8 @@
 }
 
 - (BOOL)locationServicesEnabled {
-  return [CLLocationManager locationServicesEnabled];
+  return !tests_hook::DisableGeolocation() &&
+         [CLLocationManager locationServicesEnabled];
 }
 
 - (void)startUpdatingLocation {
diff --git a/ios/chrome/test/earl_grey/eg_tests_hook.mm b/ios/chrome/test/earl_grey/eg_tests_hook.mm
index 71ad274..5f98ad77 100644
--- a/ios/chrome/test/earl_grey/eg_tests_hook.mm
+++ b/ios/chrome/test/earl_grey/eg_tests_hook.mm
@@ -14,6 +14,10 @@
   return true;
 }
 
+bool DisableGeolocation() {
+  return true;
+}
+
 bool DisableSigninRecallPromo() {
   return true;
 }
diff --git a/ipc/ipc_channel_mojo_unittest.cc b/ipc/ipc_channel_mojo_unittest.cc
index 9b28e39..5e75fbd 100644
--- a/ipc/ipc_channel_mojo_unittest.cc
+++ b/ipc/ipc_channel_mojo_unittest.cc
@@ -848,12 +848,17 @@
       : driver_binding_(this), ping_receiver_binding_(this) {}
   ~ListenerWithIndirectProxyAssociatedInterface() override {}
 
+  // IPC::Listener:
   bool OnMessageReceived(const IPC::Message& message) override { return true; }
 
-  void RegisterInterfaceFactory(IPC::ChannelProxy* proxy) {
-    proxy->AddAssociatedInterface(
-        base::Bind(&ListenerWithIndirectProxyAssociatedInterface::BindRequest,
-                   base::Unretained(this)));
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override {
+    DCHECK(!driver_binding_.is_bound());
+    DCHECK_EQ(interface_name, IPC::mojom::IndirectTestDriver::Name_);
+    IPC::mojom::IndirectTestDriverAssociatedRequest request;
+    request.Bind(std::move(handle));
+    driver_binding_.Bind(std::move(request));
   }
 
   void set_ping_handler(const base::Closure& handler) {
@@ -873,11 +878,6 @@
     ping_handler_.Run();
   }
 
-  void BindRequest(IPC::mojom::IndirectTestDriverAssociatedRequest request) {
-    DCHECK(!driver_binding_.is_bound());
-    driver_binding_.Bind(std::move(request));
-  }
-
   mojo::AssociatedBinding<IPC::mojom::IndirectTestDriver> driver_binding_;
   mojo::AssociatedBinding<IPC::mojom::PingReceiver> ping_receiver_binding_;
 
@@ -893,7 +893,6 @@
 
   ListenerWithIndirectProxyAssociatedInterface listener;
   CreateProxy(&listener);
-  listener.RegisterInterfaceFactory(proxy());
   RunProxy();
 
   base::RunLoop loop;
@@ -939,12 +938,6 @@
 
   void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
 
-  void RegisterInterfaceFactory(IPC::ChannelProxy* proxy) {
-    proxy->AddAssociatedInterface(
-        base::Bind(&ListenerWithSyncAssociatedInterface::BindRequest,
-                   base::Unretained(this)));
-  }
-
   void RunUntilQuitRequested() {
     base::RunLoop loop;
     quit_closure_ = loop.QuitClosure();
@@ -989,6 +982,17 @@
     return true;
   }
 
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override {
+    DCHECK(!binding_.is_bound());
+    DCHECK_EQ(interface_name, IPC::mojom::SimpleTestDriver::Name_);
+
+    IPC::mojom::SimpleTestDriverAssociatedRequest request;
+    request.Bind(std::move(handle));
+    binding_.Bind(std::move(request));
+  }
+
   void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
     DCHECK(!binding_.is_bound());
     binding_.Bind(std::move(request));
@@ -1027,7 +1031,6 @@
   ListenerWithSyncAssociatedInterface listener;
   CreateProxy(&listener);
   listener.set_sync_sender(proxy());
-  listener.RegisterInterfaceFactory(proxy());
   RunProxy();
 
   // Run the client's simple sanity check to completion.
@@ -1071,11 +1074,6 @@
   void set_driver(IPC::mojom::SimpleTestDriver* driver) { driver_ = driver; }
   void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
 
-  void BindRequest(IPC::mojom::SimpleTestClientAssociatedRequest request) {
-    DCHECK(!binding_.is_bound());
-    binding_.Bind(std::move(request));
-  }
-
   void WaitForValueRequest() {
     run_loop_.reset(new base::RunLoop);
     run_loop_->Run();
@@ -1119,6 +1117,17 @@
     return true;
   }
 
+  void OnAssociatedInterfaceRequest(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle handle) override {
+    DCHECK(!binding_.is_bound());
+    DCHECK_EQ(interface_name, IPC::mojom::SimpleTestClient::Name_);
+
+    IPC::mojom::SimpleTestClientAssociatedRequest request;
+    request.Bind(std::move(handle));
+    binding_.Bind(std::move(request));
+  }
+
   bool use_sync_sender_ = false;
   mojo::AssociatedBinding<IPC::mojom::SimpleTestClient> binding_;
   IPC::Sender* sync_sender_ = nullptr;
@@ -1133,8 +1142,6 @@
   SimpleTestClientImpl client_impl;
   CreateProxy(&client_impl);
   client_impl.set_sync_sender(proxy());
-  proxy()->AddAssociatedInterface(base::Bind(&SimpleTestClientImpl::BindRequest,
-                                             base::Unretained(&client_impl)));
   RunProxy();
 
   IPC::mojom::SimpleTestDriverAssociatedPtr driver;
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
index 3365aef..91e8236 100644
--- a/ipc/ipc_channel_proxy.cc
+++ b/ipc/ipc_channel_proxy.cc
@@ -27,17 +27,6 @@
 
 namespace IPC {
 
-namespace {
-
-void BindAssociatedInterfaceOnTaskRunner(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    const ChannelProxy::GenericAssociatedInterfaceFactory& factory,
-    mojo::ScopedInterfaceEndpointHandle handle) {
-  task_runner->PostTask(FROM_HERE, base::Bind(factory, base::Passed(&handle)));
-}
-
-}  // namespace
-
 //------------------------------------------------------------------------------
 
 ChannelProxy::Context::Context(
@@ -81,9 +70,9 @@
     associated_group_ = *support->GetAssociatedGroup();
 
     base::AutoLock l(pending_filters_lock_);
-    for (auto& entry : pending_interfaces_)
+    for (auto& entry : pending_io_thread_interfaces_)
       support->AddGenericAssociatedInterface(entry.first, entry.second);
-    pending_interfaces_.clear();
+    pending_io_thread_interfaces_.clear();
   }
 }
 
@@ -388,21 +377,13 @@
   associated_group_ = mojo::AssociatedGroup();
 }
 
-void ChannelProxy::Context::AddGenericAssociatedInterface(
-    const std::string& name,
-    const GenericAssociatedInterfaceFactory& factory) {
-  AddGenericAssociatedInterfaceForIOThread(
-      name, base::Bind(&BindAssociatedInterfaceOnTaskRunner,
-                       listener_task_runner_, factory));
-}
-
 void ChannelProxy::Context::AddGenericAssociatedInterfaceForIOThread(
     const std::string& name,
     const GenericAssociatedInterfaceFactory& factory) {
   base::AutoLock l(channel_lifetime_lock_);
   if (!channel_) {
     base::AutoLock l(pending_filters_lock_);
-    pending_interfaces_.emplace_back(name, factory);
+    pending_io_thread_interfaces_.emplace_back(name, factory);
     return;
   }
   Channel::AssociatedInterfaceSupport* support =
@@ -585,12 +566,6 @@
                             base::RetainedRef(filter)));
 }
 
-void ChannelProxy::AddGenericAssociatedInterface(
-    const std::string& name,
-    const GenericAssociatedInterfaceFactory& factory) {
-  context()->AddGenericAssociatedInterface(name, factory);
-}
-
 void ChannelProxy::AddGenericAssociatedInterfaceForIOThread(
     const std::string& name,
     const GenericAssociatedInterfaceFactory& factory) {
diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h
index ade563e..bda83bb18 100644
--- a/ipc/ipc_channel_proxy.h
+++ b/ipc/ipc_channel_proxy.h
@@ -169,14 +169,6 @@
       const std::string& name,
       const GenericAssociatedInterfaceFactory& factory);
 
-  // Adds a generic associated interface factory to bind incoming interface
-  // requests on the ChannelProxy's thread. MUST be called before Init() or
-  // before the remote end of the Channel is able to send messages (e.g. before
-  // its process is launched.)
-  void AddGenericAssociatedInterface(
-      const std::string& name,
-      const GenericAssociatedInterfaceFactory& factory);
-
   template <typename Interface>
   using AssociatedInterfaceFactory =
       base::Callback<void(mojo::AssociatedInterfaceRequest<Interface>)>;
@@ -193,18 +185,6 @@
                    factory));
   }
 
-  // Helper to bind a ChannelProxy-thread associated interface factory,
-  // inferring the interface name from the callback argument's type. MUST be
-  // called before Init().
-  template <typename Interface>
-  void AddAssociatedInterface(
-      const AssociatedInterfaceFactory<Interface>& factory) {
-    AddGenericAssociatedInterface(
-        Interface::Name_,
-        base::Bind(&ChannelProxy::BindAssociatedInterfaceRequest<Interface>,
-                   factory));
-  }
-
   // Gets the AssociatedGroup used to create new associated endpoints on this
   // ChannelProxy.
   mojo::AssociatedGroup* GetAssociatedGroup();
@@ -341,9 +321,6 @@
 
     mojo::AssociatedGroup* associated_group() { return &associated_group_; }
 
-    void AddGenericAssociatedInterface(
-        const std::string& name,
-        const GenericAssociatedInterfaceFactory& factory);
     void AddGenericAssociatedInterfaceForIOThread(
         const std::string& name,
         const GenericAssociatedInterfaceFactory& factory);
@@ -383,12 +360,12 @@
 
     mojo::AssociatedGroup associated_group_;
 
-    // Holds associated interface binders added by AddGenericAssociatedInterface
-    // or AddGenericAssociatedInterfaceForIOThread until the underlying channel
-    // has been initialized.
-    base::Lock pending_interfaces_lock_;
+    // Holds associated interface binders added by
+    // AddGenericAssociatedInterfaceForIOThread until the underlying channel has
+    // been initialized.
+    base::Lock pending_io_thread_interfaces_lock_;
     std::vector<std::pair<std::string, GenericAssociatedInterfaceFactory>>
-        pending_interfaces_;
+        pending_io_thread_interfaces_;
   };
 
   Context* context() { return context_.get(); }
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc
index f305c18..2d4251b 100644
--- a/net/http/disk_cache_based_quic_server_info.cc
+++ b/net/http/disk_cache_based_quic_server_info.cc
@@ -9,6 +9,7 @@
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -158,7 +159,7 @@
     new_data_ = Serialize();
   } else {
     new_data_ = pending_write_data_;
-    pending_write_data_.clear();
+    base::STLClearObject(&pending_write_data_);
   }
 
   RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST);
@@ -392,7 +393,7 @@
   if (entry_)
     entry_->Close();
   entry_ = NULL;
-  new_data_.clear();
+  base::STLClearObject(&new_data_);
   state_ = NONE;
   return OK;
 }
diff --git a/net/quic/quartc/quartc_session_test.cc b/net/quic/quartc/quartc_session_test.cc
index f77e9a0..fc190057 100644
--- a/net/quic/quartc/quartc_session_test.cc
+++ b/net/quic/quartc/quartc_session_test.cc
@@ -17,7 +17,6 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/quic_crypto_client_stream.h"
 #include "net/quic/core/quic_crypto_server_stream.h"
-#include "net/quic/core/quic_flags.h"
 #include "net/quic/core/quic_simple_buffer_allocator.h"
 #include "net/quic/platform/impl/quic_chromium_clock.h"
 #include "net/quic/quartc/quartc_alarm_factory.h"
@@ -464,23 +463,20 @@
   std::unique_ptr<QuartcSessionForTest> server_peer_;
 };
 
-TEST_F(QuartcSessionTest, StreamConnection) {
-  FLAGS_quic_reloadable_flag_enable_async_get_proof = false;
+TEST_F(QuartcSessionTest, DISABLED_StreamConnection) {
   CreateClientAndServerSessions();
   StartHandshake();
   TestStreamConnection();
 }
 
-TEST_F(QuartcSessionTest, ClientRejection) {
-  FLAGS_quic_reloadable_flag_enable_async_get_proof = false;
+TEST_F(QuartcSessionTest, DISABLED_ClientRejection) {
   CreateClientAndServerSessions(false /*client_handshake_success*/,
                                 true /*server_handshake_success*/);
   StartHandshake();
   TestDisconnectAfterFailedHandshake();
 }
 
-TEST_F(QuartcSessionTest, ServerRejection) {
-  FLAGS_quic_reloadable_flag_enable_async_get_proof = false;
+TEST_F(QuartcSessionTest, DISABLED_ServerRejection) {
   CreateClientAndServerSessions(true /*client_handshake_success*/,
                                 false /*server_handshake_success*/);
   StartHandshake();
@@ -494,8 +490,7 @@
   EXPECT_EQ(nullptr, client_peer_->CreateOutgoingStream(kDefaultStreamParam));
 }
 
-TEST_F(QuartcSessionTest, CloseQuartcStream) {
-  FLAGS_quic_reloadable_flag_enable_async_get_proof = false;
+TEST_F(QuartcSessionTest, DISABLED_CloseQuartcStream) {
   CreateClientAndServerSessions();
   StartHandshake();
   ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed() &&
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc
index eee8a6c..e93c880 100644
--- a/services/ui/ws/display.cc
+++ b/services/ui/ws/display.cc
@@ -270,13 +270,6 @@
   return root_.get();
 }
 
-ServerWindow* Display::GetActiveRootWindow() {
-  WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
-  if (display_root)
-    return display_root->root();
-  return nullptr;
-}
-
 void Display::OnAcceleratedWidgetAvailable() {
   display_manager()->OnDisplayAcceleratedWidgetAvailable(this);
   InitWindowManagerDisplayRoots();
@@ -313,6 +306,13 @@
     pair.second->root()->SetBounds(new_bounds);
 }
 
+ServerWindow* Display::GetActiveRootWindow() {
+  WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
+  if (display_root)
+    return display_root->root();
+  return nullptr;
+}
+
 bool Display::CanHaveActiveChildren(ServerWindow* window) const {
   return window && activation_parents_.Contains(window);
 }
diff --git a/services/ui/ws/display.h b/services/ui/ws/display.h
index 28bf83b..679a338 100644
--- a/services/ui/ws/display.h
+++ b/services/ui/ws/display.h
@@ -143,6 +143,9 @@
   // Updates the size of display root ServerWindow and WM root ServerWindow(s).
   void OnViewportMetricsChanged(const display::ViewportMetrics& metrics);
 
+  // Returns the root window of the active user.
+  ServerWindow* GetActiveRootWindow();
+
  private:
   friend class test::DisplayTestApi;
 
@@ -166,7 +169,6 @@
   // PlatformDisplayDelegate:
   display::Display GetDisplay() override;
   ServerWindow* GetRootWindow() override;
-  ServerWindow* GetActiveRootWindow() override;
   void OnAcceleratedWidgetAvailable() override;
   bool IsInHighContrastMode() override;
   void OnEvent(const ui::Event& event) override;
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index ec6a3471..ba893e2 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -31,6 +31,14 @@
   DCHECK(delegate_);
 }
 
+void FrameGenerator::SetDeviceScaleFactor(float device_scale_factor) {
+  if (device_scale_factor_ == device_scale_factor)
+    return;
+  device_scale_factor_ = device_scale_factor;
+  if (compositor_frame_sink_)
+    compositor_frame_sink_->SetNeedsBeginFrame(true);
+}
+
 FrameGenerator::~FrameGenerator() {
   // Invalidate WeakPtrs now to avoid callbacks back into the
   // FrameGenerator during destruction of |compositor_frame_sink_|.
@@ -50,23 +58,17 @@
   root_window_->CreateDisplayCompositorFrameSink(
       widget, std::move(sink_request), binding_.CreateInterfacePtrAndBind(),
       std::move(display_request));
-  // TODO(fsamuel): This means we're always requesting a new BeginFrame signal
-  // even when we don't need it. Once surface ID propagation work is done,
-  // this will not be necessary because FrameGenerator will only need a
-  // BeginFrame if the window manager changes.
-  compositor_frame_sink_->SetNeedsBeginFrame(true);
 }
 
-void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id,
-                                      ServerWindow* window) {
-  DCHECK(surface_id.is_valid());
+void FrameGenerator::OnSurfaceCreated(const cc::SurfaceInfo& surface_info) {
+  DCHECK(surface_info.id().is_valid());
 
   // Only handle embedded surfaces changing here. The display root surface
   // changing is handled immediately after the CompositorFrame is submitted.
-  // TODO(samans): Only tell FrameGenerator about WM surface instead of all
-  // all surfaces.
-  if (window == delegate_->GetActiveRootWindow())
-    window_manager_surface_id_ = surface_id;
+  if (surface_info != window_manager_surface_info_) {
+    window_manager_surface_info_ = surface_info;
+    compositor_frame_sink_->SetNeedsBeginFrame(true);
+  }
 }
 
 void FrameGenerator::DidReceiveCompositorFrameAck() {}
@@ -91,6 +93,7 @@
 
     compositor_frame_sink_->SubmitCompositorFrame(local_frame_id_,
                                                   std::move(frame));
+    compositor_frame_sink_->SetNeedsBeginFrame(false);
     last_submitted_frame_size_ = frame_size;
   }
 }
@@ -112,7 +115,7 @@
   render_pass->SetNew(render_pass_id, output_rect, output_rect,
                       gfx::Transform());
 
-  DrawWindow(render_pass.get(), delegate_->GetActiveRootWindow());
+  DrawWindow(render_pass.get());
 
   cc::CompositorFrame frame;
   frame.render_pass_list.push_back(std::move(render_pass));
@@ -121,7 +124,10 @@
     invert_pass->SetNew(2, output_rect, output_rect, gfx::Transform());
     cc::SharedQuadState* shared_state =
         invert_pass->CreateAndAppendSharedQuadState();
-    shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect,
+    gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(
+        output_rect.size(), window_manager_surface_info_.device_scale_factor(),
+        window_manager_surface_info_.device_scale_factor());
+    shared_state->SetAll(gfx::Transform(), scaled_bounds, output_rect,
                          output_rect, false, 1.f, SkBlendMode::kSrcOver, 0);
     auto* quad = invert_pass->CreateAndAppendDrawQuad<cc::RenderPassDrawQuad>();
     render_pass->filters.Append(cc::FilterOperation::CreateInvertFilter(1.f));
@@ -134,48 +140,42 @@
   }
   frame.metadata.device_scale_factor = device_scale_factor_;
 
-  if (window_manager_surface_id_.is_valid())
-    frame.metadata.referenced_surfaces.push_back(window_manager_surface_id_);
+  if (window_manager_surface_info_.id().is_valid()) {
+    frame.metadata.referenced_surfaces.push_back(
+        window_manager_surface_info_.id());
+  }
 
   return frame;
 }
 
-void FrameGenerator::DrawWindow(cc::RenderPass* pass, ServerWindow* window) {
-  if (!window || !window->visible())
-    return;
+void FrameGenerator::DrawWindow(cc::RenderPass* pass) {
+  DCHECK(window_manager_surface_info_.id().is_valid());
 
-  if (!window->compositor_frame_sink_manager())
-    return;
-
-  cc::SurfaceId default_surface_id =
-      window->compositor_frame_sink_manager()->GetLatestSurfaceId();
-
-  if (!default_surface_id.is_valid())
-    return;
+  const gfx::Rect bounds_at_origin(
+      window_manager_surface_info_.size_in_pixels());
 
   gfx::Transform quad_to_target_transform;
-  quad_to_target_transform.Translate(window->bounds().x(),
-                                     window->bounds().y());
+  quad_to_target_transform.Translate(bounds_at_origin.x(),
+                                     bounds_at_origin.y());
 
   cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
 
-  const gfx::Rect bounds_at_origin(window->bounds().size());
+  gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(
+      bounds_at_origin.size(),
+      window_manager_surface_info_.device_scale_factor(),
+      window_manager_surface_info_.device_scale_factor());
+
   // TODO(fsamuel): These clipping and visible rects are incorrect. They need
   // to be populated from CompositorFrame structs.
-  sqs->SetAll(
-      quad_to_target_transform, bounds_at_origin.size() /* layer_bounds */,
-      bounds_at_origin /* visible_layer_bounds */,
-      bounds_at_origin /* clip_rect */, false /* is_clipped */,
-      1.0f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting-context_id */);
+  sqs->SetAll(quad_to_target_transform, scaled_bounds /* layer_bounds */,
+              bounds_at_origin /* visible_layer_bounds */,
+              bounds_at_origin /* clip_rect */, false /* is_clipped */,
+              1.0f /* opacity */, SkBlendMode::kSrcOver,
+              0 /* sorting-context_id */);
   auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
-  quad->SetAll(sqs, bounds_at_origin /* rect */,
-               gfx::Rect() /* opaque_rect */,
+  quad->SetAll(sqs, bounds_at_origin /* rect */, gfx::Rect() /* opaque_rect */,
                bounds_at_origin /* visible_rect */, true /* needs_blending*/,
-               default_surface_id);
-}
-
-void FrameGenerator::OnWindowDestroying(ServerWindow* window) {
-  Remove(window);
+               window_manager_surface_info_.id());
 }
 
 }  // namespace ws
diff --git a/services/ui/ws/frame_generator.h b/services/ui/ws/frame_generator.h
index d5f5b75..9e5f943a 100644
--- a/services/ui/ws/frame_generator.h
+++ b/services/ui/ws/frame_generator.h
@@ -23,7 +23,6 @@
 
 namespace cc {
 class RenderPass;
-class SurfaceId;
 }
 
 namespace ui {
@@ -38,22 +37,18 @@
 
 // Responsible for redrawing the display in response to the redraw requests by
 // submitting CompositorFrames to the owned CompositorFrameSink.
-class FrameGenerator : public ServerWindowTracker,
-                       public cc::mojom::MojoCompositorFrameSinkClient {
+class FrameGenerator : public cc::mojom::MojoCompositorFrameSinkClient {
  public:
   FrameGenerator(FrameGeneratorDelegate* delegate, ServerWindow* root_window);
   ~FrameGenerator() override;
 
-  void set_device_scale_factor(float device_scale_factor) {
-    device_scale_factor_ = device_scale_factor;
-  }
+  void SetDeviceScaleFactor(float device_scale_factor);
 
   // Schedules a redraw for the provided region.
   void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget);
 
-  // If |window| corresponds to the active WM for the display then update
-  // |window_manager_surface_id_|.
-  void OnSurfaceCreated(const cc::SurfaceId& surface_id, ServerWindow* window);
+  // Updates the WindowManager's SurfaceInfo.
+  void OnSurfaceCreated(const cc::SurfaceInfo& surface_info);
 
  private:
   friend class ui::ws::test::FrameGeneratorTest;
@@ -67,12 +62,9 @@
   // Generates the CompositorFrame.
   cc::CompositorFrame GenerateCompositorFrame(const gfx::Rect& output_rect);
 
-  // DrawWindow creates SurfaceDrawQuad for the provided ServerWindow and
-  // appends it to the provided cc::RenderPass.
-  void DrawWindow(cc::RenderPass* pass, ServerWindow* window);
-
-  // ServerWindowObserver implementation.
-  void OnWindowDestroying(ServerWindow* window) override;
+  // DrawWindow creates SurfaceDrawQuad for the window manager and appends it to
+  // the provided cc::RenderPass.
+  void DrawWindow(cc::RenderPass* pass);
 
   FrameGeneratorDelegate* delegate_;
   ServerWindow* const root_window_;
@@ -84,7 +76,7 @@
   cc::mojom::MojoCompositorFrameSinkAssociatedPtr compositor_frame_sink_;
   cc::mojom::DisplayPrivateAssociatedPtr display_private_;
 
-  cc::SurfaceId window_manager_surface_id_;
+  cc::SurfaceInfo window_manager_surface_info_;
 
   mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> binding_;
 
diff --git a/services/ui/ws/frame_generator_delegate.h b/services/ui/ws/frame_generator_delegate.h
index 88b2085..03fbcd04 100644
--- a/services/ui/ws/frame_generator_delegate.h
+++ b/services/ui/ws/frame_generator_delegate.h
@@ -10,8 +10,6 @@
 
 class FrameGeneratorDelegate {
  public:
-  // Returns the root window of the active user.
-  virtual ServerWindow* GetActiveRootWindow() = 0;
   virtual bool IsInHighContrastMode() = 0;
 
  protected:
diff --git a/services/ui/ws/frame_generator_unittest.cc b/services/ui/ws/frame_generator_unittest.cc
index bb30aa8..27e2230 100644
--- a/services/ui/ws/frame_generator_unittest.cc
+++ b/services/ui/ws/frame_generator_unittest.cc
@@ -71,17 +71,20 @@
 };
 
 void FrameGeneratorTest::DrawWindow(cc::RenderPass* pass) {
-  frame_generator_->DrawWindow(pass, root_window_.get());
+  cc::SurfaceId surface_id(cc::FrameSinkId(5, 5),
+                           cc::LocalFrameId(1u, kArbitraryToken));
+  frame_generator_->window_manager_surface_info_ =
+      cc::SurfaceInfo(surface_id, 2, gfx::Size(2, 2));
+  frame_generator_->DrawWindow(pass);
 }
 
 void FrameGeneratorTest::SetUp() {
   testing::Test::SetUp();
-  frame_generator_delegate_ =
-      base::MakeUnique<TestFrameGeneratorDelegate>(root_window_.get());
+  frame_generator_delegate_ = base::MakeUnique<TestFrameGeneratorDelegate>();
   PlatformDisplayInitParams init_params;
   frame_generator_ = base::MakeUnique<FrameGenerator>(
       frame_generator_delegate_.get(), root_window_.get());
-  frame_generator_->set_device_scale_factor(
+  frame_generator_->SetDeviceScaleFactor(
       init_params.metrics.device_scale_factor);
   InitWindow(root_window());
 }
diff --git a/services/ui/ws/platform_display_default.cc b/services/ui/ws/platform_display_default.cc
index ba50d30..c9f1b97 100644
--- a/services/ui/ws/platform_display_default.cc
+++ b/services/ui/ws/platform_display_default.cc
@@ -38,7 +38,7 @@
       frame_generator_(new FrameGenerator(this, init_params.root_window)),
       metrics_(init_params.metrics),
       widget_(gfx::kNullAcceleratedWidget) {
-  frame_generator_->set_device_scale_factor(
+  frame_generator_->SetDeviceScaleFactor(
       init_params.metrics.device_scale_factor);
 }
 
@@ -149,7 +149,7 @@
   }
 
   metrics_ = metrics;
-  frame_generator_->set_device_scale_factor(metrics_.device_scale_factor);
+  frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor);
   return true;
 }
 
@@ -255,10 +255,6 @@
 
 void PlatformDisplayDefault::OnActivationChanged(bool active) {}
 
-ServerWindow* PlatformDisplayDefault::GetActiveRootWindow() {
-  return delegate_->GetActiveRootWindow();
-}
-
 bool PlatformDisplayDefault::IsInHighContrastMode() {
   return delegate_ ? delegate_->IsInHighContrastMode() : false;
 }
diff --git a/services/ui/ws/platform_display_default.h b/services/ui/ws/platform_display_default.h
index f0f5326..ca1b7d5 100644
--- a/services/ui/ws/platform_display_default.h
+++ b/services/ui/ws/platform_display_default.h
@@ -69,7 +69,6 @@
   void OnActivationChanged(bool active) override;
 
   // FrameGeneratorDelegate:
-  ServerWindow* GetActiveRootWindow() override;
   bool IsInHighContrastMode() override;
 
   const int64_t display_id_;
diff --git a/services/ui/ws/platform_display_delegate.h b/services/ui/ws/platform_display_delegate.h
index 808717bb..0358573 100644
--- a/services/ui/ws/platform_display_delegate.h
+++ b/services/ui/ws/platform_display_delegate.h
@@ -28,9 +28,6 @@
   // Returns the root window of this display.
   virtual ServerWindow* GetRootWindow() = 0;
 
-  // Returns the root window of the active user.
-  virtual ServerWindow* GetActiveRootWindow() = 0;
-
   // Called once when the AcceleratedWidget is available for drawing.
   virtual void OnAcceleratedWidgetAvailable() = 0;
 
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc
index c89d695..1506bdc 100644
--- a/services/ui/ws/test_utils.cc
+++ b/services/ui/ws/test_utils.cc
@@ -154,16 +154,10 @@
 
 // TestFrameGeneratorDelegate -------------------------------------------------
 
-TestFrameGeneratorDelegate::TestFrameGeneratorDelegate(
-    ServerWindow* root_window)
-    : root_window_(root_window) {}
+TestFrameGeneratorDelegate::TestFrameGeneratorDelegate() {}
 
 TestFrameGeneratorDelegate::~TestFrameGeneratorDelegate() {}
 
-ServerWindow* TestFrameGeneratorDelegate::GetActiveRootWindow() {
-  return root_window_;
-}
-
 bool TestFrameGeneratorDelegate::IsInHighContrastMode() {
   return false;
 }
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h
index 0b323b9..43ce2a55 100644
--- a/services/ui/ws/test_utils.h
+++ b/services/ui/ws/test_utils.h
@@ -285,16 +285,12 @@
 // A stub implementation of FrameGeneratorDelegate.
 class TestFrameGeneratorDelegate : public FrameGeneratorDelegate {
  public:
-  TestFrameGeneratorDelegate(ServerWindow* root_window);
+  TestFrameGeneratorDelegate();
   ~TestFrameGeneratorDelegate() override;
 
   // FrameGeneratorDelegate:
-  ServerWindow* GetActiveRootWindow() override;
   bool IsInHighContrastMode() override;
 
- private:
-  ServerWindow* root_window_;
-
   DISALLOW_COPY_AND_ASSIGN(TestFrameGeneratorDelegate);
 };
 
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc
index b41585f..c4758a5 100644
--- a/services/ui/ws/window_server.cc
+++ b/services/ui/ws/window_server.cc
@@ -787,10 +787,11 @@
 
   // FrameGenerator will add an appropriate reference for the new surface.
   DCHECK(display_manager_->GetDisplayContaining(window));
-  display_manager_->GetDisplayContaining(window)
-      ->platform_display()
-      ->GetFrameGenerator()
-      ->OnSurfaceCreated(surface_info.id(), window);
+  auto display = display_manager_->GetDisplayContaining(window);
+  if (window == display->GetActiveRootWindow()) {
+    display->platform_display()->GetFrameGenerator()->OnSurfaceCreated(
+        surface_info);
+  }
 
   // This is only used for testing to observe that a window has a
   // CompositorFrame.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 7e7c20a..985e8e5f 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2247,17 +2247,9 @@
 crbug.com/664844 media/track/track-cue-rendering-tree-is-removed-properly.html [ Pass Failure ]
 crbug.com/664844 media/track/track-default-attribute.html [ Pass Failure ]
 crbug.com/664844 media/track/track-kind-user-preference.html [ Pass Failure ]
-crbug.com/664853 virtual/mojo-loading/webexposed/css-properties-as-js-properties.html [ Pass Failure ]
-crbug.com/664853 virtual/mojo-loading/webexposed/web-animations-api.html [ Pass Failure ]
 crbug.com/664855 virtual/scroll_customization/fast/scroll-behavior/main-frame-interrupted-scroll.html [ Pass Failure ]
 crbug.com/664856 virtual/sharedarraybuffer/fast/workers/worker-gc.html [ Pass Failure ]
 
-crbug.com/583193 inspector-protocol/debugger/stepping-with-blackboxed-ranges.html [ NeedsManualRebaseline ]
-crbug.com/583193 inspector/sources/debugger-frameworks/frameworks-jquery.html [ NeedsManualRebaseline ]
-crbug.com/583193 inspector/sources/debugger-frameworks/frameworks-steppings.html [ NeedsManualRebaseline ]
-crbug.com/583193 inspector/sources/debugger-frameworks/frameworks-skip-step-in.html [ NeedsManualRebaseline ]
-crbug.com/583193 inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout.html [ NeedsManualRebaseline ]
-
 # Possible duplicate of crbug.com/665577
 # crbug.com/664858 virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html [ Pass Failure ]
 # crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html [ Pass Failure ]
@@ -2265,6 +2257,9 @@
 # crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-anchors.html [ Pass Failure ]
 # crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-vertical-rl-anchors.html [ Pass Failure ]
 # crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/scroll-during-selection.html [ Pass Failure ]
+
+crbug.com/684874 virtual/threaded/fast/scroll-behavior/smooth-scroll/scroll-during-selection.html [ Pass Failure ]
+
 # ====== Random order flaky tests end here ======
 
 # ====== Begin of display:contents tests ======
@@ -2338,3 +2333,6 @@
 crbug.com/681471 virtual/stable/paint/invalidation/media-audio-no-spurious-repaints.html [ Failure Pass Timeout ]
 
 crbug.com/683800 [ Win7 Debug ] external/wpt/selection/ [ Failure Pass ]
+
+# CQ and Rebaseline-cl for crrev.com/2626973005 does not include this
+crbug.com/680407 [ Mac ] fast/forms/select/menulist-appearance-basic.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
index 685ab78e..4f7e8a7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js
@@ -288,6 +288,16 @@
     return InspectorTest.timelineModel().mainThreadEvents().filter(e => e.name === name)[index || 0];
 }
 
+InspectorTest.findChildEvent = function(events, parentIndex, name)
+{
+    var endTime = events[parentIndex].endTime;
+    for (var i = parentIndex + 1; i < events.length && (!events[i].endTime || events[i].endTime <= endTime); ++i) {
+        if (events[i].name === name)
+            return events[i];
+    }
+    return null;
+}
+
 InspectorTest.FakeFileReader = function(input, delegate, callback)
 {
     this._delegate = delegate;
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions-expected.txt
index caceac4b..25022c43 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions-expected.txt
@@ -71,18 +71,39 @@
 Checking 'shou'
 Not Found: should not find this
 
+Checking 'myMap.get('
+Found: "first")
+Found: "second")
+Found: "third")
+
+Checking 'myMap.get(''
+Found: 'first')
+Found: 'second')
+Found: 'third')
+
+Checking 'myMap.set('firs'
+Found: 'first', 
+
+Checking 'myMap.set(should'
+Found: shouldFindThisFunction
+Not Found: shouldNotFindThis
+Not Found: "shouldNotFindThis")
+
+Checking 'myMap.delete(''
+Found: 'first')
+Found: 'second')
+Found: 'third')
+
 Checking 'document.   bo'
 Found: body
 
 Checking 'document.	bo'
 Found: body
 
-Checking 'document.
-bo'
+Checking 'document.\nbo'
 Found: body
 
-Checking 'document.
-bo'
+Checking 'document.\r\nbo'
 Found: body
 
 Checking 'document   [    'bo'
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions.html b/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions.html
index 2dd77ca2..20ee94f 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-correct-suggestions.html
@@ -12,9 +12,11 @@
 }
 
 function shouldNotFindThisFunction() { }
-
+function shouldFindThisFunction() { }
 window["should not find this"] = true;
 
+var myMap = new Map([['first', 1], ['second', 2], ['third', 3], ['shouldNotFindThis', 4]]);
+
 function test()
 {
     var consoleEditor;
@@ -31,7 +33,7 @@
         function checkExpected(suggestions)
         {
             var completions = new Set(suggestions.map(suggestion => suggestion.title));
-            var message = "Checking '" + text + "'";
+            var message = "Checking '" + text.replace('\n', '\\n').replace('\r', '\\r') + "'";
             if (force)
                 message += " forcefully";
             InspectorTest.addResult(message);
@@ -72,6 +74,11 @@
         () => testCompletions("// do", ["document"], false),
         () => testCompletions('["should', ["shouldNotFindThisFunction"]),
         () => testCompletions("shou", ["should not find this"]),
+        () => testCompletions('myMap.get(', ['"first")', '"second")', '"third")']),
+        () => testCompletions('myMap.get(\'', ['\'first\')', '\'second\')', '\'third\')']),
+        () => testCompletions('myMap.set(\'firs', ['\'first\', ']),
+        () => testCompletions('myMap.set(should', ['shouldFindThisFunction', 'shouldNotFindThis', '\"shouldNotFindThis\")']),
+        () => testCompletions('myMap.delete(\'', ['\'first\')', '\'second\')', '\'third\')']),
         () => testCompletions("document.   bo", ["body"]),
         () => testCompletions("document.\tbo", ["body"]),
         () => testCompletions("document.\nbo", ["body"]),
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html
index d068362..e11b4e5 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html
@@ -36,8 +36,8 @@
         for (let i = 0; i < events.length; ++i) {
             if (events[i].name !== TimelineModel.TimelineModel.RecordType.TimerFire)
                 continue;
-            var nextEvent = events[i + 1];
-            var fnCallSite = nextEvent.args["data"];
+            var functionCallChild = InspectorTest.findChildEvent(events, i, TimelineModel.TimelineModel.RecordType.FunctionCall);
+            var fnCallSite = functionCallChild.args["data"];
             InspectorTest.addResult(`${events[i].name} ${fnCallSite.url}:${fnCallSite.lineNumber + 1}`);
         }
         InspectorTest.completeTest();
diff --git a/third_party/WebKit/LayoutTests/presentation/presentation-start-error.html b/third_party/WebKit/LayoutTests/presentation/presentation-start-error.html
new file mode 100644
index 0000000..6cd746e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/presentation/presentation-start-error.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/mojo-helpers.js"></script>
+<script src="resources/presentation-service-mock.js"></script>
+<button>click me</button>
+<script>
+
+var button = document.querySelector('button');
+
+async_test(t => {
+  presentationServiceMock.then(service => {
+    service.startSession = urls => {
+      return Promise.resolve({
+        sessionInfo: null,
+        error: {
+          error_type: 3 /* PresentationErrorType.PREVIOUS_START_IN_PROGRESS */,
+          message: 'Previous start in progress'
+        }
+      });
+    };
+    // This is receiving the user gesture and runs the callback.
+    waitForClick(() => {
+      var request = new PresentationRequest("http://example.com");
+      request.start().catch(t.step_func_done(ex => {
+        assert_equals(ex.name, 'OperationError');
+      }));
+    }, button);
+  });
+}, "Test that the PresentationRequest.start() rejects with OperationError if PresentationService reports PREVIOUS_START_IN_PROGRESS error");
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/presentation/presentation-start.html b/third_party/WebKit/LayoutTests/presentation/presentation-start.html
index 1f824ea..f23de70 100644
--- a/third_party/WebKit/LayoutTests/presentation/presentation-start.html
+++ b/third_party/WebKit/LayoutTests/presentation/presentation-start.html
@@ -11,15 +11,15 @@
 var button = document.querySelector('button');
 
 var testPresentationRequestStart = function(t, requestArgument, connectionUrl) {
-  presentationServiceMock.then(t.step_func(service => {
+  presentationServiceMock.then(service => {
     // This is receiving the user gesture and runs the callback.
-    waitForClick(t.step_func(_ => {
+    waitForClick(() => {
       new PresentationRequest(requestArgument).start().then(
       t.step_func_done(connection => {
         assert_equals(connection.url, connectionUrl);
       }));
-    }), button);
-  }));
+    }, button);
+  });
 };
 
 async_test(t => {
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index cc40d0e..16517766f 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -378,6 +378,7 @@
     "properties/CSSPropertyAPIPaintOrder.cpp",
     "properties/CSSPropertyAPIPaintStroke.cpp",
     "properties/CSSPropertyAPIQuotes.cpp",
+    "properties/CSSPropertyAPIRadius.cpp",
     "properties/CSSPropertyAPIRotate.cpp",
     "properties/CSSPropertyAPIScale.cpp",
     "properties/CSSPropertyAPIScrollSnapCoordinate.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in
index b621586..1866879 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.in
+++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -346,8 +346,8 @@
 resize custom_value
 right typedom_types=[Length], keywords=[auto], supports_percentage, interpolable, initial=initialOffset, converter=convertLengthOrAuto
 r interpolable, svg, converter=convertLength
-rx interpolable, svg, converter=convertLengthOrAuto
-ry interpolable, svg, converter=convertLengthOrAuto
+rx interpolable, svg, converter=convertLengthOrAuto, api_class=CSSPropertyAPIRadius
+ry interpolable, svg, converter=convertLengthOrAuto, api_class=CSSPropertyAPIRadius
 scroll-behavior runtime_flag=CSSOMSmoothScroll, type_name=ScrollBehavior
 scroll-snap-type runtime_flag=CSSScrollSnapPoints, type_name=ScrollSnapType
 scroll-snap-points-x runtime_flag=CSSScrollSnapPoints, converter=convertSnapPoints
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 1c6eb882..a757e70 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1163,13 +1163,6 @@
   return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll);
 }
 
-static CSSValue* consumeRxOrRy(CSSParserTokenRange& range) {
-  if (range.peek().id() == CSSValueAuto)
-    return consumeIdent(range);
-  return consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeAll,
-                                UnitlessQuirk::Forbid);
-}
-
 static CSSValue* consumePerspective(CSSParserTokenRange& range,
                                     const CSSParserContext* context,
                                     CSSPropertyID unresolvedProperty) {
@@ -2275,9 +2268,6 @@
     case CSSPropertyR:
       return consumeLengthOrPercent(m_range, SVGAttributeMode, ValueRangeAll,
                                     UnitlessQuirk::Forbid);
-    case CSSPropertyRx:
-    case CSSPropertyRy:
-      return consumeRxOrRy(m_range);
     case CSSPropertyPerspective:
       return consumePerspective(m_range, m_context, unresolvedProperty);
     case CSSPropertyScrollSnapPointsX:
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp
new file mode 100644
index 0000000..ce9b83e
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIRadius.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIRadius::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  if (range.peek().id() == CSSValueAuto)
+    return CSSPropertyParserHelpers::consumeIdent(range);
+  return CSSPropertyParserHelpers::consumeLengthOrPercent(
+      range, SVGAttributeMode, ValueRangeAll,
+      CSSPropertyParserHelpers::UnitlessQuirk::Forbid);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/DocumentTest.cpp b/third_party/WebKit/Source/core/dom/DocumentTest.cpp
index df59289..d9e2f2f 100644
--- a/third_party/WebKit/Source/core/dom/DocumentTest.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentTest.cpp
@@ -123,10 +123,6 @@
     return m_contextDestroyedCalledCounter;
   }
 
-  const HeapVector<Member<const Element>>& attributeChangedElements() const {
-    return m_attributeChangedElements;
-  }
-
   const HeapVector<Member<const ContainerNode>>& childrenChangedNodes() const {
     return m_childrenChangedNodes;
   }
@@ -162,7 +158,6 @@
  private:
   // Implement |SynchronousMutationObserver| member functions.
   void contextDestroyed(Document*) final;
-  void didChangeAttribute(const Element&) final;
   void didChangeChildren(const ContainerNode&) final;
   void didMergeTextNodes(const Text&, const NodeWithIndex&, unsigned) final;
   void didMoveTreeToNewDocument(const Node& root) final;
@@ -175,7 +170,6 @@
   void nodeWillBeRemoved(Node&) final;
 
   int m_contextDestroyedCalledCounter = 0;
-  HeapVector<Member<const Element>> m_attributeChangedElements;
   HeapVector<Member<const ContainerNode>> m_childrenChangedNodes;
   HeapVector<Member<MergeTextNodesRecord>> m_mergeTextNodesRecords;
   HeapVector<Member<const Node>> m_moveTreeToNewDocumentNodes;
@@ -196,11 +190,6 @@
   ++m_contextDestroyedCalledCounter;
 }
 
-void TestSynchronousMutationObserver::didChangeAttribute(
-    const Element& element) {
-  m_attributeChangedElements.push_back(&element);
-}
-
 void TestSynchronousMutationObserver::didChangeChildren(
     const ContainerNode& container) {
   m_childrenChangedNodes.push_back(&container);
@@ -242,7 +231,6 @@
 }
 
 DEFINE_TRACE(TestSynchronousMutationObserver) {
-  visitor->trace(m_attributeChangedElements);
   visitor->trace(m_childrenChangedNodes);
   visitor->trace(m_mergeTextNodesRecords);
   visitor->trace(m_moveTreeToNewDocumentNodes);
@@ -517,24 +505,6 @@
   EXPECT_EQ(1, observer.countContextDestroyedCalled());
 }
 
-TEST_F(DocumentTest, SynchronousMutationNotifierChangeAttribute) {
-  auto& observer = *new TestSynchronousMutationObserver(document());
-  Element* divNode = document().createElement("div");
-  document().body()->appendChild(divNode);
-  divNode->setAttribute(HTMLNames::classAttr, "foo");
-
-  ASSERT_EQ(1u, observer.attributeChangedElements().size());
-  EXPECT_EQ(divNode, observer.attributeChangedElements()[0]);
-
-  divNode->setAttribute(HTMLNames::classAttr, "bar");
-  ASSERT_EQ(2u, observer.attributeChangedElements().size());
-  EXPECT_EQ(divNode, observer.attributeChangedElements()[1]);
-
-  divNode->removeAttribute(HTMLNames::classAttr);
-  ASSERT_EQ(3u, observer.attributeChangedElements().size());
-  EXPECT_EQ(divNode, observer.attributeChangedElements()[2]);
-}
-
 TEST_F(DocumentTest, SynchronousMutationNotifieAppendChild) {
   auto& observer = *new TestSynchronousMutationObserver(document());
   document().body()->appendChild(document().createTextNode("a123456789"));
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index ee87d5e..77e51203 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -1297,7 +1297,6 @@
   parseAttribute(params);
 
   document().incDOMTreeVersion();
-  document().notifyChangeAttribute(*this);
 
   if (name == HTMLNames::idAttr) {
     AtomicString oldId = elementData()->idForStyleResolution();
diff --git a/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.cpp b/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.cpp
index 59474ec..506cdb9 100644
--- a/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.cpp
+++ b/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.cpp
@@ -11,12 +11,6 @@
 
 SynchronousMutationNotifier::SynchronousMutationNotifier() = default;
 
-void SynchronousMutationNotifier::notifyChangeAttribute(
-    const Element& element) {
-  for (SynchronousMutationObserver* observer : m_observers)
-    observer->didChangeAttribute(element);
-}
-
 void SynchronousMutationNotifier::notifyChangeChildren(
     const ContainerNode& container) {
   for (SynchronousMutationObserver* observer : m_observers)
diff --git a/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.h b/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.h
index 2c1f4b2..813f209 100644
--- a/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.h
+++ b/third_party/WebKit/Source/core/dom/SynchronousMutationNotifier.h
@@ -14,7 +14,6 @@
 class CharacterData;
 class ContainerNode;
 class Document;
-class Element;
 class Node;
 class NodeWithIndex;
 class SynchronousMutationObserver;
@@ -23,7 +22,8 @@
 class CORE_EXPORT SynchronousMutationNotifier
     : public LifecycleNotifier<Document, SynchronousMutationObserver> {
  public:
-  void notifyChangeAttribute(const Element&);
+  // TODO(yosin): We will have |notifyXXX()| functions defined in
+  // |SynchronousMutationObserver|.
   void notifyChangeChildren(const ContainerNode&);
   void notifyMergeTextNodes(const Text& mergedNode,
                             const NodeWithIndex& nodeToBeRemovedWithIndex,
diff --git a/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.cpp b/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.cpp
index 2ceae32..1840e8b 100644
--- a/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.cpp
+++ b/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.cpp
@@ -12,7 +12,6 @@
 SynchronousMutationObserver::SynchronousMutationObserver()
     : LifecycleObserver(nullptr) {}
 
-void SynchronousMutationObserver::didChangeAttribute(const Element&) {}
 void SynchronousMutationObserver::didChangeChildren(const ContainerNode&) {}
 void SynchronousMutationObserver::didMergeTextNodes(const Text&,
                                                     const NodeWithIndex&,
diff --git a/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h b/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h
index 8d4d17f..ad0311ca 100644
--- a/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h
+++ b/third_party/WebKit/Source/core/dom/SynchronousMutationObserver.h
@@ -14,7 +14,6 @@
 class CharacterData;
 class ContainerNode;
 class Document;
-class Element;
 class NodeWithIndex;
 class Text;
 
@@ -41,9 +40,6 @@
   //  - didInsertText(Node*, unsigned offset, unsigned length);
   //  - didRemoveText(Node*, unsigned offset, unsigned length);
 
-  // Called just after attribute is changed.
-  virtual void didChangeAttribute(const Element&);
-
   // Called after child nodes changed.
   virtual void didChangeChildren(const ContainerNode&);
 
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index d5e4f34..19c6471a 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -929,11 +929,6 @@
   return nullptr;
 }
 
-bool nodeIsUserSelectAll(const Node* node) {
-  return node && node->layoutObject() &&
-         node->layoutObject()->style()->userSelect() == SELECT_ALL;
-}
-
 EUserSelect usedValueOfUserSelect(const Node& node) {
   if (node.isHTMLElement() && toHTMLElement(node).isTextControl())
     return SELECT_TEXT;
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h
index 0b334ec5..563e02d 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.h
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -187,7 +187,6 @@
 CORE_EXPORT bool areIdenticalElements(const Node&, const Node&);
 bool isNonTableCellHTMLBlockElement(const Node*);
 bool isBlockFlowElement(const Node&);
-bool nodeIsUserSelectAll(const Node*);
 EUserSelect usedValueOfUserSelect(const Node&);
 bool isTextSecurityNode(const Node*);
 CORE_EXPORT TextDirection directionOfEnclosingBlock(const Position&);
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index 6c84cce7..7366ca2 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1743,6 +1743,11 @@
   return honorEditingBoundaryAtOrAfter(next, c.deepEquivalent());
 }
 
+static bool nodeIsUserSelectAll(const Node* node) {
+  return node && node->layoutObject() &&
+         node->layoutObject()->style()->userSelect() == SELECT_ALL;
+}
+
 template <typename Strategy>
 PositionTemplate<Strategy> startOfParagraphAlgorithm(
     const PositionTemplate<Strategy>& position,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index a9880e4..bd10701 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -179,6 +179,7 @@
 }  // namespace
 
 NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(
+    LayoutObject* layout_object,
     PassRefPtr<const ComputedStyle> style,
     NGBlockNode* first_child,
     NGConstraintSpace* constraint_space,
@@ -188,6 +189,8 @@
       first_child_(first_child),
       constraint_space_(constraint_space),
       break_token_(break_token),
+      builder_(new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox,
+                                     layout_object)),
       is_fragment_margin_strut_block_start_updated_(false) {
   DCHECK(style_);
 }
@@ -261,7 +264,6 @@
   space_builder_->SetPercentageResolutionSize(
       NGLogicalSize(adjusted_inline_size, adjusted_block_size));
 
-  builder_ = new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox);
   builder_->SetDirection(constraint_space_->Direction());
   builder_->SetWritingMode(constraint_space_->WritingMode());
   builder_->SetInlineSize(inline_size).SetBlockSize(block_size);
@@ -306,8 +308,7 @@
       ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_);
   builder_->SetBlockSize(block_size);
 
-  HeapLinkedHashSet<WeakMember<NGBlockNode>> positioned_out_of_flow_children =
-      LayoutOutOfFlowChildren();
+  LayoutOutOfFlowChildren();
 
   builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_);
 
@@ -316,9 +317,6 @@
 
   NGPhysicalFragment* fragment = builder_->ToBoxFragment();
 
-  for (auto& node : positioned_out_of_flow_children)
-    node->PositionUpdated();
-
   return fragment;
 }
 
@@ -341,8 +339,7 @@
   builder_->AddChild(fragment, fragment_offset);
 }
 
-HeapLinkedHashSet<WeakMember<NGBlockNode>>
-NGBlockLayoutAlgorithm::LayoutOutOfFlowChildren() {
+void NGBlockLayoutAlgorithm::LayoutOutOfFlowChildren() {
   HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates;
   Vector<NGStaticPosition> out_of_flow_candidate_positions;
   builder_->GetAndClearOutOfFlowDescendantCandidates(
@@ -350,7 +347,6 @@
 
   Member<NGOutOfFlowLayoutPart> out_of_flow_layout =
       new NGOutOfFlowLayoutPart(&Style(), builder_->Size());
-  HeapLinkedHashSet<WeakMember<NGBlockNode>> positioned_children;
   size_t candidate_positions_index = 0;
 
   for (auto& child : out_of_flow_candidates) {
@@ -362,13 +358,11 @@
       NGLogicalOffset offset;
       out_of_flow_layout->Layout(*child, static_position, &fragment, &offset);
       // TODO(atotic) Need to adjust size of overflow rect per spec.
-      positioned_children.add(child);
       builder_->AddChild(fragment, offset);
     } else {
       builder_->AddOutOfFlowDescendant(child, static_position);
     }
   }
-  return positioned_children;
 }
 
 bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
index 1524af04..b0599801 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -29,12 +29,14 @@
 class CORE_EXPORT NGBlockLayoutAlgorithm : public NGLayoutAlgorithm {
  public:
   // Default constructor.
+  // @param layout_object The layout object associated with this block.
   // @param style Style reference of the block that is being laid out.
   // @param first_child Our first child; the algorithm will use its NextSibling
   //                    method to access all the children.
   // @param space The constraint space which the algorithm should generate a
   //              fragment within.
-  NGBlockLayoutAlgorithm(PassRefPtr<const ComputedStyle>,
+  NGBlockLayoutAlgorithm(LayoutObject* layout_object,
+                         PassRefPtr<const ComputedStyle> style,
                          NGBlockNode* first_child,
                          NGConstraintSpace* space,
                          NGBreakToken* break_token = nullptr);
@@ -51,7 +53,7 @@
   // Creates a new constraint space for the current child.
   NGConstraintSpace* CreateConstraintSpaceForCurrentChild();
   void FinishCurrentChildLayout(NGFragment* fragment);
-  HeapLinkedHashSet<WeakMember<NGBlockNode>> LayoutOutOfFlowChildren();
+  void LayoutOutOfFlowChildren();
 
   // Proceed to the next sibling that still needs layout.
   //
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
index d5189a5..ff60378 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -4,20 +4,28 @@
 
 #include "core/layout/ng/ng_block_layout_algorithm.h"
 
+#include "core/dom/NodeComputedStyle.h"
+#include "core/dom/TagCollection.h"
+#include "core/layout/ng/layout_ng_block_flow.h"
 #include "core/layout/ng/ng_block_node.h"
 #include "core/layout/ng/ng_constraint_space.h"
 #include "core/layout/ng/ng_constraint_space_builder.h"
+#include "core/layout/ng/ng_floating_object.h"
 #include "core/layout/ng/ng_length_utils.h"
+#include "core/layout/LayoutTestHelper.h"
 #include "core/layout/ng/ng_physical_box_fragment.h"
 #include "core/layout/ng/ng_physical_fragment.h"
 #include "core/layout/ng/ng_units.h"
-#include "core/layout/LayoutTestHelper.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "core/style/ComputedStyle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
 namespace {
 
+using testing::ElementsAre;
+using testing::Pointee;
+
 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode,
                                             TextDirection direction,
                                             NGLogicalSize size,
@@ -50,19 +58,32 @@
     NGBlockNode parent(style_.get());
     parent.SetFirstChild(first_child);
 
-    NGBlockLayoutAlgorithm algorithm(style_.get(), first_child, space);
+    NGBlockLayoutAlgorithm algorithm(/* layout_object */ nullptr, style_.get(),
+                                     first_child, space);
 
     NGPhysicalFragment* fragment = algorithm.Layout();
     return toNGPhysicalBoxFragment(fragment);
   }
 
+  std::pair<NGPhysicalBoxFragment*, NGConstraintSpace*>
+  RunBlockLayoutAlgorithmForElement(Element* element) {
+    LayoutNGBlockFlow* block_flow =
+        toLayoutNGBlockFlow(element->layoutObject());
+    NGConstraintSpace* space =
+        NGConstraintSpace::CreateFromLayoutObject(*block_flow);
+    NGPhysicalBoxFragment* fragment = RunBlockLayoutAlgorithm(
+        space, new NGBlockNode(element->layoutObject()->slowFirstChild()));
+    return std::make_pair(fragment, space);
+  }
+
   MinAndMaxContentSizes RunComputeMinAndMax(NGBlockNode* first_child) {
     // The constraint space is not used for min/max computation, but we need
     // it to create the algorithm.
     NGConstraintSpace* space =
         ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr,
                                  NGLogicalSize(LayoutUnit(), LayoutUnit()));
-    NGBlockLayoutAlgorithm algorithm(style_.get(), first_child, space);
+    NGBlockLayoutAlgorithm algorithm(/* layout_object */ nullptr, style_.get(),
+                                     first_child, space);
     MinAndMaxContentSizes sizes;
     EXPECT_TRUE(algorithm.ComputeMinAndMaxContentSizes(&sizes));
     return sizes;
@@ -167,237 +188,352 @@
 
 // Verifies the collapsing margins case for the next pair:
 // - top margin of a box and top margin of its first in-flow child.
-//
-// Test case's HTML representation:
-// <div style="margin-top: 20px; height: 50px;">  <!-- DIV1 -->
-//    <div style="margin-top: 10px"></div>        <!-- DIV2 -->
-// </div>
-//
-// Expected:
-// - Empty margin strut of the fragment that establishes new formatting context
-// - Margins are collapsed resulting a single margin 20px = max(20px, 10px)
-// - The top offset of DIV2 == 20px
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1) {
-  const int kHeight = 50;
-  const int kDiv1MarginTop = 20;
-  const int kDiv2MarginTop = 10;
+// Verifies that floats are positioned at the top of the first child that can
+// determine its position after margins collapsed.
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase1WithFloats) {
+  setBodyInnerHTML(
+      "<style>"
+      "  #container {"
+      "    height: 200px;"
+      "    width: 200px;"
+      "    margin-top: 10px;"
+      "    padding: 0 7px;"
+      "    background-color: red;"
+      "  }"
+      "  #first-child {"
+      "    margin-top: 20px;"
+      "    height: 10px;"
+      "    background-color: blue;"
+      "  }"
+      "  #float-child-left {"
+      "    float: left;"
+      "    height: 10px;"
+      "    width: 10px;"
+      "    padding: 10px;"
+      "    margin: 10px;"
+      "    background-color: green;"
+      "  }"
+      "  #float-child-right {"
+      "    float: right;"
+      "    height: 30px;"
+      "    width: 30px;"
+      "    background-color: pink;"
+      "  }"
+      "</style>"
+      "<div id='container'>"
+      "  <div id='float-child-left'></div>"
+      "  <div id='float-child-right'></div>"
+      "  <div id='first-child'></div>"
+      "</div>");
 
-  // DIV1
-  RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
-  div1_style->setHeight(Length(kHeight, Fixed));
-  div1_style->setMarginTop(Length(kDiv1MarginTop, Fixed));
-  NGBlockNode* div1 = new NGBlockNode(div1_style.get());
+  // ** Run LayoutNG algorithm **
+  NGConstraintSpace* space;
+  NGPhysicalBoxFragment* fragment;
+  std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+      document().getElementsByTagName("html")->item(0));
+  ASSERT_EQ(fragment->Children().size(), 1UL);
+  auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+  // 20 = max(first child's margin top, containers's margin top)
+  int body_top_offset = 20;
+  EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+  // 8 = body's margin
+  int body_left_offset = 8;
+  EXPECT_THAT(LayoutUnit(body_left_offset), body_fragment->LeftOffset());
+  ASSERT_EQ(1UL, body_fragment->Children().size());
+  auto* container_fragment =
+      toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+  // 0 = collapsed with body's margin
+  EXPECT_THAT(LayoutUnit(0), container_fragment->TopOffset());
+  ASSERT_EQ(1UL, container_fragment->Children().size());
+  auto* first_child_fragment =
+      toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+  // 0 = collapsed with container's margin
+  EXPECT_THAT(LayoutUnit(0), first_child_fragment->TopOffset());
 
-  // DIV2
-  RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
-  div2_style->setMarginTop(Length(kDiv2MarginTop, Fixed));
-  NGBlockNode* div2 = new NGBlockNode(div2_style.get());
+  // ** Verify layout tree **
+  Element* first_child = document().getElementById("first-child");
+  int first_child_block_offset = body_top_offset;
+  EXPECT_EQ(first_child_block_offset, first_child->offsetTop());
 
-  div1->SetFirstChild(div2);
+  // float-child-left is positioned at the top edge of the container padding box
+  Element* float_child_left = document().getElementById("float-child-left");
+  // 30 = std::max(first-child's margin 20, container's margin 10,
+  //      body's margin 8) + float-child-left's margin 10
+  int float_child_left_block_offset = 30;
+  EXPECT_EQ(float_child_left_block_offset, float_child_left->offsetTop());
 
-  auto* space =
-      NGConstraintSpaceBuilder(kHorizontalTopBottom)
-          .SetAvailableSize(NGLogicalSize(LayoutUnit(100), NGSizeIndefinite))
-          .SetPercentageResolutionSize(
-              NGLogicalSize(LayoutUnit(100), NGSizeIndefinite))
-          .SetTextDirection(TextDirection::kLtr)
-          .SetIsNewFormattingContext(true)
-          .ToConstraintSpace();
-  NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
+  // float-child-right is positioned at the top edge of container padding box
+  Element* float_child_right = document().getElementById("float-child-right");
+  // Should be equal to first_child_block_offset
+  // 20 = std::max(first-child's margin 20, container's margin 10,
+  //      body's margin 8)
+  int float_child_right_block_offset = 20;
+  EXPECT_EQ(float_child_right_block_offset, float_child_right->offsetTop());
 
-  EXPECT_TRUE(frag->MarginStrut().IsEmpty());
-  ASSERT_EQ(frag->Children().size(), 1UL);
-  const NGPhysicalBoxFragment* div2_fragment =
-      static_cast<const NGPhysicalBoxFragment*>(frag->Children()[0].get());
-  EXPECT_EQ(NGDeprecatedMarginStrut({LayoutUnit(kDiv2MarginTop)}),
-            div2_fragment->MarginStrut());
-  EXPECT_EQ(kDiv1MarginTop, div2_fragment->TopOffset());
+  // ** Verify exclusions **
+  // float-child-left's height(10) + padding(2x10) + margin(2x10) = 50px
+  NGLogicalSize exclusion1_size = {LayoutUnit(50), LayoutUnit(50)};
+  // float-child-left's inline offset
+  // 15 = body's margin(8) + container's inline padding(7)
+  NGLogicalOffset exclusion1_offset = {LayoutUnit(15),
+                                       LayoutUnit(first_child_block_offset)};
+  NGLogicalRect exclusion1_rect = {exclusion1_offset, exclusion1_size};
+  NGExclusion expected_exclusion1 = {exclusion1_rect, NGExclusion::kFloatLeft};
+
+  NGLogicalSize exclusion2_size = {LayoutUnit(30), LayoutUnit(30)};
+  // float-child-right's inline offset
+  // right_float_offset = 200 container's width - right float width 30 = 170
+  // 185 = body's margin(8) + right_float_offset(170) + container's padding(7)
+  NGLogicalOffset exclusion2_offset = {LayoutUnit(185),
+                                       LayoutUnit(first_child_block_offset)};
+  NGLogicalRect exclusion2_rect = {exclusion2_offset, exclusion2_size};
+  NGExclusion expected_exclusion2 = {exclusion2_rect, NGExclusion::kFloatRight};
+
+  EXPECT_THAT(space->Exclusions()->storage,
+              (ElementsAre(Pointee(expected_exclusion1),
+                           Pointee(expected_exclusion2))));
 }
 
 // Verifies the collapsing margins case for the next pair:
 // - bottom margin of box and top margin of its next in-flow following sibling.
-//
-// Test case's HTML representation:
-// <div style="margin-bottom: 20px; height: 50px;">  <!-- DIV1 -->
-//    <div style="margin-bottom: -15px"></div>       <!-- DIV2 -->
-//    <div></div>                                    <!-- DIV3 -->
-// </div>
-// <div></div>                                       <!-- DIV4 -->
-// <div style="margin-top: 10px; height: 50px;">     <!-- DIV5 -->
-//    <div></div>                                    <!-- DIV6 -->
-//    <div style="margin-top: -30px"></div>          <!-- DIV7 -->
-// </div>
-//
-// Expected:
-//   Margins are collapsed resulting an overlap
-//   -10px = max(20px, 10px) - max(abs(-15px), abs(-30px))
-//   between DIV2 and DIV3. Zero-height blocks are ignored.
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2) {
-  const int kHeight = 50;
-  const int kDiv1MarginBottom = 20;
-  const int kDiv2MarginBottom = -15;
-  const int kDiv5MarginTop = 10;
-  const int kDiv7MarginTop = -30;
-  const int kExpectedCollapsedMargin = -10;
+// - top and bottom margins of a box that does not establish a new block
+//   formatting context and that has zero computed 'min-height', zero or 'auto'
+//   computed 'height', and no in-flow children
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase2WithFloats) {
+  setBodyInnerHTML(
+      "<style>"
+      "#first-child {"
+      "  background-color: red;"
+      "  height: 50px;"
+      "  margin-bottom: 20px;"
+      "}"
+      "#float-between-empties {"
+      "  background-color: green;"
+      "  float: left;"
+      "  height: 30px;"
+      "  width: 30px;"
+      "}"
+      "#float-between-nonempties {"
+      "  background-color: lightgreen;"
+      "  float: left;"
+      "  height: 40px;"
+      "  width: 40px;"
+      "}"
+      "#float-top-align {"
+      "  background-color: seagreen;"
+      "  float: left;"
+      "  height: 50px;"
+      "  width: 50px;"
+      "}"
+      "#second-child {"
+      "  background-color: blue;"
+      "  height: 50px;"
+      "  margin-top: 10px;"
+      "}"
+      "</style>"
+      "<div id='first-child'>"
+      "  <div id='empty1' style='margin-bottom: -15px'></div>"
+      "  <div id='float-between-empties'></div>"
+      "  <div id='empty2'></div>"
+      "</div>"
+      "<div id='float-between-nonempties'></div>"
+      "<div id='second-child'>"
+      "  <div id='float-top-align'></div>"
+      "  <div id='empty3'></div>"
+      "  <div id='empty4' style='margin-top: -30px'></div>"
+      "</div>"
+      "<div id='empty5'></div>");
 
-  // DIV1
-  RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
-  div1_style->setHeight(Length(kHeight, Fixed));
-  div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed));
-  NGBlockNode* div1 = new NGBlockNode(div1_style.get());
+  // ** Run LayoutNG algorithm **
+  NGConstraintSpace* space;
+  NGPhysicalBoxFragment* fragment;
+  std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+      document().getElementsByTagName("html")->item(0));
 
-  // DIV2
-  RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
-  div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed));
-  NGBlockNode* div2 = new NGBlockNode(div2_style.get());
+  auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+  // -7 = empty1's margin(-15) + body's margin(8)
+  int body_top_offset = -7;
+  EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+  int body_left_offset = 8;
+  EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+  ASSERT_EQ(3UL, body_fragment->Children().size());
 
-  // Empty DIVs: DIV3, DIV4, DIV6
-  NGBlockNode* div3 = new NGBlockNode(ComputedStyle::create().get());
-  NGBlockNode* div4 = new NGBlockNode(ComputedStyle::create().get());
-  NGBlockNode* div6 = new NGBlockNode(ComputedStyle::create().get());
+  auto* first_child_fragment =
+      toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+  EXPECT_THAT(LayoutUnit(), first_child_fragment->TopOffset());
 
-  // DIV5
-  RefPtr<ComputedStyle> div5_style = ComputedStyle::create();
-  div5_style->setHeight(Length(kHeight, Fixed));
-  div5_style->setMarginTop(Length(kDiv5MarginTop, Fixed));
-  NGBlockNode* div5 = new NGBlockNode(div5_style.get());
+  auto* second_child_fragment =
+      toNGPhysicalBoxFragment(body_fragment->Children()[1]);
+  // 40 = first_child's height(50) - margin's collapsing result(10)
+  int second_child_block_offset = 40;
+  EXPECT_THAT(LayoutUnit(second_child_block_offset),
+              second_child_fragment->TopOffset());
 
-  // DIV7
-  RefPtr<ComputedStyle> div7_style = ComputedStyle::create();
-  div7_style->setMarginTop(Length(kDiv7MarginTop, Fixed));
-  NGBlockNode* div7 = new NGBlockNode(div7_style.get());
+  auto* empty5_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[2]);
+  // 90 = first_child's height(50) + collapsed margins(-10) +
+  // second child's height(50)
+  int empty5_fragment_block_offset = 90;
+  EXPECT_THAT(LayoutUnit(empty5_fragment_block_offset),
+              empty5_fragment->TopOffset());
 
-  div1->SetFirstChild(div2);
-  div2->SetNextSibling(div3);
-  div1->SetNextSibling(div4);
-  div4->SetNextSibling(div5);
-  div5->SetFirstChild(div6);
-  div6->SetNextSibling(div7);
+  ASSERT_EQ(3UL, body_fragment->PositionedFloats().size());
+  auto float_nonempties_fragment =
+      body_fragment->PositionedFloats().at(1)->fragment;
+  // 70 = first_child's height(50) + first child's margin-bottom(20)
+  EXPECT_THAT(LayoutUnit(70), float_nonempties_fragment->TopOffset());
+  EXPECT_THAT(LayoutUnit(0), float_nonempties_fragment->LeftOffset());
 
-  auto* space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
-  NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
+  // ** Verify layout tree **
+  Element* first_child = document().getElementById("first-child");
+  // -7 = body_top_offset
+  EXPECT_EQ(body_top_offset, first_child->offsetTop());
 
-  ASSERT_EQ(frag->Children().size(), 3UL);
+  NGLogicalSize float_empties_exclusion_size = {LayoutUnit(30), LayoutUnit(30)};
+  NGLogicalOffset float_empties_exclusion_offset = {
+      LayoutUnit(body_left_offset), LayoutUnit(body_top_offset)};
+  NGLogicalRect float_empties_exclusion_rect = {float_empties_exclusion_offset,
+                                                float_empties_exclusion_size};
+  NGExclusion float_empties_exclusion = {float_empties_exclusion_rect,
+                                         NGExclusion::kFloatLeft};
 
-  // DIV1
-  const NGPhysicalFragment* child = frag->Children()[0];
-  EXPECT_EQ(kHeight, child->Height());
-  EXPECT_EQ(0, child->TopOffset());
+  NGLogicalSize float_nonempties_exclusion_size = {LayoutUnit(40),
+                                                   LayoutUnit(40)};
+  // 63 = first_child_margin_strut(20) + first-child's height(50) +
+  // body_top_offset(-7)
+  NGLogicalOffset float_nonempties_exclusion_offset = {
+      LayoutUnit(body_left_offset), LayoutUnit(63)};
+  NGLogicalRect float_nonempties_exclusion_rect = {
+      float_nonempties_exclusion_offset, float_nonempties_exclusion_size};
+  NGExclusion float_nonempties_exclusion = {float_nonempties_exclusion_rect,
+                                            NGExclusion::kFloatLeft};
 
-  // DIV5
-  child = frag->Children()[2];
-  EXPECT_EQ(kHeight, child->Height());
-  EXPECT_EQ(kHeight + kExpectedCollapsedMargin, child->TopOffset());
+  NGLogicalSize float_top_align_exclusion_size = {LayoutUnit(50),
+                                                  LayoutUnit(50)};
+  // 63 = float_nonempties_exclusion_offset because of the top edge alignment
+  // rule.
+  // 48 = body's margin + float_nonempties_exclusion_size
+  NGLogicalOffset float_top_align_exclusion_offset = {LayoutUnit(48),
+                                                      LayoutUnit(63)};
+  NGLogicalRect float_top_align_exclusion_rect = {
+      float_top_align_exclusion_offset, float_top_align_exclusion_size};
+  NGExclusion float_top_align_exclusion = {float_top_align_exclusion_rect,
+                                           NGExclusion::kFloatLeft};
+
+  EXPECT_THAT(space->Exclusions()->storage,
+              (ElementsAre(Pointee(float_empties_exclusion),
+                           Pointee(float_nonempties_exclusion),
+                           Pointee(float_top_align_exclusion))));
 }
 
 // Verifies the collapsing margins case for the next pair:
 // - bottom margin of a last in-flow child and bottom margin of its parent if
 //   the parent has 'auto' computed height
-//
-// Test case's HTML representation:
-// <div style="margin-bottom: 20px; height: 50px;">            <!-- DIV1 -->
-//   <div style="margin-bottom: 200px; height: 50px;"/>        <!-- DIV2 -->
-// </div>
-//
-// Expected:
-//   1) Margins are collapsed with the result = std::max(20, 200)
-//      if DIV1.height == auto
-//   2) Margins are NOT collapsed if DIV1.height != auto
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) {
-  const int kHeight = 50;
-  const int kDiv1MarginBottom = 20;
-  const int kDiv2MarginBottom = 200;
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase3) {
+  setBodyInnerHTML(
+      "<style>"
+      " #container {"
+      "   margin-bottom: 20px;"
+      " }"
+      " #child {"
+      "   margin-bottom: 200px;"
+      "   height: 50px;"
+      " }"
+      "</style>"
+      "<div id='container'>"
+      "  <div id='child'></div>"
+      "</div>");
 
-  // DIV1
-  RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
-  div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed));
-  NGBlockNode* div1 = new NGBlockNode(div1_style.get());
+  const NGPhysicalBoxFragment* body_fragment;
+  const NGPhysicalBoxFragment* container_fragment;
+  const NGPhysicalBoxFragment* child_fragment;
+  const NGPhysicalBoxFragment* fragment;
+  auto run_test = [&](const Length& container_height) {
+    Element* container = document().getElementById("container");
+    container->mutableComputedStyle()->setHeight(container_height);
+    std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
+        document().getElementsByTagName("html")->item(0));
+    ASSERT_EQ(1UL, fragment->Children().size());
+    body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+    container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+    ASSERT_EQ(1UL, container_fragment->Children().size());
+    child_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+  };
 
-  // DIV2
-  RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
-  div2_style->setHeight(Length(kHeight, Fixed));
-  div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed));
-  NGBlockNode* div2 = new NGBlockNode(div2_style.get());
+  // height == auto
+  run_test(Length(Auto));
+  // Margins are collapsed with the result 200 = std::max(20, 200)
+  // The fragment size 258 == body's margin 8 + child's height 50 + 200
+  EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(258)), fragment->Size());
+  //  EXPECT_EQ(NGMarginStrut({LayoutUnit(200)}),
+  //            container_fragment->EndMarginStrut());
 
-  div1->SetFirstChild(div2);
-
-  auto* space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
-  NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-
-  // Verify that margins are collapsed.
-  EXPECT_EQ(
-      NGDeprecatedMarginStrut({LayoutUnit(0), LayoutUnit(kDiv2MarginBottom)}),
-      frag->MarginStrut());
-
-  // Verify that margins are NOT collapsed.
-  div1_style->setHeight(Length(kHeight, Fixed));
-  frag = RunBlockLayoutAlgorithm(space, div1);
-  EXPECT_EQ(
-      NGDeprecatedMarginStrut({LayoutUnit(0), LayoutUnit(kDiv1MarginBottom)}),
-      frag->MarginStrut());
+  // height == fixed
+  run_test(Length(50, Fixed));
+  // Margins are not collapsed, so fragment still has margins == 20.
+  // The fragment size 78 == body's margin 8 + child's height 50 + 20
+  //  EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(78)),
+  //            fragment->Size());
+  //  EXPECT_EQ(NGMarginStrut(), container_fragment->EndMarginStrut());
 }
 
 // Verifies that 2 adjoining margins are not collapsed if there is padding or
 // border that separates them.
-//
-// Test case's HTML representation:
-// <div style="margin: 30px 0px; padding: 20px 0px;">    <!-- DIV1 -->
-//   <div style="margin: 200px 0px; height: 50px;"/>     <!-- DIV2 -->
-// </div>
-//
-// Expected:
-// Margins do NOT collapse if there is an interfering padding or border.
-TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) {
-  const int kHeight = 50;
-  const int kDiv1Margin = 30;
-  const int kDiv1Padding = 20;
-  const int kDiv2Margin = 200;
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase4) {
+  setBodyInnerHTML(
+      "<style>"
+      "  #container {"
+      "    margin: 30px 0px;"
+      "    width: 200px;"
+      "  }"
+      "  #child {"
+      "    margin: 200px 0px;"
+      "    height: 50px;"
+      "    background-color: blue;"
+      "  }"
+      "</style>"
+      "<div id='container'>"
+      "  <div id='child'></div>"
+      "</div>");
 
-  // DIV1
-  RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
-  div1_style->setMarginTop(Length(kDiv1Margin, Fixed));
-  div1_style->setMarginBottom(Length(kDiv1Margin, Fixed));
-  div1_style->setPaddingTop(Length(kDiv1Padding, Fixed));
-  div1_style->setPaddingBottom(Length(kDiv1Padding, Fixed));
-  NGBlockNode* div1 = new NGBlockNode(div1_style.get());
+  const NGPhysicalBoxFragment* body_fragment;
+  const NGPhysicalBoxFragment* container_fragment;
+  const NGPhysicalBoxFragment* child_fragment;
+  const NGPhysicalBoxFragment* fragment;
+  auto run_test = [&](const Length& container_padding_top) {
+    Element* container = document().getElementById("container");
+    container->mutableComputedStyle()->setPaddingTop(container_padding_top);
+    std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
+        document().getElementsByTagName("html")->item(0));
+    ASSERT_EQ(1UL, fragment->Children().size());
+    body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+    container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+    ASSERT_EQ(1UL, container_fragment->Children().size());
+    child_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+  };
 
-  // DIV2
-  RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
-  div2_style->setHeight(Length(kHeight, Fixed));
-  div2_style->setMarginTop(Length(kDiv2Margin, Fixed));
-  div2_style->setMarginBottom(Length(kDiv2Margin, Fixed));
-  NGBlockNode* div2 = new NGBlockNode(div2_style.get());
+  // with padding
+  run_test(Length(20, Fixed));
+  // 500 = child's height 50 + 2xmargin 400 + paddint-top 20 +
+  // container's margin 30
+  EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(500)), fragment->Size());
+  // 30 = max(body's margin 8, container margin 30)
+  EXPECT_EQ(LayoutUnit(30), body_fragment->TopOffset());
+  // 220 = container's padding top 20 + child's margin
+  EXPECT_EQ(LayoutUnit(220), child_fragment->TopOffset());
 
-  div1->SetFirstChild(div2);
-
-  auto* space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
-  NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-
-  // Verify that margins do NOT collapse.
-  frag = RunBlockLayoutAlgorithm(space, div1);
-  EXPECT_EQ(NGDeprecatedMarginStrut(
-                {LayoutUnit(kDiv1Margin), LayoutUnit(kDiv1Margin)}),
-            frag->MarginStrut());
-  ASSERT_EQ(frag->Children().size(), 1UL);
-
-  EXPECT_EQ(NGDeprecatedMarginStrut(
-                {LayoutUnit(kDiv2Margin), LayoutUnit(kDiv2Margin)}),
-            static_cast<const NGPhysicalBoxFragment*>(frag->Children()[0].get())
-                ->MarginStrut());
-
-  // Reset padding and verify that margins DO collapse.
-  div1_style->setPaddingTop(Length(0, Fixed));
-  div1_style->setPaddingBottom(Length(0, Fixed));
-  frag = RunBlockLayoutAlgorithm(space, div1);
-  EXPECT_EQ(NGDeprecatedMarginStrut(
-                {LayoutUnit(kDiv2Margin), LayoutUnit(kDiv2Margin)}),
-            frag->MarginStrut());
+  // without padding
+  run_test(Length(0, Fixed));
+  // 450 = 2xmax(body's margin 8, container's margin 30, child's margin 200) +
+  //       child's height 50
+  EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(450)), fragment->Size());
+  // 200 = (body's margin 8, container's margin 30, child's margin 200)
+  EXPECT_EQ(LayoutUnit(200), body_fragment->TopOffset());
+  // 0 = collapsed margins
+  EXPECT_EQ(LayoutUnit(0), child_fragment->TopOffset());
 }
 
 // Verifies that margins of 2 adjoining blocks with different writing modes
@@ -632,175 +768,404 @@
   EXPECT_EQ(LayoutUnit(0), child->TopOffset());
 }
 
-// Verifies that 3 Left/Right float fragments and one regular block fragment
-// are correctly positioned by the algorithm.
-//
-// Test case's HTML representation:
-//  <div id="parent" style="width: 200px; height: 200px;">
-//    <div style="float:left; width: 30px; height: 30px;
-//        margin-top: 10px;"/>   <!-- DIV1 -->
-//    <div style="width: 30px; height: 30px;"/>   <!-- DIV2 -->
-//    <div style="float:right; width: 50px; height: 50px;"/>  <!-- DIV3 -->
-//    <div style="float:left; width: 120px; height: 120px;
-//        margin-left: 30px;"/>  <!-- DIV4 -->
-//  </div>
-//
-// Expected:
-// - Left float(DIV1) is positioned at the left.
-// - Regular block (DIV2) is positioned behind DIV1.
-// - Right float(DIV3) is positioned at the right below DIV2
-// - Left float(DIV4) is positioned at the left below DIV3.
-TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatFragments) {
-  const int kParentLeftPadding = 10;
-  const int kDiv1TopMargin = 10;
-  const int kParentSize = 200;
-  const int kDiv1Size = 30;
-  const int kDiv2Size = 30;
-  const int kDiv3Size = 50;
-  const int kDiv4Size = kParentSize - kDiv3Size;
-  const int kDiv4LeftMargin = kDiv1Size;
+// Verifies that floats can be correctly positioned if they are inside of nested
+// empty blocks.
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFloatInsideEmptyBlocks) {
+  setBodyInnerHTML(
+      "<!DOCTYPE html>"
+      "<style>"
+      "  #container {"
+      "    height: 200px;"
+      "    width: 200px;"
+      "  }"
+      "  #empty1 {"
+      "    margin: 20px;"
+      "    padding: 0 20px;"
+      "  }"
+      "  #empty2 {"
+      "    margin: 15px;"
+      "    padding: 0 15px;"
+      "  }"
+      "  #float {"
+      "    float: left;"
+      "    height: 5px;"
+      "    width: 5px;"
+      "    padding: 10px;"
+      "    margin: 10px;"
+      "    background-color: green;"
+      "  }"
+      "</style>"
+      "<div id='container'>"
+      "  <div id='empty1'>"
+      "    <div id='empty2'>"
+      "      <div id='float'></div>"
+      "    </div>"
+      "  </div>"
+      "</div>");
 
-  style_->setHeight(Length(kParentSize, Fixed));
-  style_->setWidth(Length(kParentSize, Fixed));
-  style_->setPaddingLeft(Length(kParentLeftPadding, Fixed));
+  // ** Run LayoutNG algorithm **
+  NGConstraintSpace* space;
+  NGPhysicalBoxFragment* fragment;
+  std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+      document().getElementsByTagName("html")->item(0));
 
-  // DIV1
-  RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
-  div1_style->setWidth(Length(kDiv1Size, Fixed));
-  div1_style->setHeight(Length(kDiv1Size, Fixed));
-  div1_style->setFloating(EFloat::kLeft);
-  div1_style->setMarginTop(Length(kDiv1TopMargin, Fixed));
-  NGBlockNode* div1 = new NGBlockNode(div1_style.get());
+  auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+  // 20 = std::max(empty1's margin, empty2's margin, body's margin)
+  int body_top_offset = 20;
+  EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset());
+  ASSERT_EQ(1UL, body_fragment->Children().size());
+  auto* container_fragment =
+      toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+  ASSERT_EQ(1UL, container_fragment->Children().size());
 
-  // DIV2
-  RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
-  div2_style->setWidth(Length(kDiv2Size, Fixed));
-  div2_style->setHeight(Length(kDiv2Size, Fixed));
-  NGBlockNode* div2 = new NGBlockNode(div2_style.get());
+  auto* empty1_fragment =
+      toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+  // 0, vertical margins got collapsed
+  EXPECT_THAT(LayoutUnit(), empty1_fragment->TopOffset());
+  // 20 empty1's margin
+  int empty1_inline_offset = 20;
+  EXPECT_THAT(LayoutUnit(empty1_inline_offset), empty1_fragment->LeftOffset());
+  ASSERT_EQ(empty1_fragment->Children().size(), 1UL);
 
-  // DIV3
-  RefPtr<ComputedStyle> div3_style = ComputedStyle::create();
-  div3_style->setWidth(Length(kDiv3Size, Fixed));
-  div3_style->setHeight(Length(kDiv3Size, Fixed));
-  div3_style->setFloating(EFloat::kRight);
-  NGBlockNode* div3 = new NGBlockNode(div3_style.get());
+  auto* empty2_fragment =
+      toNGPhysicalBoxFragment(empty1_fragment->Children()[0]);
+  // 0, vertical margins got collapsed
+  EXPECT_THAT(LayoutUnit(), empty2_fragment->TopOffset());
+  // 35 = empty1's padding(20) + empty2's padding(15)
+  int empty2_inline_offset = 35;
+  EXPECT_THAT(LayoutUnit(empty2_inline_offset), empty2_fragment->LeftOffset());
 
-  // DIV4
-  RefPtr<ComputedStyle> div4_style = ComputedStyle::create();
-  div4_style->setWidth(Length(kDiv4Size, Fixed));
-  div4_style->setHeight(Length(kDiv4Size, Fixed));
-  div4_style->setMarginLeft(Length(kDiv4LeftMargin, Fixed));
-  div4_style->setFloating(EFloat::kLeft);
-  NGBlockNode* div4 = new NGBlockNode(div4_style.get());
+  ASSERT_EQ(1UL, body_fragment->PositionedFloats().size());
+  auto float_fragment = body_fragment->PositionedFloats().at(0)->fragment;
+  // 10 = float's padding
+  EXPECT_THAT(LayoutUnit(10), float_fragment->TopOffset());
+  // 25 = empty2's padding(15) + float's padding(10)
+  int float_inline_offset = 25;
+  EXPECT_THAT(float_fragment->LeftOffset(), LayoutUnit(float_inline_offset));
 
-  div1->SetNextSibling(div2);
-  div2->SetNextSibling(div3);
-  div3->SetNextSibling(div4);
+  // ** Verify layout tree **
+  Element* left_float = document().getElementById("float");
+  // 88 = body's margin(8) +
+  // empty1's padding and margin + empty2's padding and margins + float's
+  // padding
+  EXPECT_THAT(left_float->offsetLeft(), 88);
+  // 30 = body_top_offset(collapsed margins result) + float's padding
+  EXPECT_THAT(body_top_offset + 10, left_float->offsetTop());
 
-  auto* space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
-  NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-  ASSERT_EQ(frag->Children().size(), 4UL);
+  // ** Legacy Floating objects **
+  Element* body = document().getElementsByTagName("body")->item(0);
+  auto& floating_objects =
+      const_cast<FloatingObjects*>(
+          toLayoutBlockFlow(body->layoutObject())->floatingObjects())
+          ->mutableSet();
+  ASSERT_EQ(1UL, floating_objects.size());
+  auto floating_object = floating_objects.takeFirst();
+  ASSERT_TRUE(floating_object->isPlaced());
+  // 80 = float_inline_offset(25) + accumulative offset of empty blocks(35 + 20)
+  EXPECT_THAT(LayoutUnit(80), floating_object->x());
+  // 10 = float's padding
+  EXPECT_THAT(LayoutUnit(10), floating_object->y());
+}
 
-  // DIV1
-  const NGPhysicalFragment* child1 = frag->Children()[0];
-  EXPECT_EQ(kDiv1TopMargin, child1->TopOffset());
-  EXPECT_EQ(kParentLeftPadding, child1->LeftOffset());
+// Verifies that left/right floating and regular blocks can be positioned
+// correctly by the algorithm.
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFloatFragments) {
+  setBodyInnerHTML(
+      "<style>"
+      "  #container {"
+      "    height: 200px;"
+      "    width: 200px;"
+      "  }"
+      "  #left-float {"
+      "    background-color: red;"
+      "    float:left;"
+      "    height: 30px;"
+      "    width: 30px;"
+      "  }"
+      "  #left-wide-float {"
+      "    background-color: greenyellow;"
+      "    float:left;"
+      "    height: 30px;"
+      "    width: 180px;"
+      "  }"
+      "  #regular {"
+      "    width: 40px;"
+      "    height: 40px;"
+      "    background-color: green;"
+      "  }"
+      "  #right-float {"
+      "    background-color: cyan;"
+      "    float:right;"
+      "    width: 50px;"
+      "    height: 50px;"
+      "  }"
+      "  #left-float-with-margin {"
+      "    background-color: black;"
+      "    float:left;"
+      "    height: 120px;"
+      "    margin: 10px;"
+      "    width: 120px;"
+      "  }"
+      "</style>"
+      "<div id='container'>"
+      "  <div id='left-float'></div>"
+      "  <div id='left-wide-float'></div>"
+      "  <div id='regular'></div>"
+      "  <div id='right-float'></div>"
+      "  <div id='left-float-with-margin'></div>"
+      "</div>");
 
-  // DIV2
-  const NGPhysicalFragment* child2 = frag->Children()[1];
-  EXPECT_EQ(0, child2->TopOffset());
-  EXPECT_EQ(kParentLeftPadding, child2->LeftOffset());
+  // ** Run LayoutNG algorithm **
+  NGConstraintSpace* space;
+  NGPhysicalBoxFragment* fragment;
+  std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement(
+      document().getElementsByTagName("html")->item(0));
 
-  // DIV3
-  const NGPhysicalFragment* child3 = frag->Children()[2];
-  EXPECT_EQ(kDiv2Size, child3->TopOffset());
-  EXPECT_EQ(kParentLeftPadding + kParentSize - kDiv3Size, child3->LeftOffset());
+  // ** Verify LayoutNG fragments and the list of positioned floats **
+  EXPECT_THAT(LayoutUnit(), fragment->TopOffset());
+  ASSERT_EQ(1UL, fragment->Children().size());
+  auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+  EXPECT_THAT(LayoutUnit(8), body_fragment->TopOffset());
+  auto* container_fragment =
+      toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+  ASSERT_EQ(1UL, container_fragment->Children().size());
+  ASSERT_EQ(4UL, container_fragment->PositionedFloats().size());
 
-  // DIV4
-  const NGPhysicalFragment* child4 = frag->Children()[3];
-  EXPECT_EQ(kDiv2Size + kDiv3Size, child4->TopOffset());
-  EXPECT_EQ(kParentLeftPadding + kDiv4LeftMargin, child4->LeftOffset());
+  // ** Verify layout tree **
+  Element* left_float = document().getElementById("left-float");
+  // 8 = body's margin-top
+  int left_float_block_offset = 8;
+  EXPECT_EQ(left_float_block_offset, left_float->offsetTop());
+  auto left_float_fragment =
+      container_fragment->PositionedFloats().at(0)->fragment;
+  EXPECT_THAT(LayoutUnit(), left_float_fragment->TopOffset());
+
+  Element* left_wide_float = document().getElementById("left-wide-float");
+  // left-wide-float is positioned right below left-float as it's too wide.
+  // 38 = left_float_block_offset +
+  //      left-float's height 30
+  int left_wide_float_block_offset = 38;
+  EXPECT_EQ(left_wide_float_block_offset, left_wide_float->offsetTop());
+  auto left_wide_float_fragment =
+      container_fragment->PositionedFloats().at(1)->fragment;
+  // 30 = left-float's height.
+  EXPECT_THAT(LayoutUnit(30), left_wide_float_fragment->TopOffset());
+
+  Element* regular = document().getElementById("regular");
+  // regular_block_offset = body's margin-top 8
+  int regular_block_offset = 8;
+  EXPECT_EQ(regular_block_offset, regular->offsetTop());
+  auto* regular_block_fragment =
+      toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+  EXPECT_THAT(LayoutUnit(), regular_block_fragment->TopOffset());
+
+  Element* right_float = document().getElementById("right-float");
+  // 158 = body's margin-left 8 + container's width 200 - right_float's width 50
+  int right_float_inline_offset = 158;
+  // it's positioned right after our left_wide_float
+  // 68 = left_wide_float_block_offset 38 + left-wide-float's height 30
+  int right_float_block_offset = left_wide_float_block_offset + 30;
+  EXPECT_EQ(right_float_inline_offset, right_float->offsetLeft());
+  EXPECT_EQ(right_float_block_offset, right_float->offsetTop());
+  auto right_float_fragment =
+      container_fragment->PositionedFloats().at(2)->fragment;
+  // 60 = right_float_block_offset(68) - body's margin(8)
+  EXPECT_THAT(LayoutUnit(right_float_block_offset - 8),
+              right_float_fragment->TopOffset());
+  // 150 = right_float_inline_offset(158) - body's margin(8)
+  EXPECT_THAT(LayoutUnit(right_float_inline_offset - 8),
+              right_float_fragment->LeftOffset());
+
+  Element* left_float_with_margin =
+      document().getElementById("left-float-with-margin");
+  // 18 = body's margin(8) + left-float-with-margin's margin(10)
+  int left_float_with_margin_inline_offset = 18;
+  EXPECT_EQ(left_float_with_margin_inline_offset,
+            left_float_with_margin->offsetLeft());
+  // 78 = left_wide_float_block_offset 38 + left-wide-float's height 30 +
+  //      left-float-with-margin's margin(10)
+  int left_float_with_margin_block_offset = 78;
+  EXPECT_EQ(left_float_with_margin_block_offset,
+            left_float_with_margin->offsetTop());
+  auto left_float_with_margin_fragment =
+      container_fragment->PositionedFloats().at(3)->fragment;
+  // 70 = left_float_with_margin_block_offset(78) - body's margin(8)
+  EXPECT_THAT(LayoutUnit(left_float_with_margin_block_offset - 8),
+              left_float_with_margin_fragment->TopOffset());
+  // 10 = left_float_with_margin_inline_offset(18) - body's margin(8)
+  EXPECT_THAT(LayoutUnit(left_float_with_margin_inline_offset - 8),
+              left_float_with_margin_fragment->LeftOffset());
+
+  // ** Verify exclusions **
+  NGLogicalSize left_float_exclusion_size = {LayoutUnit(30), LayoutUnit(30)};
+  // this should be equal to body's margin(8)
+  NGLogicalOffset left_float_exclusion_offset = {LayoutUnit(8), LayoutUnit(8)};
+  NGLogicalRect left_float_exclusion_rect = {left_float_exclusion_offset,
+                                             left_float_exclusion_size};
+  NGExclusion left_float_exclusion = {left_float_exclusion_rect,
+                                      NGExclusion::kFloatLeft};
+
+  NGLogicalSize left_wide_exclusion_size = {LayoutUnit(180), LayoutUnit(30)};
+  NGLogicalOffset left_wide_exclusion_offset = {
+      LayoutUnit(8), LayoutUnit(left_wide_float_block_offset)};
+  NGLogicalRect left_wide_exclusion_rect = {left_wide_exclusion_offset,
+                                            left_wide_exclusion_size};
+  NGExclusion left_wide_exclusion = {left_wide_exclusion_rect,
+                                     NGExclusion::kFloatLeft};
+
+  NGLogicalSize right_float_exclusion_size = {LayoutUnit(50), LayoutUnit(50)};
+  NGLogicalOffset right_float_exclusion_offset = {
+      LayoutUnit(right_float_inline_offset),
+      LayoutUnit(right_float_block_offset)};
+  NGLogicalRect right_float_exclusion_rect = {right_float_exclusion_offset,
+                                              right_float_exclusion_size};
+  NGExclusion right_float_exclusion = {right_float_exclusion_rect,
+                                       NGExclusion::kFloatRight};
+
+  // left-float-with-margin's size(120) + margin(2x10)
+  NGLogicalSize left_float_with_margin_exclusion_size = {LayoutUnit(140),
+                                                         LayoutUnit(140)};
+  // Exclusion starts from the right_float_block_offset position.
+  NGLogicalOffset left_float_with_margin_exclusion_offset = {
+      LayoutUnit(8), LayoutUnit(right_float_block_offset)};
+  NGLogicalRect left_float_with_margin_exclusion_rect = {
+      left_float_with_margin_exclusion_offset,
+      left_float_with_margin_exclusion_size};
+  NGExclusion left_float_with_margin_exclusion = {
+      left_float_with_margin_exclusion_rect, NGExclusion::kFloatLeft};
+
+  EXPECT_THAT(
+      space->Exclusions()->storage,
+      (ElementsAre(Pointee(left_float_exclusion), Pointee(left_wide_exclusion),
+                   Pointee(right_float_exclusion),
+                   Pointee(left_float_with_margin_exclusion))));
 }
 
 // Verifies that NG block layout algorithm respects "clear" CSS property.
-//
-// Test case's HTML representation:
-//  <div id="parent" style="width: 200px; height: 200px;">
-//    <div style="float: left; width: 30px; height: 30px;"/>   <!-- DIV1 -->
-//    <div style="float: right; width: 40px; height: 40px;
-//        clear: left;"/>  <!-- DIV2 -->
-//    <div style="clear: ...; width: 50px; height: 50px;"/>    <!-- DIV3 -->
-//  </div>
-//
-// Expected:
-// - DIV2 is positioned below DIV1 because it has clear: left;
-// - DIV3 is positioned below DIV1 if clear: left;
-// - DIV3 is positioned below DIV2 if clear: right;
-// - DIV3 is positioned below DIV2 if clear: both;
-TEST_F(NGBlockLayoutAlgorithmTest, PositionFragmentsWithClear) {
-  const int kParentSize = 200;
-  const int kDiv1Size = 30;
-  const int kDiv2Size = 40;
-  const int kDiv3Size = 50;
+// TODO(glebl): Enable with new the float/margins collapsing algorithm.
+TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFragmentsWithClear) {
+  setBodyInnerHTML(
+      "<style>"
+      "  #container {"
+      "    height: 200px;"
+      "    width: 200px;"
+      "  }"
+      "  #float-left {"
+      "    background-color: red;"
+      "    float: left;"
+      "    height: 30px;"
+      "    width: 30px;"
+      "  }"
+      "  #float-right {"
+      "    background-color: blue;"
+      "    float: right;"
+      "    height: 170px;"
+      "    width: 40px;"
+      "  }"
+      "  #clearance {"
+      "    background-color: yellow;"
+      "    height: 60px;"
+      "    width: 60px;"
+      "    margin: 20px;"
+      "  }"
+      "  #block {"
+      "    margin: 40px;"
+      "    background-color: black;"
+      "    height: 60px;"
+      "    width: 60px;"
+      "  }"
+      "  #adjoining-clearance {"
+      "    background-color: green;"
+      "    clear: left;"
+      "    height: 20px;"
+      "    width: 20px;"
+      "    margin: 30px;"
+      "  }"
+      "</style>"
+      "<div id='container'>"
+      "  <div id='float-left'></div>"
+      "  <div id='float-right'></div>"
+      "  <div id='clearance'></div>"
+      "  <div id='block'></div>"
+      "  <div id='adjoining-clearance'></div>"
+      "</div>");
 
-  style_->setHeight(Length(kParentSize, Fixed));
-  style_->setWidth(Length(kParentSize, Fixed));
+  const NGPhysicalBoxFragment* clerance_fragment;
+  const NGPhysicalBoxFragment* body_fragment;
+  const NGPhysicalBoxFragment* container_fragment;
+  const NGPhysicalBoxFragment* block_fragment;
+  const NGPhysicalBoxFragment* adjoining_clearance_fragment;
+  auto run_with_clearance = [&](EClear clear_value) {
+    NGPhysicalBoxFragment* fragment;
+    Element* el_with_clear = document().getElementById("clearance");
+    el_with_clear->mutableComputedStyle()->setClear(clear_value);
+    std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement(
+        document().getElementsByTagName("html")->item(0));
+    ASSERT_EQ(1UL, fragment->Children().size());
+    body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]);
+    container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]);
+    ASSERT_EQ(3UL, container_fragment->Children().size());
+    clerance_fragment =
+        toNGPhysicalBoxFragment(container_fragment->Children()[0]);
+    block_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[1]);
+    adjoining_clearance_fragment =
+        toNGPhysicalBoxFragment(container_fragment->Children()[2]);
+  };
 
-  // DIV1
-  RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
-  div1_style->setWidth(Length(kDiv1Size, Fixed));
-  div1_style->setHeight(Length(kDiv1Size, Fixed));
-  div1_style->setFloating(EFloat::kLeft);
-  NGBlockNode* div1 = new NGBlockNode(div1_style.get());
+  // clear: none
+  run_with_clearance(EClear::ClearNone);
+  // 20 = std::max(body's margin 8, clearance's margins 20)
+  EXPECT_EQ(LayoutUnit(20), body_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+  // 0 = collapsed margins
+  EXPECT_EQ(LayoutUnit(0), clerance_fragment->TopOffset());
+  // 100 = clearance's height 60 +
+  //       std::max(clearance's margins 20, block's margins 40)
+  EXPECT_EQ(LayoutUnit(100), block_fragment->TopOffset());
+  // 200 = 100 + block's height 60 + max(adjoining_clearance's margins 30,
+  //                                     block's margins 40)
+  EXPECT_EQ(LayoutUnit(200), adjoining_clearance_fragment->TopOffset());
 
-  // DIV2
-  RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
-  div2_style->setWidth(Length(kDiv2Size, Fixed));
-  div2_style->setHeight(Length(kDiv2Size, Fixed));
-  div2_style->setClear(EClear::ClearLeft);
-  div2_style->setFloating(EFloat::kRight);
-  NGBlockNode* div2 = new NGBlockNode(div2_style.get());
+  // clear: right
+  run_with_clearance(EClear::ClearRight);
+  // 8 = body's margin. This doesn't collapse its margins with 'clearance' block
+  // as it's not an adjoining block to body.
+  EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+  // 170 = float-right's height
+  EXPECT_EQ(LayoutUnit(170), clerance_fragment->TopOffset());
+  // 270 = float-right's height + clearance's height 60 +
+  //       max(clearance's margin 20, block margin 40)
+  EXPECT_EQ(LayoutUnit(270), block_fragment->TopOffset());
+  // 370 = block's offset 270 + block's height 60 +
+  //       std::max(block's margin 40, adjoining_clearance's margin 30)
+  EXPECT_EQ(LayoutUnit(370), adjoining_clearance_fragment->TopOffset());
 
-  // DIV3
-  RefPtr<ComputedStyle> div3_style = ComputedStyle::create();
-  div3_style->setWidth(Length(kDiv3Size, Fixed));
-  div3_style->setHeight(Length(kDiv3Size, Fixed));
-  NGBlockNode* div3 = new NGBlockNode(div3_style.get());
+  // clear: left
+  run_with_clearance(EClear::ClearLeft);
+  // 8 = body's margin. This doesn't collapse its margins with 'clearance' block
+  // as it's not an adjoining block to body.
+  EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+  // 30 = float_left's height
+  EXPECT_EQ(LayoutUnit(30), clerance_fragment->TopOffset());
+  // 130 = float_left's height + clearance's height 60 +
+  //       max(clearance's margin 20, block margin 40)
+  EXPECT_EQ(LayoutUnit(130), block_fragment->TopOffset());
+  // 230 = block's offset 130 + block's height 60 +
+  //       std::max(block's margin 40, adjoining_clearance's margin 30)
+  EXPECT_EQ(LayoutUnit(230), adjoining_clearance_fragment->TopOffset());
 
-  div1->SetNextSibling(div2);
-  div2->SetNextSibling(div3);
-
-  // clear: left;
-  div3_style->setClear(EClear::ClearLeft);
-  auto* space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
-  NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1);
-  const NGPhysicalFragment* child3 = frag->Children()[2];
-  EXPECT_EQ(kDiv1Size, child3->TopOffset());
-
-  // clear: right;
-  div3_style->setClear(EClear::ClearRight);
-  space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
-  frag = RunBlockLayoutAlgorithm(space, div1);
-  child3 = frag->Children()[2];
-  EXPECT_EQ(kDiv1Size + kDiv2Size, child3->TopOffset());
-
-  // clear: both;
-  div3_style->setClear(EClear::ClearBoth);
-  space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
-  frag = RunBlockLayoutAlgorithm(space, div1);
-  space = ConstructConstraintSpace(
-      kHorizontalTopBottom, TextDirection::kLtr,
-      NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize)));
-  child3 = frag->Children()[2];
-  EXPECT_EQ(kDiv1Size + kDiv2Size, child3->TopOffset());
+  // clear: both
+  // same as clear: right
+  run_with_clearance(EClear::ClearBoth);
+  EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(170), clerance_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(270), block_fragment->TopOffset());
+  EXPECT_EQ(LayoutUnit(370), adjoining_clearance_fragment->TopOffset());
 }
 
 // Verifies that we compute the right min and max-content size.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index 09a93eb8..882d9c3 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -21,6 +21,45 @@
 
 namespace blink {
 
+namespace {
+
+// Copies data back to the legacy layout tree for a given child fragment.
+void FragmentPositionUpdated(const NGPhysicalBoxFragment& box_fragment) {
+  LayoutBox* layout_box = toLayoutBox(box_fragment.GetLayoutObject());
+  if (!layout_box)
+    return;
+
+  DCHECK(layout_box->parent()) << "Should be called on children only.";
+
+  layout_box->setX(box_fragment.LeftOffset());
+  layout_box->setY(box_fragment.TopOffset());
+}
+
+// Similar to FragmentPositionUpdated but for floats.
+// - Updates layout object's geometric information.
+// - Creates legacy FloatingObject and attached it to the provided parent.
+void FloatingObjectPositionedUpdated(NGFloatingObject& floating_object,
+                                     LayoutBox* parent) {
+  NGPhysicalBoxFragment* box_fragment =
+      toNGPhysicalBoxFragment(floating_object.fragment);
+  FragmentPositionUpdated(*box_fragment);
+
+  LayoutBox* layout_box = toLayoutBox(box_fragment->GetLayoutObject());
+  DCHECK(layout_box->isFloating());
+
+  if (parent && parent->isLayoutBlockFlow()) {
+    FloatingObject* floating_object =
+        toLayoutBlockFlow(parent)->insertFloatingObject(*layout_box);
+    // TODO(glebl): Fix floating_object's inline offset if it's attached to
+    // parent != layout_box_->parent
+    floating_object->setX(box_fragment->LeftOffset());
+    floating_object->setY(box_fragment->TopOffset());
+    floating_object->setIsPlaced(true);
+  }
+}
+
+}  // namespace
+
 NGBlockNode::NGBlockNode(LayoutObject* layout_object)
     : NGLayoutInputNode(NGLayoutInputNodeType::kLegacyBlock),
       layout_box_(toLayoutBox(layout_object)) {
@@ -88,8 +127,8 @@
           .ToConstraintSpace();
 
   // TODO(cbiesinger): For orthogonal children, we need to always synthesize.
-  NGBlockLayoutAlgorithm minmax_algorithm(Style(), toNGBlockNode(FirstChild()),
-                                          constraint_space);
+  NGBlockLayoutAlgorithm minmax_algorithm(
+      layout_box_, Style(), toNGBlockNode(FirstChild()), constraint_space);
   if (minmax_algorithm.ComputeMinAndMaxContentSizes(sizes))
     return true;
 
@@ -142,6 +181,10 @@
   return next_sibling_;
 }
 
+LayoutObject* NGBlockNode::GetLayoutObject() {
+  return layout_box_;
+}
+
 NGLayoutInputNode* NGBlockNode::FirstChild() {
   if (!first_child_) {
     LayoutObject* child = layout_box_ ? layout_box_->slowFirstChild() : nullptr;
@@ -175,29 +218,6 @@
   NGLayoutInputNode::trace(visitor);
 }
 
-void NGBlockNode::PositionUpdated() {
-  if (!layout_box_)
-    return;
-  DCHECK(layout_box_->parent()) << "Should be called on children only.";
-
-  layout_box_->setX(fragment_->LeftOffset());
-  layout_box_->setY(fragment_->TopOffset());
-}
-
-void NGBlockNode::FloatPositionUpdated(LayoutObject* parent) {
-  PositionUpdated();
-
-  if (layout_box_->isFloating() && parent && parent->isLayoutBlockFlow()) {
-    FloatingObject* floating_object =
-        toLayoutBlockFlow(parent)->insertFloatingObject(*layout_box_);
-    // TODO(glebl): Fix floating_object's inline offset if it's attached to
-    // parent != layout_box_->parent
-    floating_object->setX(fragment_->LeftOffset());
-    floating_object->setY(fragment_->TopOffset());
-    floating_object->setIsPlaced(true);
-  }
-}
-
 bool NGBlockNode::CanUseNewLayout() {
   if (!layout_box_)
     return true;
@@ -255,13 +275,12 @@
     // Ensure the position of the children are copied across to the
     // LayoutObject tree.
   } else {
-    for (NGBlockNode* box = toNGBlockNode(FirstChild()); box;
-         box = box->NextSibling()) {
-      if (box->fragment_ && box->fragment_->IsPlaced())
-        box->PositionUpdated();
+    for (const auto& child_fragment : fragment_->Children()) {
+      if (child_fragment->IsPlaced())
+        FragmentPositionUpdated(toNGPhysicalBoxFragment(*child_fragment));
 
-      for (const auto& floating_object : box->fragment_->PositionedFloats()) {
-        floating_object->node->FloatPositionUpdated(box->layout_box_);
+      for (const auto& floating_object : child_fragment->PositionedFloats()) {
+        FloatingObjectPositionedUpdated(*floating_object, layout_box_);
       }
     }
   }
@@ -301,7 +320,7 @@
   LayoutRect overflow = layout_box_->layoutOverflowRect();
   // TODO(layout-ng): This does not handle writing modes correctly (for
   // overflow)
-  NGFragmentBuilder builder(NGPhysicalFragment::kFragmentBox);
+  NGFragmentBuilder builder(NGPhysicalFragment::kFragmentBox, layout_box_);
   builder.SetInlineSize(layout_box_->logicalWidth())
       .SetBlockSize(layout_box_->logicalHeight())
       .SetDirection(layout_box_->styleRef().direction())
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.h b/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
index dbf5213..088fdaf 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
@@ -34,8 +34,8 @@
   ~NGBlockNode() override;
 
   NGPhysicalFragment* Layout(NGConstraintSpace* constraint_space) override;
-
   NGBlockNode* NextSibling() override;
+  LayoutObject* GetLayoutObject() override;
 
   // Computes the value of min-content and max-content for this box.
   // The return value has the same meaning as for Layout.
@@ -75,17 +75,7 @@
 
   // Save static position for legacy AbsPos layout.
   void SaveStaticOffsetForLegacy(const NGLogicalOffset&);
-
-  // This is necessary for interop between old and new trees -- after our parent
-  // positions us, it calls this function so we can store the position on the
-  // underlying LayoutBox.
-  void PositionUpdated();
-
  private:
-  // Similar to PositionUpdated but for floats.
-  // - Updates layout object's geometric information.
-  // - Creates legacy FloatingObject and attached it to the provided parent.
-  void FloatPositionUpdated(LayoutObject* parent);
 
   bool CanUseNewLayout();
   bool HasInlineChildren();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
index 8491651..45eaca4 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -12,10 +12,13 @@
 
 namespace blink {
 
-NGFragmentBuilder::NGFragmentBuilder(NGPhysicalFragment::NGFragmentType type)
+// TODO(ikilpatrick): Make writing mode and direction be in the constructor.
+NGFragmentBuilder::NGFragmentBuilder(NGPhysicalFragment::NGFragmentType type,
+                                     LayoutObject* layout_object)
     : type_(type),
       writing_mode_(kHorizontalTopBottom),
-      direction_(TextDirection::kLtr) {}
+      direction_(TextDirection::kLtr),
+      layout_object_(layout_object) {}
 
 NGFragmentBuilder& NGFragmentBuilder::SetWritingMode(
     NGWritingMode writing_mode) {
@@ -156,7 +159,7 @@
   break_token_ = nullptr;
 
   NGPhysicalSize physical_size = size_.ConvertToPhysical(writing_mode_);
-  HeapVector<Member<const NGPhysicalFragment>> children;
+  HeapVector<Member<NGPhysicalFragment>> children;
   children.reserveCapacity(children_.size());
 
   for (size_t i = 0; i < children_.size(); ++i) {
@@ -178,8 +181,8 @@
   }
 
   return new NGPhysicalBoxFragment(
-      physical_size, overflow_.ConvertToPhysical(writing_mode_), children,
-      out_of_flow_descendants_, out_of_flow_positions_, margin_strut_,
+      layout_object_, physical_size, overflow_.ConvertToPhysical(writing_mode_),
+      children, out_of_flow_descendants_, out_of_flow_positions_, margin_strut_,
       unpositioned_floats_, positioned_floats_, break_token);
 }
 
@@ -194,7 +197,8 @@
   HeapVector<Member<NGFloatingObject>> empty_positioned_floats;
 
   return new NGPhysicalTextFragment(
-      node, start_index, end_index, size_.ConvertToPhysical(writing_mode_),
+      layout_object_, node, start_index, end_index,
+      size_.ConvertToPhysical(writing_mode_),
       overflow_.ConvertToPhysical(writing_mode_), out_of_flow_descendants_,
       out_of_flow_positions_, empty_unpositioned_floats,
       empty_positioned_floats);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
index 29e39de..d1a7301 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
@@ -20,7 +20,7 @@
 class CORE_EXPORT NGFragmentBuilder final
     : public GarbageCollectedFinalized<NGFragmentBuilder> {
  public:
-  NGFragmentBuilder(NGPhysicalFragment::NGFragmentType);
+  NGFragmentBuilder(NGPhysicalFragment::NGFragmentType, LayoutObject*);
 
   using WeakBoxList = HeapLinkedHashSet<WeakMember<NGBlockNode>>;
 
@@ -137,6 +137,8 @@
   NGWritingMode writing_mode_;
   TextDirection direction_;
 
+  LayoutObject* layout_object_;
+
   NGLogicalSize size_;
   NGLogicalSize overflow_;
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc
index bc36849..a6cd530 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc
@@ -18,6 +18,7 @@
 namespace blink {
 
 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm(
+    LayoutObject* layout_object,
     PassRefPtr<const ComputedStyle> style,
     NGInlineNode* first_child,
     NGConstraintSpace* constraint_space,
@@ -26,14 +27,15 @@
       style_(style),
       first_child_(first_child),
       constraint_space_(constraint_space),
-      break_token_(break_token) {
+      break_token_(break_token),
+      builder_(new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox,
+                                     layout_object)) {
   DCHECK(style_);
 }
 
 NGPhysicalFragment* NGInlineLayoutAlgorithm::Layout() {
   // TODO(kojii): Implement sizing and child constraint spaces. Share common
   // logic with NGBlockLayoutAlgorithm using composition.
-  builder_ = new NGFragmentBuilder(NGPhysicalFragment::kFragmentBox);
   builder_->SetWritingMode(constraint_space_->WritingMode());
   builder_->SetDirection(constraint_space_->Direction());
   NGInlineNode* current_child = first_child_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.h
index 760531e..e37ba0d 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.h
@@ -12,6 +12,7 @@
 namespace blink {
 
 class ComputedStyle;
+class LayoutObject;
 class NGBreakToken;
 class NGConstraintSpace;
 class NGFragmentBuilder;
@@ -26,12 +27,14 @@
 class CORE_EXPORT NGInlineLayoutAlgorithm : public NGLayoutAlgorithm {
  public:
   // Default constructor.
+  // @param layout_object The LayoutObject associated with this anonymous block.
   // @param style Style reference of the block that is being laid out.
   // @param first_child Our first child; the algorithm will use its NextSibling
   //                    method to access all the children.
   // @param space The constraint space which the algorithm should generate a
   //              fragment within.
-  NGInlineLayoutAlgorithm(PassRefPtr<const ComputedStyle>,
+  NGInlineLayoutAlgorithm(LayoutObject* layout_object,
+                          PassRefPtr<const ComputedStyle> style,
                           NGInlineNode* first_child,
                           NGConstraintSpace* space,
                           NGBreakToken* break_token = nullptr);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
index 76940e5f..34f3f3f 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
@@ -25,7 +25,7 @@
 namespace blink {
 
 NGInlineNode::NGInlineNode(LayoutObject* start_inline,
-                           ComputedStyle* block_style)
+                           const ComputedStyle* block_style)
     : NGLayoutInputNode(NGLayoutInputNodeType::kLegacyInline),
       start_inline_(start_inline),
       last_inline_(nullptr),
@@ -246,6 +246,10 @@
   return next_sibling_;
 }
 
+LayoutObject* NGInlineNode::GetLayoutObject() {
+  return GetLayoutBlockFlow();
+}
+
 // Find the first LayoutBlockFlow in the ancestor chain of |start_inilne_|.
 LayoutBlockFlow* NGInlineNode::GetLayoutBlockFlow() const {
   for (LayoutObject* layout_object = start_inline_->parent(); layout_object;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h
index 1aaaec5..e01d502 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h
@@ -31,12 +31,13 @@
 // Represents an inline node to be laid out.
 class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
  public:
-  NGInlineNode(LayoutObject* start_inline, ComputedStyle* block_style);
+  NGInlineNode(LayoutObject* start_inline, const ComputedStyle* block_style);
   ~NGInlineNode() override;
 
   NGPhysicalFragment* Layout(NGConstraintSpace*) override;
   void LayoutInline(NGConstraintSpace*, NGLineBuilder*);
   NGInlineNode* NextSibling() override;
+  LayoutObject* GetLayoutObject() override;
 
   // Prepare inline and text content for layout. Must be called before
   // calling the Layout method.
@@ -67,7 +68,7 @@
 
   LayoutObject* start_inline_;
   LayoutObject* last_inline_;
-  RefPtr<ComputedStyle> block_style_;
+  RefPtr<const ComputedStyle> block_style_;
 
   Member<NGInlineNode> next_sibling_;
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc
index 7f51d7b..8a797d9 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc
@@ -24,6 +24,8 @@
   }
   using NGInlineNode::NGInlineNode;
 
+  LayoutObject* GetLayoutObject() override { return nullptr; }
+
   String& Text() { return text_content_; }
   Vector<NGLayoutInlineItem>& Items() { return items_; }
 
@@ -71,7 +73,8 @@
         new NGTextLayoutAlgorithm(node, constraint_space);
     algorithm->LayoutInline(&line_builder);
 
-    NGFragmentBuilder fragment_builder(NGPhysicalFragment::kFragmentBox);
+    NGFragmentBuilder fragment_builder(NGPhysicalFragment::kFragmentBox,
+                                       /* layout_object */ nullptr);
     line_builder.CreateFragments(&fragment_builder);
     NGPhysicalBoxFragment* fragment = fragment_builder.ToBoxFragment();
     for (const NGPhysicalFragment* child : fragment->Children()) {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.cc
index 1050b23..89996db 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.cc
@@ -26,14 +26,17 @@
   if (!block->CanUseNewLayout())
     return new NGLegacyBlockLayoutAlgorithm(block, constraint_space);
   const ComputedStyle* style = block->Style();
+  LayoutObject* layout_object = input_node->GetLayoutObject();
   if (block->HasInlineChildren()) {
     NGInlineNode* child = toNGInlineNode(block->FirstChild());
-    return new NGInlineLayoutAlgorithm(style, child, constraint_space);
+    return new NGInlineLayoutAlgorithm(layout_object, style, child,
+                                       constraint_space);
   }
   NGBlockNode* child = toNGBlockNode(block->FirstChild());
   // TODO(layout-ng): The break token should be passed as an argument to this
   // method instead of getting it from the NGBlockNode
   NGBreakToken* token = block->CurrentBreakToken();
-  return new NGBlockLayoutAlgorithm(style, child, constraint_space, token);
+  return new NGBlockLayoutAlgorithm(layout_object, style, child,
+                                    constraint_space, token);
 }
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h
index 91022a0..6e502df 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_input_node.h
@@ -10,6 +10,7 @@
 
 namespace blink {
 
+class LayoutObject;
 class NGConstraintSpace;
 class NGPhysicalFragment;
 class NGLayoutAlgorithm;
@@ -30,6 +31,9 @@
   // Returns the next sibling.
   virtual NGLayoutInputNode* NextSibling() = 0;
 
+  // Returns the LayoutObject which is associated with this node.
+  virtual LayoutObject* GetLayoutObject() = 0;
+
   NGLayoutInputNodeType Type() const {
     return static_cast<NGLayoutInputNodeType>(type_);
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
index 7b85379..be0f9ab1 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
@@ -42,7 +42,8 @@
   if (inline_box_->IsBidiEnabled())
     BidiReorder();
 
-  NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText);
+  NGFragmentBuilder text_builder(NGPhysicalFragment::kFragmentText,
+                                 inline_box_->GetLayoutObject());
   text_builder.SetWritingMode(constraint_space_->WritingMode());
   LayoutUnit inline_offset;
   const Vector<NGLayoutInlineItem>& items = inline_box_->Items();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
index ee1b8d8a..8efd4f9 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
@@ -7,16 +7,18 @@
 namespace blink {
 
 NGPhysicalBoxFragment::NGPhysicalBoxFragment(
+    LayoutObject* layout_object,
     NGPhysicalSize size,
     NGPhysicalSize overflow,
-    HeapVector<Member<const NGPhysicalFragment>>& children,
+    HeapVector<Member<NGPhysicalFragment>>& children,
     HeapLinkedHashSet<WeakMember<NGBlockNode>>& out_of_flow_descendants,
     Vector<NGStaticPosition>& out_of_flow_positions,
     NGDeprecatedMarginStrut margin_strut,
     HeapVector<Member<NGFloatingObject>>& unpositioned_floats,
     HeapVector<Member<NGFloatingObject>>& positioned_floats,
     NGBreakToken* break_token)
-    : NGPhysicalFragment(size,
+    : NGPhysicalFragment(layout_object,
+                         size,
                          overflow,
                          kFragmentBox,
                          out_of_flow_descendants,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
index 0a9edc2..e9b2a171 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
@@ -19,9 +19,10 @@
  public:
   // This modifies the passed-in children vector.
   NGPhysicalBoxFragment(
+      LayoutObject* layout_object,
       NGPhysicalSize size,
       NGPhysicalSize overflow,
-      HeapVector<Member<const NGPhysicalFragment>>& children,
+      HeapVector<Member<NGPhysicalFragment>>& children,
       HeapLinkedHashSet<WeakMember<NGBlockNode>>& out_of_flow_descendants,
       Vector<NGStaticPosition>& out_of_flow_positions,
       NGDeprecatedMarginStrut margin_strut,
@@ -29,7 +30,7 @@
       HeapVector<Member<NGFloatingObject>>& positioned_floats,
       NGBreakToken* break_token = nullptr);
 
-  const HeapVector<Member<const NGPhysicalFragment>>& Children() const {
+  const HeapVector<Member<NGPhysicalFragment>>& Children() const {
     return children_;
   }
 
@@ -38,7 +39,7 @@
   DECLARE_TRACE_AFTER_DISPATCH();
 
  private:
-  HeapVector<Member<const NGPhysicalFragment>> children_;
+  HeapVector<Member<NGPhysicalFragment>> children_;
   NGDeprecatedMarginStrut margin_strut_;
 };
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
index f08f1c5b..147049b 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
@@ -11,6 +11,7 @@
 namespace blink {
 
 NGPhysicalFragment::NGPhysicalFragment(
+    LayoutObject* layout_object,
     NGPhysicalSize size,
     NGPhysicalSize overflow,
     NGFragmentType type,
@@ -19,7 +20,8 @@
     HeapVector<Member<NGFloatingObject>>& unpositioned_floats,
     HeapVector<Member<NGFloatingObject>>& positioned_floats,
     NGBreakToken* break_token)
-    : size_(size),
+    : layout_object_(layout_object),
+      size_(size),
       overflow_(overflow),
       break_token_(break_token),
       type_(type),
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
index a222834..bb69c7f 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
@@ -13,6 +13,7 @@
 
 namespace blink {
 
+class LayoutObject;
 class NGBlockNode;
 class NGBreakToken;
 struct NGFloatingObject;
@@ -21,6 +22,10 @@
 // fragment stores all of its information in the physical coordinate system for
 // use by paint, hit-testing etc.
 //
+// The fragment keeps a pointer back to the LayoutObject which generated it.
+// Once we have transitioned fully to LayoutNG it should be a const pointer
+// such that paint/hit-testing/etc don't modify it.
+//
 // Layout code should only access output layout information through the
 // NGFragmentBase classes which transforms information into the logical
 // coordinate system.
@@ -64,6 +69,8 @@
 
   NGBreakToken* BreakToken() const { return break_token_; }
 
+  LayoutObject* GetLayoutObject() const { return layout_object_; }
+
   const HeapLinkedHashSet<WeakMember<NGBlockNode>>& OutOfFlowDescendants()
       const {
     return out_of_flow_descendants_;
@@ -101,6 +108,7 @@
 
  protected:
   NGPhysicalFragment(
+      LayoutObject* layout_object,
       NGPhysicalSize size,
       NGPhysicalSize overflow,
       NGFragmentType type,
@@ -110,6 +118,7 @@
       HeapVector<Member<NGFloatingObject>>& positioned_floats,
       NGBreakToken* break_token = nullptr);
 
+  LayoutObject* layout_object_;
   NGPhysicalSize size_;
   NGPhysicalSize overflow_;
   NGPhysicalOffset offset_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_text_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_text_fragment.h
index 7de145b..7bdfffb 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_text_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_text_fragment.h
@@ -17,6 +17,7 @@
 class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
  public:
   NGPhysicalTextFragment(
+      LayoutObject* layout_object,
       const NGInlineNode* node,
       unsigned start_index,
       unsigned end_index,
@@ -26,7 +27,8 @@
       Vector<NGStaticPosition> out_of_flow_positions,
       HeapVector<Member<NGFloatingObject>>& unpositioned_floats,
       HeapVector<Member<NGFloatingObject>>& positioned_floats)
-      : NGPhysicalFragment(size,
+      : NGPhysicalFragment(layout_object,
+                           size,
                            overflow,
                            kFragmentText,
                            out_of_flow_descendants,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.h b/third_party/WebKit/Source/core/layout/ng/ng_units.h
index d5b98d1..f2a5972a 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_units.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_units.h
@@ -44,13 +44,6 @@
   bool IsEmpty() const {
     return inline_size == LayoutUnit() || block_size == LayoutUnit();
   }
-
- private:
-  friend class NGBlockLayoutAlgorithmTest;
-  // Used in tests.
-  NGLogicalSize(int inline_size, int block_size)
-      : inline_size(LayoutUnit(inline_size)),
-        block_size(LayoutUnit(block_size)) {}
 };
 
 inline std::ostream& operator<<(std::ostream& stream,
@@ -96,13 +89,6 @@
   bool operator<=(const NGLogicalOffset& other) const;
 
   String ToString() const;
-
- private:
-  friend class NGBlockLayoutAlgorithmTest;
-  // Used in tests.
-  NGLogicalOffset(int inline_offset, int block_offset)
-      : inline_offset(LayoutUnit(inline_offset)),
-        block_offset(LayoutUnit(block_offset)) {}
 };
 
 CORE_EXPORT inline std::ostream& operator<<(std::ostream& os,
@@ -130,7 +116,7 @@
   }
 };
 
-struct NGPhysicalSize {
+struct CORE_EXPORT NGPhysicalSize {
   NGPhysicalSize() {}
   NGPhysicalSize(LayoutUnit width, LayoutUnit height)
       : width(width), height(height) {}
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
index c5c2ac2..276b3bc 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
@@ -853,13 +853,53 @@
       ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
   FetchRequest request(testURL, FetchInitiatorInfo());
   ImageResource* imageResource = ImageResource::fetch(request, fetcher);
+  std::unique_ptr<MockImageResourceObserver> observer =
+      MockImageResourceObserver::create(imageResource->getContent());
 
   imageResource->loader()->didReceiveResponse(
       WrappedResourceResponse(
           ResourceResponse(testURL, "image/jpeg", 18, nullAtom, String())),
       nullptr);
+
+  EXPECT_EQ(0, observer->imageChangedCount());
+
   imageResource->loader()->didReceiveData("notactuallyanimage", 18);
+
   EXPECT_EQ(ResourceStatus::DecodeError, imageResource->getStatus());
+  EXPECT_TRUE(observer->imageNotifyFinishedCalled());
+  EXPECT_EQ(ResourceStatus::DecodeError,
+            observer->statusOnImageNotifyFinished());
+  EXPECT_EQ(2, observer->imageChangedCount());
+  EXPECT_FALSE(imageResource->isLoading());
+}
+
+TEST(ImageResourceTest, DecodeErrorWithEmptyBody) {
+  KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html");
+  ScopedRegisteredURL scopedRegisteredURL(testURL);
+
+  ResourceFetcher* fetcher =
+      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  FetchRequest request(testURL, FetchInitiatorInfo());
+  ImageResource* imageResource = ImageResource::fetch(request, fetcher);
+  std::unique_ptr<MockImageResourceObserver> observer =
+      MockImageResourceObserver::create(imageResource->getContent());
+
+  imageResource->loader()->didReceiveResponse(
+      WrappedResourceResponse(
+          ResourceResponse(testURL, "image/jpeg", 0, nullAtom, String())),
+      nullptr);
+
+  EXPECT_EQ(ResourceStatus::Pending, imageResource->getStatus());
+  EXPECT_FALSE(observer->imageNotifyFinishedCalled());
+  EXPECT_EQ(0, observer->imageChangedCount());
+
+  imageResource->loader()->didFinishLoading(0.0, 0, 0);
+
+  EXPECT_EQ(ResourceStatus::DecodeError, imageResource->getStatus());
+  EXPECT_TRUE(observer->imageNotifyFinishedCalled());
+  EXPECT_EQ(ResourceStatus::DecodeError,
+            observer->statusOnImageNotifyFinished());
+  EXPECT_EQ(1, observer->imageChangedCount());
   EXPECT_FALSE(imageResource->isLoading());
 }
 
@@ -1027,6 +1067,9 @@
   imageResource->loader()->didReceiveResponse(
       WrappedResourceResponse(ResourceResponse(
           testURL, "image/jpeg", sizeof(kBadData), nullAtom, String())));
+
+  EXPECT_EQ(0, observer->imageChangedCount());
+
   imageResource->loader()->didReceiveData(kBadData, sizeof(kBadData));
 
   // The dimensions could not be extracted, so the full original image should be
@@ -1039,6 +1082,7 @@
       static_cast<int>(WebCachePolicy::BypassingCache),
       static_cast<int>(imageResource->resourceRequest().getCachePolicy()));
   EXPECT_FALSE(observer->imageNotifyFinishedCalled());
+  EXPECT_EQ(3, observer->imageChangedCount());
 
   imageResource->loader()->didReceiveResponse(
       WrappedResourceResponse(ResourceResponse(
@@ -1051,7 +1095,7 @@
   EXPECT_EQ(ResourceStatus::Cached, imageResource->getStatus());
   EXPECT_EQ(sizeof(kJpegImage), imageResource->encodedSize());
   EXPECT_FALSE(imageResource->isPlaceholder());
-  EXPECT_LT(0, observer->imageChangedCount());
+  EXPECT_LT(3, observer->imageChangedCount());
   EXPECT_EQ(kJpegImageWidth, observer->imageWidthOnLastImageChanged());
   EXPECT_TRUE(observer->imageNotifyFinishedCalled());
   EXPECT_EQ(kJpegImageWidth, observer->imageWidthOnImageNotifyFinished());
diff --git a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp
index 504ee10a..0432687 100644
--- a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp
@@ -44,6 +44,7 @@
   m_imageNotifyFinishedCount++;
   m_imageWidthOnImageNotifyFinished =
       m_content->hasImage() ? m_content->getImage()->width() : 0;
+  m_statusOnImageNotifyFinished = m_content->getStatus();
 }
 
 bool MockImageResourceObserver::imageNotifyFinishedCalled() const {
diff --git a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h
index 0fdabb11..44028471 100644
--- a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h
+++ b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h
@@ -8,6 +8,7 @@
 #include "core/loader/resource/ImageResource.h"
 #include "core/loader/resource/ImageResourceContent.h"
 #include "core/loader/resource/ImageResourceObserver.h"
+#include "platform/loader/fetch/ResourceStatus.h"
 #include <memory>
 
 namespace blink {
@@ -31,6 +32,9 @@
   int imageWidthOnImageNotifyFinished() const {
     return m_imageWidthOnImageNotifyFinished;
   }
+  ResourceStatus statusOnImageNotifyFinished() const {
+    return m_statusOnImageNotifyFinished;
+  }
 
  private:
   explicit MockImageResourceObserver(ImageResourceContent*);
@@ -45,6 +49,7 @@
   int m_imageWidthOnLastImageChanged;
   int m_imageNotifyFinishedCount;
   int m_imageWidthOnImageNotifyFinished;
+  ResourceStatus m_statusOnImageNotifyFinished = ResourceStatus::NotStarted;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js b/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js
index 379e79a..79463a2 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js
@@ -14,13 +14,24 @@
  * @return {!Promise<!UI.SuggestBox.Suggestions>}
  */
 Components.JavaScriptAutocomplete.completionsForTextInCurrentContext = function(text, query, force) {
+  var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text, true);
+  var mapCompletionsPromise = Components.JavaScriptAutocomplete._mapCompletions(text, query);
+  return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpression, query, force)
+      .then(completions => mapCompletionsPromise.then(mapCompletions => mapCompletions.concat(completions)));
+};
+
+/**
+ * @param {string} text
+ * @param {boolean=} allowEndingBracket
+ * @return {string}
+ */
+Components.JavaScriptAutocomplete._clipExpression = function(text, allowEndingBracket) {
   var index;
   var stopChars = new Set('=:({;,!+-*/&|^<>`'.split(''));
   var whiteSpaceChars = new Set(' \r\n\t'.split(''));
   var continueChars = new Set('[. \r\n\t'.split(''));
 
   for (index = text.length - 1; index >= 0; index--) {
-    // Pass less stop characters to rangeOfWord so the range will be a more complete expression.
     if (stopChars.has(text.charAt(index)))
       break;
     if (whiteSpaceChars.has(text.charAt(index)) && !continueChars.has(text.charAt(index - 1)))
@@ -35,16 +46,112 @@
     if (character === ']')
       bracketCount++;
     // Allow an open bracket at the end for property completion.
-    if (character === '[' && index < clippedExpression.length - 1) {
+    if (character === '[' && (index < clippedExpression.length - 1 || !allowEndingBracket)) {
       bracketCount--;
       if (bracketCount < 0)
         break;
     }
     index--;
   }
-  clippedExpression = clippedExpression.substring(index + 1).trim();
+  return clippedExpression.substring(index + 1).trim();
+};
 
-  return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpression, query, force);
+/**
+ * @param {string} text
+ * @param {string} query
+ * @return {!Promise<!UI.SuggestBox.Suggestions>}
+ */
+Components.JavaScriptAutocomplete._mapCompletions = function(text, query) {
+  var mapMatch = text.match(/\.\s*(get|set|delete)\s*\(\s*$/);
+  var executionContext = UI.context.flavor(SDK.ExecutionContext);
+  if (!executionContext || !mapMatch)
+    return Promise.resolve([]);
+
+  var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text.substring(0, mapMatch.index));
+  var fulfill;
+  var promise = new Promise(x => fulfill = x);
+  executionContext.evaluate(clippedExpression, 'completion', true, true, false, false, false, evaluated);
+  return promise;
+
+  /**
+   * @param {?SDK.RemoteObject} result
+   * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
+   */
+  function evaluated(result, exceptionDetails) {
+    if (!result || !!exceptionDetails || result.subtype !== 'map') {
+      fulfill([]);
+      return;
+    }
+    result.getOwnPropertiesPromise(false).then(extractEntriesProperty);
+  }
+
+  /**
+   * @param {!{properties: ?Array<!SDK.RemoteObjectProperty>, internalProperties: ?Array<!SDK.RemoteObjectProperty>}} properties
+   */
+  function extractEntriesProperty(properties) {
+    var internalProperties = properties.internalProperties || [];
+    var entriesProperty = internalProperties.find(property => property.name === '[[Entries]]');
+    if (!entriesProperty) {
+      fulfill([]);
+      return;
+    }
+    entriesProperty.value.callFunctionJSONPromise(getEntries).then(keysObj => gotKeys(Object.keys(keysObj)));
+  }
+
+  /**
+   * @suppressReceiverCheck
+   * @this {!Array<{key:?, value:?}>}
+   * @return {!Object}
+   */
+  function getEntries() {
+    var result = {__proto__: null};
+    for (var i = 0; i < this.length; i++) {
+      if (typeof this[i].key === 'string')
+        result[this[i].key] = true;
+    }
+    return result;
+  }
+
+  /**
+   * @param {!Array<string>} rawKeys
+   */
+  function gotKeys(rawKeys) {
+    var caseSensitivePrefix = [];
+    var caseInsensitivePrefix = [];
+    var caseSensitiveAnywhere = [];
+    var caseInsensitiveAnywhere = [];
+    var quoteChar = '"';
+    if (query.startsWith('\''))
+      quoteChar = '\'';
+    var endChar = ')';
+    if (mapMatch[0].indexOf('set') !== -1)
+      endChar = ', ';
+
+    var sorter = rawKeys.length < 1000 ? String.naturalOrderComparator : undefined;
+    var keys = rawKeys.sort(sorter).map(key => quoteChar + key + quoteChar + endChar);
+
+    for (var key of keys) {
+      if (key.length < query.length)
+        continue;
+      if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1)
+        continue;
+      // Substitute actual newlines with newline characters. @see crbug.com/498421
+      var title = key.split('\n').join('\\n');
+
+      if (key.startsWith(query))
+        caseSensitivePrefix.push({title: title, priority: 4});
+      else if (key.toLowerCase().startsWith(query.toLowerCase()))
+        caseInsensitivePrefix.push({title: title, priority: 3});
+      else if (key.indexOf(query) !== -1)
+        caseSensitiveAnywhere.push({title: title, priority: 2});
+      else
+        caseInsensitiveAnywhere.push({title: title, priority: 1});
+    }
+    var suggestions = caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
+    if (suggestions.length)
+      suggestions[0].subtitle = Common.UIString('Keys');
+    fulfill(suggestions);
+  }
 };
 
 /**
@@ -76,8 +183,8 @@
   if (!query && !expressionString && !force)
     return Promise.resolve([]);
 
-  var fufill;
-  var promise = new Promise(x => fufill = x);
+  var fulfill;
+  var promise = new Promise(x => fulfill = x);
   var selectedFrame = executionContext.debuggerModel.selectedCallFrame();
   if (!expressionString && selectedFrame)
     variableNamesInScopes(selectedFrame, receivedPropertyNames);
@@ -91,7 +198,7 @@
    */
   function evaluated(result, exceptionDetails) {
     if (!result || !!exceptionDetails) {
-      fufill([]);
+      fulfill([]);
       return;
     }
 
@@ -223,7 +330,7 @@
     if (result && !exceptionDetails)
       receivedPropertyNames(/** @type {!Object} */ (result.value));
     else
-      fufill([]);
+      fulfill([]);
   }
 
   /**
@@ -232,7 +339,7 @@
   function receivedPropertyNames(object) {
     executionContext.target().runtimeAgent().releaseObjectGroup('completion');
     if (!object) {
-      fufill([]);
+      fulfill([]);
       return;
     }
     var propertyGroups = /** @type {!Array<!Components.JavaScriptAutocomplete.CompletionGroup>} */ (object);
@@ -262,7 +369,7 @@
       ];
       propertyGroups.push({items: commandLineAPI});
     }
-    fufill(Components.JavaScriptAutocomplete._completionsForQuery(
+    fulfill(Components.JavaScriptAutocomplete._completionsForQuery(
         dotNotation, bracketNotation, expressionString, query, propertyGroups));
   }
 };
@@ -296,7 +403,7 @@
   var result = [];
   var lastGroupTitle;
   for (var group of propertyGroups) {
-    group.items.sort(itemComparator);
+    group.items.sort(itemComparator.bind(null, group.items.length > 1000));
     var caseSensitivePrefix = [];
     var caseInsensitivePrefix = [];
     var caseSensitiveAnywhere = [];
@@ -340,17 +447,18 @@
   return result;
 
   /**
+   * @param {boolean} naturalOrder
    * @param {string} a
    * @param {string} b
    * @return {number}
    */
-  function itemComparator(a, b) {
+  function itemComparator(naturalOrder, a, b) {
     var aStartsWithUnderscore = a.startsWith('_');
     var bStartsWithUnderscore = b.startsWith('_');
     if (aStartsWithUnderscore && !bStartsWithUnderscore)
       return 1;
     if (bStartsWithUnderscore && !aStartsWithUnderscore)
       return -1;
-    return String.naturalOrderComparator(a, b);
+    return naturalOrder ? String.naturalOrderComparator(a, b) : a.localeCompare(b);
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
index 5351fa7..11d9e33 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
@@ -264,7 +264,7 @@
 
     var excludedTokens = new Set(['js-comment', 'js-string-2', 'js-def']);
     var trimmedBefore = before.trim();
-    if (!trimmedBefore.endsWith('['))
+    if (!trimmedBefore.endsWith('[') && !trimmedBefore.match(/\.\s*(get|set|delete)\s*\(\s*$/))
       excludedTokens.add('js-string');
     if (!trimmedBefore.endsWith('.'))
       excludedTokens.add('js-property');
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
index 7dc4d44a2..37a7b2f2 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -263,9 +263,9 @@
     var columnId = this._dataGrid.sortColumnId();
     this._networkLogView.removeAllNodeHighlights();
     this._waterfallRequestsAreStale = true;
-    if (columnId === 'waterfall') {
-      this._waterfallColumnSortIcon.classList.remove('sort-ascending', 'sort-descending');
+    this._waterfallColumnSortIcon.classList.remove('sort-ascending', 'sort-descending');
 
+    if (columnId === 'waterfall') {
       if (this._dataGrid.sortOrder() === DataGrid.DataGrid.Order.Ascending)
         this._waterfallColumnSortIcon.classList.add('sort-ascending');
       else
diff --git a/third_party/WebKit/Source/devtools/front_end/network/networkLogView.css b/third_party/WebKit/Source/devtools/front_end/network/networkLogView.css
index 73a9653..a434b65 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/networkLogView.css
+++ b/third_party/WebKit/Source/devtools/front_end/network/networkLogView.css
@@ -389,6 +389,12 @@
     display: none;
 }
 
+@media (-webkit-min-device-pixel-ratio: 1.1) {
+.network-waterfall-header .sort-order-icon {
+    background-image: url(Images/toolbarButtonGlyphs_2x.png);
+}
+} /* media */
+
 .network-waterfall-header .sort-ascending.sort-order-icon {
     display: block;
     background-position: -4px -111px;
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp
index 8737ae9..5c3b653 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.cpp
@@ -32,6 +32,7 @@
 #include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/html/HTMLMediaElement.h"
 #include "modules/encryptedmedia/ContentDecryptionModuleResultPromise.h"
 #include "modules/encryptedmedia/EncryptedMediaUtils.h"
@@ -142,7 +143,9 @@
       m_cdm(std::move(cdm)),
       m_mediaElement(nullptr),
       m_reservedForMediaElement(false),
-      m_timer(this, &MediaKeys::timerFired) {
+      m_timer(TaskRunnerHelper::get(TaskType::MiscPlatformAPI, context),
+              this,
+              &MediaKeys::timerFired) {
   DVLOG(MEDIA_KEYS_LOG_LEVEL) << __func__ << "(" << this << ")";
   InstanceCounters::incrementCounter(InstanceCounters::MediaKeysCounter);
 }
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h
index 9d69dd78..edb874e 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h
+++ b/third_party/WebKit/Source/modules/encryptedmedia/MediaKeys.h
@@ -128,7 +128,7 @@
   bool m_reservedForMediaElement;
 
   HeapDeque<Member<PendingAction>> m_pendingActions;
-  Timer<MediaKeys> m_timer;
+  TaskRunnerTimer<MediaKeys> m_timer;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationError.cpp b/third_party/WebKit/Source/modules/presentation/PresentationError.cpp
index f238e04..3b1aca0 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationError.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationError.cpp
@@ -24,6 +24,9 @@
     case WebPresentationError::ErrorTypeAvailabilityNotSupported:
       code = NotSupportedError;
       break;
+    case WebPresentationError::ErrorTypePreviousStartInProgress:
+      code = OperationError;
+      break;
     case WebPresentationError::ErrorTypeUnknown:
       code = UnknownError;
       break;
diff --git a/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp b/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp
index fb749cad..0a4e6e6 100644
--- a/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp
+++ b/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp
@@ -9,7 +9,7 @@
 #include "cc/animation/animation_timeline.h"
 #include "cc/blink/web_layer_impl.h"
 #include "cc/layers/layer.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebLayer.h"
@@ -24,14 +24,13 @@
 WebLayerTreeViewImplForTesting::WebLayerTreeViewImplForTesting(
     const cc::LayerTreeSettings& settings) {
   m_animationHost = cc::AnimationHost::CreateMainInstance();
-  cc::LayerTreeHostInProcess::InitParams params;
+  cc::LayerTreeHost::InitParams params;
   params.client = this;
   params.settings = &settings;
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.task_graph_runner = &m_taskGraphRunner;
   params.mutator_host = m_animationHost.get();
-  m_layerTreeHost =
-      cc::LayerTreeHostInProcess::CreateSingleThreaded(this, &params);
+  m_layerTreeHost = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
   ASSERT(m_layerTreeHost);
 }
 
diff --git a/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp b/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp
index 1645943..897ffa5 100644
--- a/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp
+++ b/third_party/WebKit/Source/web/tests/NGInlineLayoutTest.cpp
@@ -49,7 +49,8 @@
   NGInlineNode* inlineBox =
       new NGInlineNode(blockFlow->firstChild(), blockFlow->mutableStyle());
   NGPhysicalFragment* fragment =
-      NGInlineLayoutAlgorithm(blockFlow->style(), inlineBox, constraintSpace)
+      NGInlineLayoutAlgorithm(blockFlow, blockFlow->style(), inlineBox,
+                              constraintSpace)
           .Layout();
   EXPECT_TRUE(fragment);
 
@@ -75,7 +76,8 @@
   NGInlineNode* inlineBox =
       new NGInlineNode(blockFlow->firstChild(), blockFlow->mutableStyle());
   NGPhysicalFragment* fragment =
-      NGInlineLayoutAlgorithm(blockFlow->style(), inlineBox, constraintSpace)
+      NGInlineLayoutAlgorithm(blockFlow, blockFlow->style(), inlineBox,
+                              constraintSpace)
           .Layout();
   EXPECT_TRUE(fragment);
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
index a1d3d966..5ee9604 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -342,6 +342,7 @@
         description += 'TBR=qyearsley@chromium.org\n'
         # Move any NOEXPORT tag to the end of the description.
         description = description.replace('NOEXPORT=true', '')
+        description = description.replace('\n\n\n\n', '\n\n')
         description += 'NOEXPORT=true'
         return description
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
index 2cd16a9..a590744 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
@@ -81,12 +81,12 @@
 
     def test_cl_description_with_empty_environ(self):
         host = MockHost()
-        host.executive = MockExecutive(output='Last commit message\n')
+        host.executive = MockExecutive(output='Last commit message\n\n')
         updater = DepsUpdater(host)
         description = updater._cl_description()
         self.assertEqual(
             description,
-            ('Last commit message\n'
+            ('Last commit message\n\n'
              'TBR=qyearsley@chromium.org\n'
              'NOEXPORT=true'))
         self.assertEqual(host.executive.calls, [['git', 'log', '-1', '--format=%B']])
@@ -109,7 +109,7 @@
 
     def test_cl_description_moves_noexport_tag(self):
         host = MockHost()
-        host.executive = MockExecutive(output='Summary\n\nNOEXPORT=true')
+        host.executive = MockExecutive(output='Summary\n\nNOEXPORT=true\n\n')
         updater = DepsUpdater(host)
         description = updater._cl_description()
         self.assertEqual(
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
index ceb7387..e053170 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
@@ -70,7 +70,7 @@
 
     def all_branches(self):
         """Returns a list of local and remote branches."""
-        return self.run(['git', 'branch', '-a']).splitlines()
+        return [s.strip() for s in self.run(['git', 'branch', '-a']).splitlines()]
 
     def create_branch_with_patch(self, message, patch, author):
         """Commits the given patch and pushes to the upstream repo.
@@ -95,6 +95,7 @@
         # TODO(jeffcarp): Use git am -p<n> where n is len(CHROMIUM_WPT_DIR.split(/'))
         # or something not off-by-one.
         self.run(['git', 'apply', '-'], input=patch)
+        self.run(['git', 'add', '.'])
         self.run(['git', 'commit', '--author', author, '-am', message])
         self.run(['git', 'push', REMOTE_NAME, self.branch_name])
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py
index f90c772..8591941 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt_unittest.py
@@ -96,5 +96,6 @@
             ['git', 'branch', '-a'],
             ['git', 'checkout', '-b', 'chromium-export-try'],
             ['git', 'apply', '-'],
+            ['git', 'add', '.'],
             ['git', 'commit', '--author', 'author', '-am', 'message'],
             ['git', 'push', 'github', 'chromium-export-try']])
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
index e3f6b73a..4cc6fb8 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
@@ -96,11 +96,12 @@
             raise Exception('PR could not be merged: %d' % pull_request_number)
 
     def delete_remote_branch(self, remote_branch_name):
+        # TODO(jeffcarp): Unit test this method
         path = '/repos/w3c/web-platform-tests/git/refs/heads/%s' % remote_branch_name
         data, status_code = self.request(path, method='DELETE')
 
-        if status_code != 200:
+        if status_code != 204:
             # TODO(jeffcarp): Raise more specific exception (create MergeError class?)
-            raise Exception('PR could not be merged')
+            raise Exception('Received non-204 status code attempting to delete remote branch: {}'.format(status_code))
 
         return data
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h
index f12792ef..ed01d8d84 100644
--- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h
+++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h
@@ -15,6 +15,7 @@
     ErrorTypeSessionRequestCancelled,
     ErrorTypeNoPresentationFound,
     ErrorTypeAvailabilityNotSupported,
+    ErrorTypePreviousStartInProgress,
     ErrorTypeUnknown,
     ErrorTypeLast = ErrorTypeUnknown
   };
diff --git a/third_party/WebKit/public/platform/modules/presentation/presentation.mojom b/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
index 96aea0c7..7af9140 100644
--- a/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
+++ b/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
@@ -30,6 +30,7 @@
   NO_AVAILABLE_SCREENS,
   SESSION_REQUEST_CANCELLED,
   NO_PRESENTATION_FOUND,
+  PREVIOUS_START_IN_PROGRESS,
   UNKNOWN,
 };
 
diff --git a/tools/perf/PRESUBMIT.py b/tools/perf/PRESUBMIT.py
index ec698c42..25fe5f4 100644
--- a/tools/perf/PRESUBMIT.py
+++ b/tools/perf/PRESUBMIT.py
@@ -9,7 +9,6 @@
 """
 
 import os
-import re
 import sys
 
 
@@ -96,50 +95,3 @@
   report = []
   report.extend(_CommonChecks(input_api, output_api))
   return report
-
-
-def _AreBenchmarksModified(change):
-  """Checks whether CL contains any modification to Telemetry benchmarks."""
-  for affected_file in change.AffectedFiles():
-    file_path = affected_file.LocalPath()
-    # Changes to unittest files should not count.
-    if file_path.endswith('test.py'):
-        continue
-    if (os.path.join('tools', 'perf', 'benchmarks') in file_path or
-        os.path.join('tools', 'perf', 'measurements') in file_path):
-      return True
-  return False
-
-
-def PostUploadHook(cl, change, output_api):
-  """git cl upload will call this hook after the issue is created/modified.
-
-  This hook adds extra try bots list to the CL description in order to run
-  Telemetry benchmarks on Perf trybots in addition to CQ trybots if the CL
-  contains any changes to Telemetry benchmarks.
-  """
-  benchmarks_modified = _AreBenchmarksModified(change)
-  rietveld_obj = cl.RpcServer()
-  issue = cl.issue
-  original_description = rietveld_obj.get_description(issue)
-  if not benchmarks_modified or re.search(
-      r'^CQ_INCLUDE_TRYBOTS=.*', original_description, re.M | re.I):
-    return []
-
-  results = []
-  bots = [
-    'linux_perf_cq',
-    'mac_retina_perf_cq',
-    'winx64_10_perf_cq'
-  ]
-  bots = ['master.tryserver.chromium.perf:%s' % s for s in bots]
-  bots_string = ';'.join(bots)
-  description = original_description
-  description += '\nCQ_INCLUDE_TRYBOTS=%s' % bots_string
-  results.append(output_api.PresubmitNotifyResult(
-      'Automatically added Perf trybots to run Telemetry benchmarks on CQ.'))
-
-  if description != original_description:
-    rietveld_obj.update_description(issue, description)
-
-  return results
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index fb0fe72..236560d 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -30,7 +30,7 @@
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/surfaces/surface_id_allocator.h"
 #include "cc/surfaces/surface_manager.h"
-#include "cc/trees/layer_tree_host_in_process.h"
+#include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/compositor/compositor_observer.h"
@@ -193,13 +193,13 @@
 
   animation_host_ = cc::AnimationHost::CreateMainInstance();
 
-  cc::LayerTreeHostInProcess::InitParams params;
+  cc::LayerTreeHost::InitParams params;
   params.client = this;
   params.task_graph_runner = context_factory_->GetTaskGraphRunner();
   params.settings = &settings;
   params.main_task_runner = task_runner_;
   params.mutator_host = animation_host_.get();
-  host_ = cc::LayerTreeHostInProcess::CreateSingleThreaded(this, &params);
+  host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
   UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor",
                       base::TimeTicks::Now() - before_create);
 
diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index cd1792f..a52c806 100644
--- a/ui/views/corewm/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -25,12 +25,13 @@
 #include "ui/gfx/text_elider.h"
 #include "ui/views/corewm/tooltip.h"
 #include "ui/views/widget/tooltip_manager.h"
+#include "ui/wm/public/tooltip_client.h"
 
 namespace views {
 namespace corewm {
 namespace {
 
-const int kTooltipTimeoutMs = 500;
+const int kDelayForTooltipUpdateInMs = 500;
 const int kDefaultTooltipShownTimeoutMs = 10000;
 #if defined(OS_WIN)
 // Drawing a long word in tooltip is very slow on Windows. crbug.com/513693
@@ -129,11 +130,8 @@
       tooltip_id_(NULL),
       tooltip_window_at_mouse_press_(NULL),
       tooltip_(std::move(tooltip)),
-      tooltips_enabled_(true) {
-  tooltip_timer_.Start(FROM_HERE,
-      base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs),
-      this, &TooltipController::TooltipTimerFired);
-}
+      tooltips_enabled_(true),
+      tooltip_show_delayed_(true) {}
 
 TooltipController::~TooltipController() {
   if (tooltip_window_)
@@ -150,9 +148,7 @@
     UpdateIfRequired();
 
   // Reset |tooltip_window_at_mouse_press_| if the moving within the same window
-  // but over a region that has different tooltip text. By resetting
-  // |tooltip_window_at_mouse_press_| we ensure the next time the timer fires
-  // we'll requery for the tooltip text.
+  // but over a region that has different tooltip text.
   // This handles the case of clicking on a view, moving within the same window
   // but over a different view, than back to the original.
   if (tooltip_window_at_mouse_press_ &&
@@ -160,17 +156,6 @@
       aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) {
     tooltip_window_at_mouse_press_ = NULL;
   }
-
-  // If we had stopped the tooltip timer for some reason, we must restart it if
-  // there is a change in the tooltip.
-  if (!tooltip_timer_.IsRunning()) {
-    if (tooltip_window_ != target || (tooltip_window_ &&
-        tooltip_text_ != aura::client::GetTooltipText(tooltip_window_))) {
-      tooltip_timer_.Start(FROM_HERE,
-          base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs),
-          this, &TooltipController::TooltipTimerFired);
-    }
-  }
 }
 
 void TooltipController::SetTooltipShownTimeout(aura::Window* target,
@@ -211,10 +196,10 @@
         target = GetTooltipTarget(*event, &curr_mouse_loc_);
       }
       SetTooltipWindow(target);
-      if (tooltip_timer_.IsRunning())
-        tooltip_timer_.Reset();
 
-      if (tooltip_->IsVisible())
+      if (tooltip_->IsVisible() ||
+          (tooltip_window_ &&
+           tooltip_text_ != aura::client::GetTooltipText(tooltip_window_)))
         UpdateIfRequired();
       break;
     }
@@ -232,10 +217,6 @@
       // Hide the tooltip for click, release, drag, wheel events.
       if (tooltip_->IsVisible())
         tooltip_->Hide();
-
-      // Don't reshow the tooltip during scroll.
-      if (tooltip_timer_.IsRunning())
-        tooltip_timer_.Reset();
       break;
     default:
       break;
@@ -255,6 +236,10 @@
   SetTooltipWindow(NULL);
 }
 
+void TooltipController::OnCursorVisibilityChanged(bool is_visible) {
+  UpdateIfRequired();
+}
+
 void TooltipController::OnWindowDestroyed(aura::Window* window) {
   if (tooltip_window_ == window) {
     tooltip_->Hide();
@@ -263,25 +248,26 @@
   }
 }
 
+void TooltipController::OnWindowPropertyChanged(aura::Window* window,
+                                                const void* key,
+                                                intptr_t old) {
+  if ((key == aura::client::kTooltipIdKey ||
+       key == aura::client::kTooltipTextKey) &&
+      aura::client::GetTooltipText(window) != base::string16() &&
+      (tooltip_text_ != aura::client::GetTooltipText(window) ||
+       tooltip_id_ != aura::client::GetTooltipId(window)))
+    UpdateIfRequired();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // TooltipController private:
 
-void TooltipController::TooltipTimerFired() {
-  UpdateIfRequired();
-}
-
 void TooltipController::TooltipShownTimerFired() {
   tooltip_->Hide();
-
-  // Since the user presumably no longer needs the tooltip, we also stop the
-  // tooltip timer so that tooltip does not pop back up. We will restart this
-  // timer if the tooltip changes (see UpdateTooltip()).
-  tooltip_timer_.Stop();
 }
 
 void TooltipController::UpdateIfRequired() {
-  if (!tooltips_enabled_ ||
-      aura::Env::GetInstance()->IsMouseButtonDown() ||
+  if (!tooltips_enabled_ || aura::Env::GetInstance()->IsMouseButtonDown() ||
       IsDragDropInProgress() || !IsCursorVisible()) {
     tooltip_->Hide();
     return;
@@ -309,9 +295,6 @@
   ids_differ = tooltip_id_ != tooltip_id;
   tooltip_id_ = tooltip_id;
 
-  // We add the !tooltip_->IsVisible() below because when we come here from
-  // TooltipTimerFired(), the tooltip_text may not have changed but we still
-  // want to update the tooltip because the timer has fired.
   // If we come here from UpdateTooltip(), we have already checked for tooltip
   // visibility and this check below will have no effect.
   if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) {
@@ -321,26 +304,44 @@
         gfx::TruncateString(tooltip_text_, kMaxTooltipLength, gfx::WORD_BREAK);
     // If the string consists entirely of whitespace, then don't both showing it
     // (an empty tooltip is useless).
-    base::string16 whitespace_removed_text;
     base::TrimWhitespace(trimmed_text, base::TRIM_ALL,
-                         &whitespace_removed_text);
-    if (whitespace_removed_text.empty()) {
+                         &tooltip_text_whitespace_trimmed_);
+    if (tooltip_text_whitespace_trimmed_.empty()) {
       tooltip_->Hide();
-    } else {
-      gfx::Point widget_loc = curr_mouse_loc_ +
-          tooltip_window_->GetBoundsInScreen().OffsetFromOrigin();
-      tooltip_->SetText(tooltip_window_, whitespace_removed_text, widget_loc);
-      tooltip_->Show();
-      int timeout = GetTooltipShownTimeout();
-      if (timeout > 0) {
-        tooltip_shown_timer_.Start(FROM_HERE,
-            base::TimeDelta::FromMilliseconds(timeout),
-            this, &TooltipController::TooltipShownTimerFired);
+    } else if (tooltip_show_delayed_) {
+      // Initialize the one-shot timer to show the tooltip in a while.
+      // If there is already a request queued then cancel it and post the new
+      // request. This ensures that tooltip won't show up too early.
+      // The delayed appearance of a tooltip is by default.
+      if (tooltip_defer_timer_.IsRunning()) {
+        tooltip_defer_timer_.Reset();
+      } else {
+        tooltip_defer_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
+                                                  kDelayForTooltipUpdateInMs),
+                                   this, &TooltipController::ShowTooltip);
       }
+    } else {
+      ShowTooltip();  // Allow tooltip to show up without delay for unit tests.
     }
   }
 }
 
+void TooltipController::ShowTooltip() {
+  if (!tooltip_window_)
+    return;
+  gfx::Point widget_loc =
+      curr_mouse_loc_ + tooltip_window_->GetBoundsInScreen().OffsetFromOrigin();
+  tooltip_->SetText(tooltip_window_, tooltip_text_whitespace_trimmed_,
+                    widget_loc);
+  tooltip_->Show();
+  int timeout = GetTooltipShownTimeout();
+  if (timeout > 0) {
+    tooltip_shown_timer_.Start(FROM_HERE,
+                               base::TimeDelta::FromMilliseconds(timeout), this,
+                               &TooltipController::TooltipShownTimerFired);
+  }
+}
+
 bool TooltipController::IsTooltipVisible() {
   return tooltip_->IsVisible();
 }
diff --git a/ui/views/corewm/tooltip_controller.h b/ui/views/corewm/tooltip_controller.h
index 5a274e3..630df74 100644
--- a/ui/views/corewm/tooltip_controller.h
+++ b/ui/views/corewm/tooltip_controller.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "base/timer/timer.h"
+#include "ui/aura/client/cursor_client_observer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/geometry/point.h"
@@ -31,9 +32,11 @@
 }  // namespace test
 
 // TooltipController provides tooltip functionality for aura.
-class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
-                                       public ui::EventHandler,
-                                       public aura::WindowObserver {
+class VIEWS_EXPORT TooltipController
+    : public aura::client::TooltipClient,
+      public ui::EventHandler,
+      public aura::client::CursorClientObserver,
+      public aura::WindowObserver {
  public:
   explicit TooltipController(std::unique_ptr<Tooltip> tooltip);
   ~TooltipController() override;
@@ -50,17 +53,25 @@
   void OnTouchEvent(ui::TouchEvent* event) override;
   void OnCancelMode(ui::CancelModeEvent* event) override;
 
+  // Overridden from aura::client::CursorClientObserver.
+  void OnCursorVisibilityChanged(bool is_visible) override;
+
   // Overridden from aura::WindowObserver.
   void OnWindowDestroyed(aura::Window* window) override;
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override;
 
   const gfx::Point& mouse_location() const { return curr_mouse_loc_; }
 
  private:
   friend class test::TooltipControllerTestHelper;
 
-  void TooltipTimerFired();
   void TooltipShownTimerFired();
 
+  // Show the tooltip.
+  void ShowTooltip();
+
   // Updates the tooltip if required (if there is any change in the tooltip
   // text, tooltip id or the aura::Window).
   void UpdateIfRequired();
@@ -80,8 +91,11 @@
   // Calls AddObserver on the new window if it is not NULL.
   void SetTooltipWindow(aura::Window* target);
 
+  void DisableTooltipShowDelay() { tooltip_show_delayed_ = false; }
+
   aura::Window* tooltip_window_;
   base::string16 tooltip_text_;
+  base::string16 tooltip_text_whitespace_trimmed_;
   const void* tooltip_id_;
 
   // These fields are for tracking state when the user presses a mouse button.
@@ -90,7 +104,8 @@
 
   std::unique_ptr<Tooltip> tooltip_;
 
-  base::RepeatingTimer tooltip_timer_;
+  // Timer for requesting delayed updates of the tooltip.
+  base::OneShotTimer tooltip_defer_timer_;
 
   // Timer to timeout the life of an on-screen tooltip. We hide the tooltip when
   // this timer fires.
@@ -101,6 +116,11 @@
 
   bool tooltips_enabled_;
 
+  // An indicator of whether tooltip appears with delay or not.
+  // If the flag is true, tooltip shows up with delay;
+  // otherwise there is no delay, which is used in unit tests only.
+  bool tooltip_show_delayed_;
+
   std::map<aura::Window*, int> tooltip_shown_timeout_map_;
 
   DISALLOW_COPY_AND_ASSIGN(TooltipController);
diff --git a/ui/views/corewm/tooltip_controller_test_helper.cc b/ui/views/corewm/tooltip_controller_test_helper.cc
index f96b08d..45d940f 100644
--- a/ui/views/corewm/tooltip_controller_test_helper.cc
+++ b/ui/views/corewm/tooltip_controller_test_helper.cc
@@ -14,6 +14,7 @@
 TooltipControllerTestHelper::TooltipControllerTestHelper(
     TooltipController* controller)
     : controller_(controller) {
+  controller_->DisableTooltipShowDelay();
 }
 
 TooltipControllerTestHelper::~TooltipControllerTestHelper() {
@@ -27,12 +28,8 @@
   return controller_->tooltip_window_;
 }
 
-void TooltipControllerTestHelper::FireTooltipTimer() {
-  controller_->TooltipTimerFired();
-}
-
-bool TooltipControllerTestHelper::IsTooltipTimerRunning() {
-  return controller_->tooltip_timer_.IsRunning();
+void TooltipControllerTestHelper::UpdateIfRequired() {
+  controller_->UpdateIfRequired();
 }
 
 void TooltipControllerTestHelper::FireTooltipShownTimer() {
diff --git a/ui/views/corewm/tooltip_controller_test_helper.h b/ui/views/corewm/tooltip_controller_test_helper.h
index af1bcb8..9a710f0 100644
--- a/ui/views/corewm/tooltip_controller_test_helper.h
+++ b/ui/views/corewm/tooltip_controller_test_helper.h
@@ -34,8 +34,7 @@
   // These are mostly cover methods for TooltipController private methods.
   base::string16 GetTooltipText();
   aura::Window* GetTooltipWindow();
-  void FireTooltipTimer();
-  bool IsTooltipTimerRunning();
+  void UpdateIfRequired();
   void FireTooltipShownTimer();
   bool IsTooltipShownTimerRunning();
   bool IsTooltipVisible();
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
index 72209dd..97a3351 100644
--- a/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -187,18 +187,16 @@
   view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
   EXPECT_EQ(base::string16(), helper_->GetTooltipText());
   EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+
   generator_->MoveMouseToCenterOf(GetWindow());
 
   EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint(
       generator_->current_location()));
   base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
   EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
-  EXPECT_EQ(base::string16(), helper_->GetTooltipText());
+  EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
   EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
-
   EXPECT_TRUE(helper_->IsTooltipVisible());
   generator_->MoveMouseBy(1, 0);
 
@@ -221,10 +219,8 @@
       "width");
   view_->set_tooltip_text(text);
   gfx::Point center = GetWindow()->bounds().CenterPoint();
-  generator_->MoveMouseTo(center);
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
+  generator_->MoveMouseTo(center);
 
   EXPECT_TRUE(helper_->IsTooltipVisible());
   gfx::RenderText* render_text =
@@ -249,9 +245,7 @@
   aura::Window* window = GetWindow();
   aura::Window* root_window = GetRootWindow();
 
-  // Fire tooltip timer so tooltip becomes visible.
   generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   for (int i = 0; i < 49; ++i) {
     generator_->MoveMouseBy(1, 0);
@@ -286,22 +280,18 @@
   EXPECT_EQ(NULL, helper_->GetTooltipWindow());
 
   generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint());
-  base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
-
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
 
   // Disable tooltips and check again.
   helper_->controller()->SetTooltipsEnabled(false);
   EXPECT_FALSE(helper_->IsTooltipVisible());
-  helper_->FireTooltipTimer();
+  helper_->UpdateIfRequired();
   EXPECT_FALSE(helper_->IsTooltipVisible());
 
   // Enable tooltips back and check again.
   helper_->controller()->SetTooltipsEnabled(true);
   EXPECT_FALSE(helper_->IsTooltipVisible());
-  helper_->FireTooltipTimer();
+  helper_->UpdateIfRequired();
   EXPECT_TRUE(helper_->IsTooltipVisible());
 }
 
@@ -317,8 +307,6 @@
   EXPECT_EQ(NULL, helper_->GetTooltipWindow());
 
   generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint());
-
-  helper_->FireTooltipTimer();
   EXPECT_FALSE(helper_->IsTooltipVisible());
 }
 
@@ -337,15 +325,12 @@
 
   aura::Window* window = GetWindow();
 
-  // Fire tooltip timer so tooltip becomes visible.
   generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
 
   generator_->PressKey(ui::VKEY_1, 0);
   EXPECT_FALSE(helper_->IsTooltipVisible());
-  EXPECT_FALSE(helper_->IsTooltipTimerRunning());
   EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
 
   // Moving the mouse inside |view1| should not change the state of the tooltip
@@ -353,7 +338,6 @@
   for (int i = 0; i < 49; i++) {
     generator_->MoveMouseBy(1, 0);
     EXPECT_FALSE(helper_->IsTooltipVisible());
-    EXPECT_FALSE(helper_->IsTooltipTimerRunning());
     EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
     EXPECT_EQ(window,
               GetRootWindow()->GetEventHandlerForPoint(
@@ -364,10 +348,9 @@
     EXPECT_EQ(window, helper_->GetTooltipWindow());
   }
 
-  // Now we move the mouse on to |view2|. It should re-start the tooltip timer.
+  // Now we move the mouse on to |view2|. It should update the tooltip.
   generator_->MoveMouseBy(1, 0);
-  EXPECT_TRUE(helper_->IsTooltipTimerRunning());
-  helper_->FireTooltipTimer();
+
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
   base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
@@ -391,15 +374,13 @@
 
   aura::Window* window = GetWindow();
 
-  // Fire tooltip timer so tooltip becomes visible.
+  // Update tooltip so tooltip becomes visible.
   generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
 
   helper_->FireTooltipShownTimer();
   EXPECT_FALSE(helper_->IsTooltipVisible());
-  EXPECT_FALSE(helper_->IsTooltipTimerRunning());
   EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
 
   // Moving the mouse inside |view1| should not change the state of the tooltip
@@ -407,7 +388,6 @@
   for (int i = 0; i < 49; ++i) {
     generator_->MoveMouseBy(1, 0);
     EXPECT_FALSE(helper_->IsTooltipVisible());
-    EXPECT_FALSE(helper_->IsTooltipTimerRunning());
     EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
     EXPECT_EQ(window, GetRootWindow()->GetEventHandlerForPoint(
                   generator_->current_location()));
@@ -417,10 +397,9 @@
     EXPECT_EQ(window, helper_->GetTooltipWindow());
   }
 
-  // Now we move the mouse on to |view2|. It should re-start the tooltip timer.
+  // Now we move the mouse on to |view2|. It should update the tooltip.
   generator_->MoveMouseBy(1, 0);
-  EXPECT_TRUE(helper_->IsTooltipTimerRunning());
-  helper_->FireTooltipTimer();
+
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
   base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
@@ -440,12 +419,9 @@
   generator_->MoveMouseToCenterOf(GetWindow());
   base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
   EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
-  EXPECT_EQ(base::string16(), helper_->GetTooltipText());
+  EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
   EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
-
   EXPECT_TRUE(helper_->IsTooltipVisible());
   generator_->SendMouseExit();
   EXPECT_FALSE(helper_->IsTooltipVisible());
@@ -476,8 +452,6 @@
   View::ConvertPointToWidget(v1, &v1_point);
   generator_->MoveMouseRelativeTo(GetWindow(), v1_point);
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_EQ(v1_tt, helper_->GetTooltipText());
 
@@ -489,7 +463,6 @@
   generator_->MoveMouseRelativeTo(GetWindow(), v2_point);
   generator_->MoveMouseRelativeTo(GetWindow(), v1_point);
 
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_EQ(v1_tt, helper_->GetTooltipText());
 }
@@ -554,9 +527,6 @@
   EXPECT_EQ(base::string16(), helper_->GetTooltipText());
   EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
-
   EXPECT_TRUE(helper_->IsTooltipVisible());
   view_->GetWidget()->ReleaseCapture();
   EXPECT_FALSE(helper_->IsTooltipVisible());
@@ -602,8 +572,6 @@
   generator_->MoveMouseRelativeTo(widget_->GetNativeWindow(),
                                   view_->bounds().CenterPoint());
 
-  EXPECT_TRUE(helper_->IsTooltipTimerRunning());
-  helper_->FireTooltipTimer();
   // Even though the mouse is over a window with a tooltip it shouldn't be
   // picked up because the windows don't have the same value for
   // |TooltipManager::kGroupingPropertyKey|.
@@ -618,8 +586,6 @@
   widget2->SetNativeWindowProperty(TooltipManager::kGroupingPropertyKey,
                                    reinterpret_cast<void*>(grouping_key));
   generator_->MoveMouseBy(1, 10);
-  EXPECT_TRUE(helper_->IsTooltipTimerRunning());
-  helper_->FireTooltipTimer();
   EXPECT_EQ(tooltip_text2, helper_->GetTooltipText());
 
   widget2.reset();
@@ -704,8 +670,8 @@
   window->SetBounds(gfx::Rect(0, 0, 300, 300));
   base::string16 tooltip_text(ASCIIToUTF16(" \nx  "));
   aura::client::SetTooltipText(window.get(), &tooltip_text);
+  EXPECT_FALSE(helper_->IsTooltipVisible());
   generator_->MoveMouseToCenterOf(window.get());
-  helper_->FireTooltipTimer();
   EXPECT_EQ(ASCIIToUTF16("x"), test_tooltip_->tooltip_text());
 }
 
@@ -717,10 +683,9 @@
   window->SetBounds(gfx::Rect(0, 0, 300, 300));
   base::string16 tooltip_text(ASCIIToUTF16("Tooltip Text"));
   aura::client::SetTooltipText(window.get(), &tooltip_text);
+  EXPECT_FALSE(helper_->IsTooltipVisible());
   generator_->MoveMouseToCenterOf(window.get());
 
-  // Fire tooltip timer so tooltip becomes visible.
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
 
   // Send OnCancelMode event and verify that tooltip becomes invisible and
@@ -849,7 +814,6 @@
   // Test whether a toolbar appears on v1
   gfx::Point center = v1->bounds().CenterPoint();
   generator_->MoveMouseRelativeTo(GetWindow(), center);
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_EQ(reference_string, helper_->GetTooltipText());
   gfx::Point tooltip_bounds1 = test_tooltip_->location();
@@ -857,7 +821,6 @@
   // Test whether the toolbar changes position on mouse over v2
   center = v2->bounds().CenterPoint();
   generator_->MoveMouseRelativeTo(GetWindow(), center);
-  helper_->FireTooltipTimer();
   EXPECT_TRUE(helper_->IsTooltipVisible());
   EXPECT_EQ(reference_string, helper_->GetTooltipText());
   gfx::Point tooltip_bounds2 = test_tooltip_->location();
@@ -871,7 +834,6 @@
   center = v2_1->GetLocalBounds().CenterPoint();
   views::View::ConvertPointToTarget(v2_1, view_, &center);
   generator_->MoveMouseRelativeTo(GetWindow(), center);
-  helper_->FireTooltipTimer();
   gfx::Point tooltip_bounds2_1 = test_tooltip_->location();
 
   EXPECT_NE(tooltip_bounds2, tooltip_bounds2_1);
@@ -883,7 +845,6 @@
   center = v2_2->GetLocalBounds().CenterPoint();
   views::View::ConvertPointToTarget(v2_2, view_, &center);
   generator_->MoveMouseRelativeTo(GetWindow(), center);
-  helper_->FireTooltipTimer();
   gfx::Point tooltip_bounds2_2 = test_tooltip_->location();
 
   EXPECT_NE(tooltip_bounds2_1, tooltip_bounds2_2);
@@ -895,7 +856,6 @@
   center = v1_1->GetLocalBounds().CenterPoint();
   views::View::ConvertPointToTarget(v1_1, view_, &center);
   generator_->MoveMouseRelativeTo(GetWindow(), center);
-  helper_->FireTooltipTimer();
   gfx::Point tooltip_bounds1_1 = test_tooltip_->location();
 
   EXPECT_TRUE(helper_->IsTooltipVisible());
@@ -903,7 +863,6 @@
 
   center = v1->bounds().CenterPoint();
   generator_->MoveMouseRelativeTo(GetWindow(), center);
-  helper_->FireTooltipTimer();
   tooltip_bounds1 = test_tooltip_->location();
 
   EXPECT_NE(tooltip_bounds1_1, tooltip_bounds1);
diff --git a/ui/wm/public/tooltip_client.cc b/ui/wm/public/tooltip_client.cc
index 5dd446c..c9fd6f8 100644
--- a/ui/wm/public/tooltip_client.cc
+++ b/ui/wm/public/tooltip_client.cc
@@ -4,19 +4,17 @@
 
 #include "ui/wm/public/tooltip_client.h"
 
-#include "ui/aura/window.h"
 #include "ui/aura/window_property.h"
 
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::TooltipClient*)
-DECLARE_WINDOW_PROPERTY_TYPE(void**)
+DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(AURA_EXPORT, aura::client::TooltipClient*)
+DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(AURA_EXPORT, void**)
 
 namespace aura {
 namespace client {
 
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    TooltipClient*, kRootWindowTooltipClientKey, NULL);
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(base::string16*, kTooltipTextKey, NULL);
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(void*, kTooltipIdKey, NULL);
+DEFINE_WINDOW_PROPERTY_KEY(TooltipClient*, kRootWindowTooltipClientKey, NULL);
+DEFINE_WINDOW_PROPERTY_KEY(base::string16*, kTooltipTextKey, NULL);
+DEFINE_WINDOW_PROPERTY_KEY(void*, kTooltipIdKey, NULL);
 
 void SetTooltipClient(Window* root_window, TooltipClient* client) {
   DCHECK_EQ(root_window->GetRootWindow(), root_window);
diff --git a/ui/wm/public/tooltip_client.h b/ui/wm/public/tooltip_client.h
index 7709515..2b0ebcf 100644
--- a/ui/wm/public/tooltip_client.h
+++ b/ui/wm/public/tooltip_client.h
@@ -6,6 +6,7 @@
 #define UI_WM_PUBLIC_TOOLTIP_CLIENT_H_
 
 #include "ui/aura/aura_export.h"
+#include "ui/aura/window.h"
 #include "ui/gfx/font.h"
 
 namespace gfx {
@@ -52,6 +53,10 @@
 AURA_EXPORT const base::string16 GetTooltipText(Window* window);
 AURA_EXPORT const void* GetTooltipId(Window* window);
 
+AURA_EXPORT extern const aura::WindowProperty<void*>* const kTooltipIdKey;
+AURA_EXPORT extern const aura::WindowProperty<base::string16*>* const
+    kTooltipTextKey;
+
 }  // namespace client
 }  // namespace aura