diff --git a/DEPS b/DEPS
index 7469ceb..5a67d9f 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # 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': '38fc673a85f75931b590cf0f1dc93b9d0a49c8b3',
+  'v8_revision': '13c713b9a19358734d53f50b93157818218627db',
   # 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.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '6939b1db033bf35f4adf1ee55824b6edb3e324d6',
+  'catapult_revision': '34ee837777ae61e0970bd54d5da7bf8cb55e5310',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 3f57da9..2e2904e 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -586,6 +586,8 @@
     "touch/touch_uma.h",
     "utility/screenshot_controller.cc",
     "utility/screenshot_controller.h",
+    "utility/transformer_util.cc",
+    "utility/transformer_util.h",
     "virtual_keyboard_controller.cc",
     "virtual_keyboard_controller.h",
     "wallpaper/wallpaper_controller.cc",
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc
index 78cc055..29cd68e 100644
--- a/ash/display/display_configuration_controller.cc
+++ b/ash/display/display_configuration_controller.cc
@@ -133,16 +133,6 @@
   SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
 }
 
-void DisplayConfigurationController::OnScreenRotationAnimationFinished(
-    ScreenRotationAnimator* screen_rotation_animator) {
-  const int64_t display_id = screen_rotation_animator->display_id();
-
-  DCHECK(rotation_animator_map_.count(display_id));
-
-  screen_rotation_animator->RemoveScreenRotationAnimatorObserver(this);
-  rotation_animator_map_.erase(screen_rotation_animator->display_id());
-}
-
 // Protected
 
 void DisplayConfigurationController::ResetAnimatorForTest() {
@@ -190,7 +180,6 @@
     return iter->second.get();
 
   auto animator = base::MakeUnique<ScreenRotationAnimator>(display_id);
-  animator->AddScreenRotationAnimatorObserver(this);
   ScreenRotationAnimator* result = animator.get();
   rotation_animator_map_.insert(
       std::make_pair(display_id, std::move(animator)));
diff --git a/ash/display/display_configuration_controller.h b/ash/display/display_configuration_controller.h
index 1f121dfe..e67ee35 100644
--- a/ash/display/display_configuration_controller.h
+++ b/ash/display/display_configuration_controller.h
@@ -9,7 +9,6 @@
 
 #include "ash/ash_export.h"
 #include "ash/display/window_tree_host_manager.h"
-#include "ash/rotator/screen_rotation_animator_observer.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/display/display.h"
@@ -34,8 +33,7 @@
 // * Provides a single interface for UI and API classes.
 // * TODO: Forwards display configuration changed events to UI and API classes.
 class ASH_EXPORT DisplayConfigurationController
-    : public WindowTreeHostManager::Observer,
-      public ScreenRotationAnimatorObserver {
+    : public WindowTreeHostManager::Observer {
  public:
   DisplayConfigurationController(
       display::DisplayManager* display_manager,
@@ -62,11 +60,6 @@
   // WindowTreeHostManager::Observer
   void OnDisplayConfigurationChanged() override;
 
-  // ScreenRotationAnimatorObserver
-  // This will be called when the animation is ended or aborted.
-  void OnScreenRotationAnimationFinished(
-      ScreenRotationAnimator* animator) override;
-
  protected:
   friend class ash::test::DisplayConfigurationControllerTestApi;
 
diff --git a/ash/display/display_configuration_controller_unittest.cc b/ash/display/display_configuration_controller_unittest.cc
index d1658af..6b99ad2 100644
--- a/ash/display/display_configuration_controller_unittest.cc
+++ b/ash/display/display_configuration_controller_unittest.cc
@@ -14,7 +14,7 @@
 
 using DisplayConfigurationControllerTest = test::AshTestBase;
 
-TEST_F(DisplayConfigurationControllerTest, ErasesAnimatorOnAnimationEnded) {
+TEST_F(DisplayConfigurationControllerTest, OnlyHasOneAnimator) {
   // TODO(wutao): needs display_configuration_controller
   // http://crbug.com/686839.
   if (Shell::GetAshConfig() == Config::MASH)
@@ -33,7 +33,14 @@
   screen_rotation_animator->Rotate(
       display::Display::ROTATE_90,
       display::Display::RotationSource::ROTATION_SOURCE_USER);
-  EXPECT_EQ(0, testapi.DisplayScreenRotationAnimatorMapSize());
+  EXPECT_EQ(1, testapi.DisplayScreenRotationAnimatorMapSize());
+
+  screen_rotation_animator =
+      testapi.GetScreenRotationAnimatorForDisplay(display.id());
+  screen_rotation_animator->Rotate(
+      display::Display::ROTATE_180,
+      display::Display::RotationSource::ROTATION_SOURCE_USER);
+  EXPECT_EQ(1, testapi.DisplayScreenRotationAnimatorMapSize());
 }
 
 }  // namespace ash
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc
index ed6b72d8..e9ee4a1 100644
--- a/ash/display/root_window_transformers.cc
+++ b/ash/display/root_window_transformers.cc
@@ -10,89 +10,33 @@
 #include "ash/host/root_window_transformer.h"
 #include "ash/magnifier/magnification_controller.h"
 #include "ash/shell.h"
+#include "ash/utility/transformer_util.h"
 #include "base/command_line.h"
-#include "third_party/skia/include/core/SkMatrix44.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/base/class_property.h"
 #include "ui/compositor/dip_util.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
-#include "ui/display/manager/managed_display_info.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/transform.h"
-#include "ui/gfx/transform.h"
-
-DECLARE_UI_CLASS_PROPERTY_TYPE(display::Display::Rotation);
 
 namespace ash {
 namespace {
 
-#if defined(OS_WIN)
-DEFINE_UI_CLASS_PROPERTY_KEY(display::Display::Rotation,
-                             kRotationPropertyKey,
-                             display::Display::ROTATE_0);
-#endif
-
-// Round near zero value to zero.
-void RoundNearZero(gfx::Transform* transform) {
-  const float kEpsilon = 0.001f;
-  SkMatrix44& matrix = transform->matrix();
-  for (int x = 0; x < 4; ++x) {
-    for (int y = 0; y < 4; ++y) {
-      if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon)
-        matrix.set(x, y, SkFloatToMScalar(0.0f));
-    }
-  }
-}
-
 // TODO(oshima): Transformers should be able to adjust itself
 // when the device scale factor is changed, instead of
 // precalculating the transform using fixed value.
 
-gfx::Transform CreateRotationTransform(aura::Window* root_window,
-                                       const display::Display& display) {
+// Creates rotation transform for |root_window| to |new_rotation|. This will
+// call |CreateRotationTransform()|, the |old_rotation| will implicitly be
+// |display::Display::ROTATE_0|.
+gfx::Transform CreateRootWindowRotationTransform(
+    aura::Window* root_window,
+    const display::Display& display) {
   display::ManagedDisplayInfo info =
       Shell::Get()->display_manager()->GetDisplayInfo(display.id());
-
-// TODO(oshima): Add animation. (crossfade+rotation, or just cross-fade)
-#if defined(OS_WIN)
-  // Windows 8 bots refused to resize the host window, and
-  // updating the transform results in incorrectly resizing
-  // the root window. Don't apply the transform unless
-  // necessary so that unit tests pass on win8 bots.
-  if (info.GetActiveRotation() ==
-      root_window->GetProperty(kRotationPropertyKey)) {
-    return gfx::Transform();
-  }
-  root_window->SetProperty(kRotationPropertyKey, info.GetActiveRotation());
-#endif
-
-  gfx::Transform rotate;
-  // The origin is (0, 0), so the translate width/height must be reduced by
-  // 1 pixel.
-  float one_pixel = 1.0f / display.device_scale_factor();
-  switch (info.GetActiveRotation()) {
-    case display::Display::ROTATE_0:
-      break;
-    case display::Display::ROTATE_90:
-      rotate.Translate(display.bounds().height() - one_pixel, 0);
-      rotate.Rotate(90);
-      break;
-    case display::Display::ROTATE_270:
-      rotate.Translate(0, display.bounds().width() - one_pixel);
-      rotate.Rotate(270);
-      break;
-    case display::Display::ROTATE_180:
-      rotate.Translate(display.bounds().width() - one_pixel,
-                       display.bounds().height() - one_pixel);
-      rotate.Rotate(180);
-      break;
-  }
-
-  RoundNearZero(&rotate);
-  return rotate;
+  return CreateRotationTransform(display::Display::ROTATE_0,
+                                 info.GetActiveRotation(), display);
 }
 
 gfx::Transform CreateMagnifierTransform(aura::Window* root_window) {
@@ -146,7 +90,7 @@
         CreateInsetsAndScaleTransform(host_insets_,
                                       display.device_scale_factor(),
                                       root_window_ui_scale_) *
-        CreateRotationTransform(root, display);
+        CreateRootWindowRotationTransform(root, display);
     if (base::CommandLine::ForCurrentProcess()->HasSwitch(
             switches::kAshEnableMirroredScreen)) {
       // Apply the tranform that flips the screen image horizontally so that
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index f1c51a4..9c6bf5f6 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -4,16 +4,13 @@
 
 #include "ash/rotator/screen_rotation_animator.h"
 
-#include <string>
-#include <utility>
-#include <vector>
-
 #include "ash/ash_switches.h"
 #include "ash/display/window_tree_host_manager.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/rotator/screen_rotation_animation.h"
 #include "ash/rotator/screen_rotation_animator_observer.h"
 #include "ash/shell.h"
+#include "ash/utility/transformer_util.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
@@ -21,9 +18,9 @@
 #include "cc/output/copy_output_request.h"
 #include "cc/output/copy_output_result.h"
 #include "ui/aura/window.h"
+#include "ui/compositor/callback_layer_animation_observer.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_element.h"
-#include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/layer_owner.h"
@@ -77,6 +74,10 @@
       display_id);
 }
 
+aura::Window* GetScreenRotationContainer(aura::Window* root_window) {
+  return root_window->GetChildById(kShellWindowId_ScreenRotationContainer);
+}
+
 // Returns true if the rotation between |initial_rotation| and |new_rotation| is
 // 180 degrees.
 bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
@@ -90,78 +91,70 @@
   return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
 }
 
-// A LayerAnimationObserver that will destroy the contained LayerTreeOwner
-// when notified that a layer animation has ended or was aborted.
-class LayerCleanupObserver : public ui::LayerAnimationObserver {
- public:
-  // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_|
-  // instance and the |animator_| isn't detaching itself as an observer when
-  // being destroyed. However, ideally, when |animator_| is destroying,
-  // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and
-  // delete |this| before |animator_| deleted.
-  explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator);
-  ~LayerCleanupObserver() override;
-
-  // ui::LayerAnimationObserver:
-  void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
-  void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
-  void OnLayerAnimationScheduled(
-      ui::LayerAnimationSequence* sequence) override {}
-
- protected:
-  // ui::LayerAnimationObserver:
-  bool RequiresNotificationWhenAnimatorDestroyed() const override {
-    return true;
-  }
-  void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
-  void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
-
- private:
-  base::WeakPtr<ScreenRotationAnimator> animator_;
-
-  // The LayerAnimationSequence that |this| has been attached to. Defaults to
-  // nullptr.
-  ui::LayerAnimationSequence* sequence_;
-
-  DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver);
-};
-
-LayerCleanupObserver::LayerCleanupObserver(
-    base::WeakPtr<ScreenRotationAnimator> animator)
-    : animator_(animator), sequence_(nullptr) {}
-
-LayerCleanupObserver::~LayerCleanupObserver() {
-  // We must eplicitly detach from |sequence_| because we return true from
-  // RequiresNotificationWhenAnimatorDestroyed.
-  if (sequence_)
-    sequence_->RemoveObserver(this);
+void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
+  // Add the cloned/copied layer tree into the root, so it will be rendered.
+  root_window->layer()->Add(layer);
+  root_window->layer()->StackAtTop(layer);
 }
 
-void LayerCleanupObserver::OnLayerAnimationEnded(
-    ui::LayerAnimationSequence* sequence) {
-  if (animator_)
-    animator_->ProcessAnimationQueue();
-
-  delete this;
+void AddLayerBelowWindowLayer(aura::Window* root_window,
+                              ui::Layer* top_layer,
+                              ui::Layer* layer) {
+  // Add the cloned/copied layer tree into the root, so it will be rendered.
+  root_window->layer()->Add(layer);
+  root_window->layer()->StackBelow(layer, top_layer);
 }
 
-void LayerCleanupObserver::OnLayerAnimationAborted(
-    ui::LayerAnimationSequence* sequence) {
-  if (animator_)
-    animator_->ProcessAnimationQueue();
-
-  delete this;
+// The Callback will be invoked when all animation sequences have
+// finished. |observer| will be destroyed after invoking the Callback if it
+// returns true.
+bool AnimationEndedCallback(
+    base::WeakPtr<ScreenRotationAnimator> animator,
+    const ui::CallbackLayerAnimationObserver& observer) {
+  if (animator)
+    animator->ProcessAnimationQueue();
+  return true;
 }
 
-void LayerCleanupObserver::OnAttachedToSequence(
-    ui::LayerAnimationSequence* sequence) {
-  sequence_ = sequence;
+// Creates a Transform for the old layer in screen rotation animation.
+gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
+    display::Display::Rotation old_rotation,
+    display::Display::Rotation new_rotation,
+    const display::Display& display) {
+  gfx::Transform inverse;
+  CHECK(CreateRotationTransform(old_rotation, new_rotation, display)
+            .GetInverse(&inverse));
+  return inverse;
 }
 
-void LayerCleanupObserver::OnDetachedFromSequence(
-    ui::LayerAnimationSequence* sequence) {
-  DCHECK_EQ(sequence, sequence_);
-  sequence_ = nullptr;
+// The |request_id| changed since last copy request, which means a
+// new rotation stated, we need to ignore this copy result.
+bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
+  DCHECK(request_id <= current_request_id);
+  return request_id < current_request_id;
+}
+
+// In the following cases, abort rotation:
+// 1) if the display was removed,
+// 2) the copy request has been canceled or failed. It would fail if,
+// for examples: a) The layer is removed from the compositor and destroye
+// before committing the request to the compositor. b) The compositor is
+// shutdown.
+bool AbortRotation(int64_t display_id, cc::CopyOutputResult* result) {
+  return !IsDisplayIdValid(display_id) || result->IsEmpty();
+}
+
+// Creates a black mask layer and returns the |layer_owner|.
+std::unique_ptr<ui::LayerOwner> CreateBlackMaskLayerOwner(
+    const gfx::Rect& rect) {
+  std::unique_ptr<ui::Layer> black_mask_layer =
+      base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR);
+  black_mask_layer->SetBounds(rect);
+  black_mask_layer->SetColor(SK_ColorBLACK);
+  std::unique_ptr<ui::LayerOwner> black_mask_layer_owner =
+      base::MakeUnique<ui::LayerOwner>();
+  black_mask_layer_owner->SetLayer(std::move(black_mask_layer));
+  return black_mask_layer_owner;
 }
 
 class ScreenRotationAnimationMetricsReporter
@@ -187,11 +180,17 @@
       metrics_reporter_(
           base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
       disable_animation_timers_for_test_(false),
+      has_switch_ash_enable_smooth_screen_rotation_(
+          base::CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kAshEnableSmoothScreenRotation)),
+      root_window_(GetRootWindow(display_id_)),
+      screen_rotation_container_layer_(
+          GetScreenRotationContainer(root_window_)->layer()),
       weak_factory_(this) {}
 
 ScreenRotationAnimator::~ScreenRotationAnimator() {
-  // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from
-  // calling a method on the |animator_|.
+  // To prevent a call to |AnimationEndedCallback()| from calling a method on
+  // the |animator_|.
   weak_factory_.InvalidateWeakPtrs();
 
   // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
@@ -203,133 +202,175 @@
 
 void ScreenRotationAnimator::StartRotationAnimation(
     std::unique_ptr<ScreenRotationRequest> rotation_request) {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAshEnableSmoothScreenRotation)) {
-    RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request));
-  } else {
-    CreateOldLayerTree();
-    AnimateRotation(std::move(rotation_request));
-  }
-}
-
-void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation(
-    std::unique_ptr<ScreenRotationRequest> rotation_request) {
-  std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
-      cc::CopyOutputRequest::CreateRequest(
-          CreateAfterCopyCallback(std::move(rotation_request)));
-  ui::Layer* layer = GetRootWindow(display_id_)->layer();
-  copy_output_request->set_area(gfx::Rect(layer->size()));
-  layer->RequestCopyOfOutput(std::move(copy_output_request));
-
-  screen_rotation_state_ = COPY_REQUESTED;
-}
-
-ScreenRotationAnimator::CopyCallback
-ScreenRotationAnimator::CreateAfterCopyCallback(
-    std::unique_ptr<ScreenRotationRequest> rotation_request) {
-  return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation,
-                    weak_factory_.GetWeakPtr(),
-                    base::Passed(&rotation_request));
-}
-
-void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation(
-    std::unique_ptr<ScreenRotationRequest> rotation_request,
-    std::unique_ptr<cc::CopyOutputResult> result) {
-  DCHECK(rotation_request->id <= rotation_request_id_);
-  // The |rotation_request_id_| changed since last copy request, which means a
-  // new rotation stated, we need to ignore this copy result.
-  if (rotation_request->id < rotation_request_id_)
-    return;
-
-  // In the following cases, abort rotation:
-  // 1) if the display was removed,
-  // 2) the copy request has been canceled or failed. It would fail if,
-  // for examples: a) The layer is removed from the compositor and destroye
-  // before committing the request to the compositor. b) The compositor is
-  // shutdown.
-  if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) {
+  const display::Display::Rotation current_rotation =
+      GetCurrentScreenRotation(display_id_);
+  if (current_rotation == rotation_request->new_rotation) {
+    // We need to call |ProcessAnimationQueue()| to prepare for next rotation
+    // request.
     ProcessAnimationQueue();
     return;
   }
 
-  CopyOldLayerTree(std::move(result));
+  rotation_request->old_rotation = current_rotation;
+  if (has_switch_ash_enable_smooth_screen_rotation_) {
+    std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
+        cc::CopyOutputRequest::CreateRequest(
+            CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request)));
+    RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
+    screen_rotation_state_ = COPY_REQUESTED;
+  } else {
+    StartSlowAnimation(std::move(rotation_request));
+  }
+}
+
+void ScreenRotationAnimator::StartSlowAnimation(
+    std::unique_ptr<ScreenRotationRequest> rotation_request) {
+  CreateOldLayerTreeForSlowAnimation();
+  SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
+              rotation_request->source);
   AnimateRotation(std::move(rotation_request));
 }
 
-void ScreenRotationAnimator::CreateOldLayerTree() {
-  old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_));
+void ScreenRotationAnimator::SetRotation(
+    display::Display::Rotation old_rotation,
+    display::Display::Rotation new_rotation,
+    display::Display::RotationSource source) {
+  Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation,
+                                                      source);
+  const display::Display display =
+      Shell::Get()->display_manager()->GetDisplayForId(display_id_);
+  old_layer_tree_owner_->root()->SetTransform(
+      CreateScreenRotationOldLayerTransformForDisplay(old_rotation,
+                                                      new_rotation, display));
 }
 
-void ScreenRotationAnimator::CopyOldLayerTree(
+void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
+    std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
+  copy_output_request->set_area(
+      gfx::Rect(screen_rotation_container_layer_->size()));
+  screen_rotation_container_layer_->RequestCopyOfOutput(
+      std::move(copy_output_request));
+}
+
+ScreenRotationAnimator::CopyCallback
+ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
+    std::unique_ptr<ScreenRotationRequest> rotation_request) {
+  return base::Bind(&ScreenRotationAnimator::
+                        OnScreenRotationContainerLayerCopiedBeforeRotation,
+                    weak_factory_.GetWeakPtr(),
+                    base::Passed(&rotation_request));
+}
+
+ScreenRotationAnimator::CopyCallback
+ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
+    std::unique_ptr<ScreenRotationRequest> rotation_request) {
+  return base::Bind(&ScreenRotationAnimator::
+                        OnScreenRotationContainerLayerCopiedAfterRotation,
+                    weak_factory_.GetWeakPtr(),
+                    base::Passed(&rotation_request));
+}
+
+void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
+    std::unique_ptr<ScreenRotationRequest> rotation_request,
+    std::unique_ptr<cc::CopyOutputResult> result) {
+  if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
+    return;
+  if (AbortRotation(display_id_, result.get())) {
+    ProcessAnimationQueue();
+    return;
+  }
+
+  old_layer_tree_owner_ = CopyLayerTree(std::move(result));
+  AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
+  SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
+              rotation_request->source);
+  std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
+      cc::CopyOutputRequest::CreateRequest(
+          CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
+  RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
+}
+
+void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
+    std::unique_ptr<ScreenRotationRequest> rotation_request,
+    std::unique_ptr<cc::CopyOutputResult> result) {
+  if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
+    return;
+  if (AbortRotation(display_id_, result.get())) {
+    ProcessAnimationQueue();
+    return;
+  }
+
+  new_layer_tree_owner_ = CopyLayerTree(std::move(result));
+  AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(),
+                           new_layer_tree_owner_->root());
+  AnimateRotation(std::move(rotation_request));
+}
+
+void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
+  old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
+  // |screen_rotation_container_layer_| needs update after |RecreateLayers()|.
+  screen_rotation_container_layer_ =
+      GetScreenRotationContainer(root_window_)->layer();
+  AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
+}
+
+std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
     std::unique_ptr<cc::CopyOutputResult> result) {
   cc::TextureMailbox texture_mailbox;
   std::unique_ptr<cc::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
 
-  aura::Window* root_window = GetRootWindow(display_id_);
-  gfx::Rect rect(root_window->layer()->size());
+  const gfx::Rect rect(screen_rotation_container_layer_->size());
   std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
   copy_layer->SetBounds(rect);
   copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
                                 rect.size());
-  old_layer_tree_owner_ =
-      base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
+  return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
 }
 
 void ScreenRotationAnimator::AnimateRotation(
     std::unique_ptr<ScreenRotationRequest> rotation_request) {
   screen_rotation_state_ = ROTATING;
-
-  aura::Window* root_window = GetRootWindow(display_id_);
-  std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer(
-      new LayerCleanupObserver(weak_factory_.GetWeakPtr()));
-  ui::Layer* old_root_layer = old_layer_tree_owner_->root();
-  old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree");
-  // Add the cloned layer tree in to the root, so it will be rendered.
-  root_window->layer()->Add(old_root_layer);
-  root_window->layer()->StackAtTop(old_root_layer);
-
-  const gfx::Rect original_screen_bounds = root_window->GetTargetBounds();
-
-  const int rotation_factor = GetRotationFactor(
-      GetCurrentScreenRotation(display_id_), rotation_request->new_rotation);
-
+  const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
+                                                rotation_request->new_rotation);
   const int old_layer_initial_rotation_degrees = GetInitialDegrees(
-      GetCurrentScreenRotation(display_id_), rotation_request->new_rotation);
-
+      rotation_request->old_rotation, rotation_request->new_rotation);
   const base::TimeDelta duration =
       base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
-
   const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
-
-  Shell::Get()->display_manager()->SetDisplayRotation(
-      display_id_, rotation_request->new_rotation, rotation_request->source);
-
-  const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds();
+  const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds();
   const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
                                       rotated_screen_bounds.height() / 2);
 
-  ui::Layer* screen_rotation_container_layer =
-      root_window->GetChildById(kShellWindowId_ScreenRotationContainer)
-          ->layer();
-  std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation =
+  ui::Layer* new_root_layer;
+  if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) {
+    new_root_layer = new_layer_tree_owner_->root();
+    // Add a black mask layer on top of |screen_rotation_container_layer_|.
+    black_mask_layer_owner_ = CreateBlackMaskLayerOwner(
+        gfx::Rect(screen_rotation_container_layer_->size()));
+    AddLayerBelowWindowLayer(root_window_, new_root_layer,
+                             black_mask_layer_owner_->layer());
+  } else {
+    new_root_layer = screen_rotation_container_layer_;
+  }
+
+  std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
       base::MakeUnique<ScreenRotationAnimation>(
-          screen_rotation_container_layer, kRotationDegrees * rotation_factor,
-          0 /* end_degrees */, screen_rotation_container_layer->opacity(),
-          screen_rotation_container_layer->opacity() /* target_opacity */,
-          pivot, duration, tween_type);
+          new_root_layer, kRotationDegrees * rotation_factor,
+          0 /* end_degrees */, new_root_layer->opacity(),
+          new_root_layer->opacity() /* target_opacity */, pivot, duration,
+          tween_type);
 
-  ui::LayerAnimator* current_layer_animator =
-      screen_rotation_container_layer->GetAnimator();
-  current_layer_animator->set_preemption_strategy(
+  ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
+  new_layer_animator->set_preemption_strategy(
       ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
-  std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence =
+  std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
       base::MakeUnique<ui::LayerAnimationSequence>(
-          std::move(current_layer_screen_rotation));
-  current_layer_animator->StartAnimation(
-      current_layer_animation_sequence.release());
+          std::move(new_layer_screen_rotation));
 
+  ui::Layer* old_root_layer = old_layer_tree_owner_->root();
+  const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
   // The old layer will also be transformed into the new orientation. We will
   // translate it so that the old layer's center point aligns with the new
   // orientation's center point and use that center point as the pivot for the
@@ -354,31 +395,41 @@
   std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
       base::MakeUnique<ui::LayerAnimationSequence>(
           std::move(old_layer_screen_rotation));
-  // Add an observer so that the cloned layers can be cleaned up with the
-  // animation completes/aborts.
-  old_layer_animation_sequence->AddObserver(
-      old_layer_cleanup_observer.release());
+
   // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
   // control the animation.
-  if (disable_animation_timers_for_test_)
+  if (disable_animation_timers_for_test_) {
+    if (new_layer_tree_owner_)
+      new_layer_animator->set_disable_timer_for_test(true);
     old_layer_animator->set_disable_timer_for_test(true);
+  }
   old_layer_animation_sequence->SetAnimationMetricsReporter(
       metrics_reporter_.get());
-  old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
 
-  rotation_request.reset();
+  // Add an observer so that the cloned/copied layers can be cleaned up with the
+  // animation completes/aborts.
+  ui::CallbackLayerAnimationObserver* observer =
+      new ui::CallbackLayerAnimationObserver(
+          base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
+  if (new_layer_tree_owner_)
+    new_layer_animator->AddObserver(observer);
+  new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
+  old_layer_animator->AddObserver(observer);
+  old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
+  observer->SetActive();
 }
 
 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
                                     display::Display::RotationSource source) {
-  if (GetCurrentScreenRotation(display_id_) == new_rotation)
-    return;
-
+  // |rotation_request_id_| is used to skip stale requests. Before the layer
+  // CopyOutputResult callback called, there could have new rotation request.
+  // Increases |rotation_request_id_| for each new request and in the callback,
+  // we compare the |rotation_request.id| and |rotation_request_id_| to
+  // determine the stale status.
   rotation_request_id_++;
   std::unique_ptr<ScreenRotationRequest> rotation_request =
       base::MakeUnique<ScreenRotationRequest>(rotation_request_id_,
                                               new_rotation, source);
-
   switch (screen_rotation_state_) {
     case IDLE:
     case COPY_REQUESTED:
@@ -387,8 +438,7 @@
     case ROTATING:
       last_pending_request_ = std::move(rotation_request);
       // The pending request will be processed when the
-      // OnLayerAnimation(Ended|Aborted) methods should be called after
-      // |StopAnimating()|.
+      // |AnimationEndedCallback()| should be called after |StopAnimating()|.
       StopAnimating();
       break;
   }
@@ -406,33 +456,30 @@
 
 void ScreenRotationAnimator::ProcessAnimationQueue() {
   screen_rotation_state_ = IDLE;
+  if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
+    root_window_->layer()->Remove(black_mask_layer_owner_->layer());
   old_layer_tree_owner_.reset();
+  new_layer_tree_owner_.reset();
+  black_mask_layer_owner_.reset();
   if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
-    display::Display::Rotation new_rotation =
-        last_pending_request_->new_rotation;
-    display::Display::RotationSource source = last_pending_request_->source;
-    last_pending_request_.reset();
-    Rotate(new_rotation, source);
+    StartRotationAnimation(std::move(last_pending_request_));
     return;
   }
 
+  // This is only used in test to notify animator observer.
   for (auto& observer : screen_rotation_animator_observers_)
     observer.OnScreenRotationAnimationFinished(this);
 }
 
-void ScreenRotationAnimator::set_disable_animation_timers_for_test(
-    bool disable_timers) {
-  disable_animation_timers_for_test_ = disable_timers;
-}
-
 void ScreenRotationAnimator::StopAnimating() {
-  GetRootWindow(display_id_)
-      ->GetChildById(kShellWindowId_ScreenRotationContainer)
-      ->layer()
-      ->GetAnimator()
-      ->StopAnimating();
+  // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
+  // the rotation request comes before the copy request finished.
   if (old_layer_tree_owner_)
     old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
+  if (new_layer_tree_owner_)
+    new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
+  if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
+    root_window_->layer()->Remove(black_mask_layer_owner_->layer());
 }
 
 }  // namespace ash
diff --git a/ash/rotator/screen_rotation_animator.h b/ash/rotator/screen_rotation_animator.h
index ce77673..1a47928 100644
--- a/ash/rotator/screen_rotation_animator.h
+++ b/ash/rotator/screen_rotation_animator.h
@@ -14,13 +14,19 @@
 #include "base/observer_list.h"
 #include "ui/display/display.h"
 
+namespace aura {
+class Window;
+}  // namesapce aura
+
 namespace cc {
+class CopyOutputRequest;
 class CopyOutputResult;
 }  // namespace cc
 
 namespace ui {
 class AnimationMetricsReporter;
 class Layer;
+class LayerOwner;
 class LayerTreeOwner;
 }  // namespace ui
 
@@ -69,13 +75,19 @@
                           display::Display::RotationSource from_source)
         : id(id), new_rotation(to_rotation), source(from_source) {}
     int64_t id;
+    display::Display::Rotation old_rotation;
     display::Display::Rotation new_rotation;
     display::Display::RotationSource source;
   };
 
   // This function can be overridden in unit test to test removing external
   // display.
-  virtual CopyCallback CreateAfterCopyCallback(
+  virtual CopyCallback CreateAfterCopyCallbackBeforeRotation(
+      std::unique_ptr<ScreenRotationRequest> rotation_request);
+
+  // This function can be overridden in unit test to test removing external
+  // display.
+  virtual CopyCallback CreateAfterCopyCallbackAfterRotation(
       std::unique_ptr<ScreenRotationRequest> rotation_request);
 
  private:
@@ -84,20 +96,44 @@
   void StartRotationAnimation(
       std::unique_ptr<ScreenRotationRequest> rotation_request);
 
-  // This is an asynchronous call to request copy output of root layer.
-  void RequestCopyRootLayerAndAnimateRotation(
+  // The code path to start "slow animation". The difference between the "slow"
+  // and "smooth" animation, is that "slow animation" will recreate all the
+  // layers before rotation and use the recreated layers and rotated layers for
+  // cross-fading animation. This is slow by adding multiple layer animation
+  // elements. The "smooth animation" copies the layer output before and after
+  // rotation, and use them for cross-fading animation. The output copy layer
+  // flatten the layer hierarchy and makes the animation smooth.
+  void StartSlowAnimation(
       std::unique_ptr<ScreenRotationRequest> rotation_request);
 
-  // The callback in |RequestCopyRootLayerAndAnimateRotation()|.
-  void OnRootLayerCopiedBeforeRotation(
+  // A wrapper to call |display_manager| to set screen rotation and rotate the
+  // |old_layer_tree| to the |old_rotation|.
+  void SetRotation(display::Display::Rotation old_rotation,
+                   display::Display::Rotation new_rotation,
+                   display::Display::RotationSource source);
+
+  // This is an asynchronous call to request copy output of root layer.
+  void RequestCopyScreenRotationContainerLayer(
+      std::unique_ptr<cc::CopyOutputRequest> copy_output_request);
+
+  // The callback in |RequestCopyScreenRotationContainerLayer()| before screen
+  // rotation.
+  void OnScreenRotationContainerLayerCopiedBeforeRotation(
       std::unique_ptr<ScreenRotationRequest> rotation_request,
       std::unique_ptr<cc::CopyOutputResult> result);
 
-  // Recreates all |root_window| layers.
-  void CreateOldLayerTree();
+  // The callback in |RequestCopyScreenRotationContainerLayer()| after screen
+  // rotation.
+  void OnScreenRotationContainerLayerCopiedAfterRotation(
+      std::unique_ptr<ScreenRotationRequest> rotation_request,
+      std::unique_ptr<cc::CopyOutputResult> result);
 
-  // Requests a copy of |root_window| root layer output.
-  void CopyOldLayerTree(std::unique_ptr<cc::CopyOutputResult> result);
+  // Recreates all |root_window| layers and their layer tree owner.
+  void CreateOldLayerTreeForSlowAnimation();
+
+  // Creates a new layer and its layer tree owner from |CopyOutputResult|.
+  std::unique_ptr<ui::LayerTreeOwner> CopyLayerTree(
+      std::unique_ptr<cc::CopyOutputResult> result);
 
   // Note: Only call this function when the |old_layer_tree_owner_| is set up
   // properly.
@@ -108,7 +144,9 @@
   // |rotation_degrees| arc.
   void AnimateRotation(std::unique_ptr<ScreenRotationRequest> rotation_request);
 
-  void set_disable_animation_timers_for_test(bool disable_timers);
+  void set_disable_animation_timers_for_test(bool disable_timers) {
+    disable_animation_timers_for_test_ = disable_timers;
+  }
 
   void StopAnimating();
 
@@ -135,7 +173,12 @@
   base::ObserverList<ScreenRotationAnimatorObserver>
       screen_rotation_animator_observers_;
   std::unique_ptr<ui::LayerTreeOwner> old_layer_tree_owner_;
+  std::unique_ptr<ui::LayerTreeOwner> new_layer_tree_owner_;
+  std::unique_ptr<ui::LayerOwner> black_mask_layer_owner_;
   std::unique_ptr<ScreenRotationRequest> last_pending_request_;
+  bool has_switch_ash_enable_smooth_screen_rotation_;
+  aura::Window* root_window_;
+  ui::Layer* screen_rotation_container_layer_;
   base::WeakPtrFactory<ScreenRotationAnimator> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimator);
diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc
index 09e64d3..19de9ce 100644
--- a/ash/rotator/screen_rotation_animator_unittest.cc
+++ b/ash/rotator/screen_rotation_animator_unittest.cc
@@ -5,6 +5,7 @@
 #include "ash/rotator/screen_rotation_animator.h"
 
 #include "ash/ash_switches.h"
+#include "ash/display/window_tree_host_manager.h"
 #include "ash/public/cpp/config.h"
 #include "ash/rotator/screen_rotation_animator_observer.h"
 #include "ash/rotator/test/screen_rotation_animator_test_api.h"
@@ -59,53 +60,128 @@
 
 class TestScreenRotationAnimator : public ScreenRotationAnimator {
  public:
-  TestScreenRotationAnimator(int64_t display_id, const base::Closure& callback);
+  TestScreenRotationAnimator(int64_t display_id,
+                             const base::Closure& before_callback,
+                             const base::Closure& after_callback);
   ~TestScreenRotationAnimator() override {}
 
  private:
-  CopyCallback CreateAfterCopyCallback(
+  CopyCallback CreateAfterCopyCallbackBeforeRotation(
+      std::unique_ptr<ScreenRotationRequest> rotation_request) override;
+  CopyCallback CreateAfterCopyCallbackAfterRotation(
       std::unique_ptr<ScreenRotationRequest> rotation_request) override;
 
   void IntersectBefore(CopyCallback next_callback,
                        std::unique_ptr<cc::CopyOutputResult> result);
+  void IntersectAfter(CopyCallback next_callback,
+                      std::unique_ptr<cc::CopyOutputResult> result);
 
-  base::Closure intersect_callback_;
+  base::Closure intersect_before_callback_;
+  base::Closure intersect_after_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TestScreenRotationAnimator);
 };
 
 TestScreenRotationAnimator::TestScreenRotationAnimator(
     int64_t display_id,
-    const base::Closure& callback)
-    : ScreenRotationAnimator(display_id), intersect_callback_(callback) {}
+    const base::Closure& before_callback,
+    const base::Closure& after_callback)
+    : ScreenRotationAnimator(display_id),
+      intersect_before_callback_(before_callback),
+      intersect_after_callback_(after_callback) {}
 
 ScreenRotationAnimator::CopyCallback
-TestScreenRotationAnimator::CreateAfterCopyCallback(
+TestScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
     std::unique_ptr<ScreenRotationRequest> rotation_request) {
-  CopyCallback next_callback = ScreenRotationAnimator::CreateAfterCopyCallback(
-      std::move(rotation_request));
+  CopyCallback next_callback =
+      ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
+          std::move(rotation_request));
   return base::Bind(&TestScreenRotationAnimator::IntersectBefore,
                     base::Unretained(this), next_callback);
 }
 
+ScreenRotationAnimator::CopyCallback
+TestScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
+    std::unique_ptr<ScreenRotationRequest> rotation_request) {
+  CopyCallback next_callback =
+      ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
+          std::move(rotation_request));
+  return base::Bind(&TestScreenRotationAnimator::IntersectAfter,
+                    base::Unretained(this), next_callback);
+}
+
 void TestScreenRotationAnimator::IntersectBefore(
     CopyCallback next_callback,
     std::unique_ptr<cc::CopyOutputResult> result) {
-  intersect_callback_.Run();
+  intersect_before_callback_.Run();
+  next_callback.Run(std::move(result));
+}
+
+void TestScreenRotationAnimator::IntersectAfter(
+    CopyCallback next_callback,
+    std::unique_ptr<cc::CopyOutputResult> result) {
+  intersect_after_callback_.Run();
   next_callback.Run(std::move(result));
 }
 
 }  // namespace
 
-class ScreenRotationAnimatorTest : public test::AshTestBase {
+class ScreenRotationAnimatorSlowAnimationTest : public test::AshTestBase {
  public:
-  ScreenRotationAnimatorTest() {}
-  ~ScreenRotationAnimatorTest() override {}
+  ScreenRotationAnimatorSlowAnimationTest() {}
+  ~ScreenRotationAnimatorSlowAnimationTest() override {}
+
+  // AshTestBase:
+  void SetUp() override;
+
+ protected:
+  int64_t display_id() const { return display_.id(); }
+
+  ScreenRotationAnimator* animator() { return animator_.get(); }
+
+  test::ScreenRotationAnimatorTestApi* test_api() { return test_api_.get(); }
+
+ private:
+  display::Display display_;
+
+  std::unique_ptr<ScreenRotationAnimator> animator_;
+
+  std::unique_ptr<test::ScreenRotationAnimatorTestApi> test_api_;
+
+  std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimatorSlowAnimationTest);
+};
+
+void ScreenRotationAnimatorSlowAnimationTest::SetUp() {
+  AshTestBase::SetUp();
+
+  display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  animator_ = base::MakeUnique<ScreenRotationAnimator>(display_.id());
+  test_api_ =
+      base::MakeUnique<test::ScreenRotationAnimatorTestApi>(animator_.get());
+  test_api()->DisableAnimationTimers();
+  non_zero_duration_mode_ =
+      base::MakeUnique<ui::ScopedAnimationDurationScaleMode>(
+          ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
+}
+
+class ScreenRotationAnimatorSmoothAnimationTest : public test::AshTestBase {
+ public:
+  ScreenRotationAnimatorSmoothAnimationTest() {}
+  ~ScreenRotationAnimatorSmoothAnimationTest() override {}
 
   // AshTestBase:
   void SetUp() override;
 
   void RemoveSecondaryDisplay(const std::string& specs);
+  void QuitWaitForCopyCallback();
 
  protected:
   int64_t display_id() const { return display_.id(); }
@@ -113,7 +189,8 @@
   TestScreenRotationAnimator* animator() { return animator_.get(); }
 
   void SetScreenRotationAnimator(int64_t display_id,
-                                 const base::Closure& callback);
+                                 const base::Closure& before_callback,
+                                 const base::Closure& after_callback);
 
   test::ScreenRotationAnimatorTestApi* test_api() { return test_api_.get(); }
 
@@ -130,41 +207,56 @@
 
   std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimatorTest);
+  DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimatorSmoothAnimationTest);
 };
 
-void ScreenRotationAnimatorTest::RemoveSecondaryDisplay(
+void ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay(
     const std::string& specs) {
   UpdateDisplay(specs);
+  QuitWaitForCopyCallback();
+}
+
+void ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback() {
   run_loop_->QuitWhenIdle();
 }
 
-void ScreenRotationAnimatorTest::SetUp() {
+void ScreenRotationAnimatorSmoothAnimationTest::SetUp() {
   AshTestBase::SetUp();
 
   display_ = display::Screen::GetScreen()->GetPrimaryDisplay();
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kAshEnableSmoothScreenRotation);
   run_loop_ = base::MakeUnique<base::RunLoop>();
-  SetScreenRotationAnimator(display_.id(), run_loop_->QuitWhenIdleClosure());
+  SetScreenRotationAnimator(display_.id(), run_loop_->QuitWhenIdleClosure(),
+                            run_loop_->QuitWhenIdleClosure());
   non_zero_duration_mode_ =
       base::MakeUnique<ui::ScopedAnimationDurationScaleMode>(
           ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
 }
 
-void ScreenRotationAnimatorTest::SetScreenRotationAnimator(
+void ScreenRotationAnimatorSmoothAnimationTest::SetScreenRotationAnimator(
     int64_t display_id,
-    const base::Closure& callback) {
-  animator_ =
-      base::MakeUnique<TestScreenRotationAnimator>(display_id, callback);
+    const base::Closure& before_callback,
+    const base::Closure& after_callback) {
+  animator_ = base::MakeUnique<TestScreenRotationAnimator>(
+      display_id, before_callback, after_callback);
   test_api_ =
       base::MakeUnique<test::ScreenRotationAnimatorTestApi>(animator_.get());
   test_api()->DisableAnimationTimers();
 }
 
-void ScreenRotationAnimatorTest::WaitForCopyCallback() {
+void ScreenRotationAnimatorSmoothAnimationTest::WaitForCopyCallback() {
+  run_loop_.reset(new base::RunLoop());
   run_loop_->Run();
 }
 
-TEST_F(ScreenRotationAnimatorTest, ShouldNotifyObserver) {
+TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldNotifyObserver) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -187,7 +279,7 @@
   animator()->RemoveScreenRotationAnimatorObserver(&observer);
 }
 
-TEST_F(ScreenRotationAnimatorTest, ShouldNotifyObserverOnce) {
+TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldNotifyObserverOnce) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -214,7 +306,7 @@
   animator()->RemoveScreenRotationAnimatorObserver(&observer);
 }
 
-TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotation) {
+TEST_F(ScreenRotationAnimatorSlowAnimationTest, RotatesToDifferentRotation) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -231,7 +323,8 @@
   EXPECT_FALSE(test_api()->HasActiveAnimations());
 }
 
-TEST_F(ScreenRotationAnimatorTest, ShouldNotRotateTheSameRotation) {
+TEST_F(ScreenRotationAnimatorSlowAnimationTest,
+       ShouldNotRotateTheSameRotation) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -248,7 +341,7 @@
 // Simulates the situation that if there is a new rotation request during
 // animation, it should stop the animation immediately and add the new rotation
 // request to the |last_pending_request_|.
-TEST_F(ScreenRotationAnimatorTest, RotatesDuringRotation) {
+TEST_F(ScreenRotationAnimatorSlowAnimationTest, RotatesDuringRotation) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -270,7 +363,7 @@
 
 // If there are multiple requests queued during animation, it should process the
 // last request and finish the rotation animation.
-TEST_F(ScreenRotationAnimatorTest, ShouldCompleteAnimations) {
+TEST_F(ScreenRotationAnimatorSlowAnimationTest, ShouldCompleteAnimations) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -297,7 +390,8 @@
 }
 
 // Test enable smooth screen rotation code path.
-TEST_F(ScreenRotationAnimatorTest, RotatesToDifferentRotationWithCopyCallback) {
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       RotatesToDifferentRotationWithCopyCallback) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -305,9 +399,12 @@
     return;
   }
 
+  SetScreenRotationAnimator(
+      display_manager()->GetDisplayAt(0).id(), run_loop_->QuitWhenIdleClosure(),
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
+          base::Unretained(this)));
   SetDisplayRotation(display_id(), display::Display::ROTATE_0);
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kAshEnableSmoothScreenRotation);
   animator()->Rotate(display::Display::ROTATE_90,
                      display::Display::RotationSource::ROTATION_SOURCE_USER);
   WaitForCopyCallback();
@@ -317,8 +414,10 @@
   EXPECT_FALSE(test_api()->HasActiveAnimations());
 }
 
-// If the external display is removed, it should not crash.
-TEST_F(ScreenRotationAnimatorTest, RemoveSecondaryDisplayAfterCopyCallback) {
+// If the external secondary display is removed before the first copy request
+// callback called, it should not crash.
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       RemoveExternalSecondaryDisplayBeforeFirstCopyCallback) {
   // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
   if (Shell::GetAshConfig() == Config::MASH) {
     ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
@@ -333,10 +432,10 @@
       display_manager()->GetDisplayAt(0).id();
   SetScreenRotationAnimator(
       display_manager()->GetDisplayAt(1).id(),
-      base::Bind(&ScreenRotationAnimatorTest::RemoveSecondaryDisplay,
-                 base::Unretained(this), "640x480"));
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kAshEnableSmoothScreenRotation);
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
+          base::Unretained(this), "640x480"),
+      run_loop_->QuitWhenIdleClosure());
   SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
                      display::Display::ROTATE_0);
   animator()->Rotate(display::Display::ROTATE_90,
@@ -346,4 +445,99 @@
   EXPECT_EQ(primary_display_id, display_manager()->GetDisplayAt(0).id());
 }
 
+// If the external primary display is removed before the first copy request
+// callback called, it should not crash.
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       RemoveExternalPrimaryDisplayBeforeFirstCopyCallback) {
+  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  UpdateDisplay("640x480,800x600");
+  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
+
+  Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
+      display_manager()->GetDisplayAt(1).id());
+  const unsigned int secondary_display_id =
+      display_manager()->GetDisplayAt(0).id();
+  SetScreenRotationAnimator(
+      display_manager()->GetDisplayAt(1).id(),
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
+          base::Unretained(this), "640x480"),
+      run_loop_->QuitWhenIdleClosure());
+  SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
+                     display::Display::ROTATE_0);
+  animator()->Rotate(display::Display::ROTATE_90,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+  WaitForCopyCallback();
+  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
+  EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
+}
+
+// If the external secondary display is removed before the second copy request
+// callback called, it should not crash.
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       RemoveExternalSecondaryDisplayBeforeSecondCopyCallback) {
+  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  UpdateDisplay("640x480,800x600");
+  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
+
+  const unsigned int primary_display_id =
+      display_manager()->GetDisplayAt(0).id();
+  SetScreenRotationAnimator(
+      display_manager()->GetDisplayAt(1).id(), run_loop_->QuitWhenIdleClosure(),
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
+          base::Unretained(this), "640x480"));
+  SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
+                     display::Display::ROTATE_0);
+  animator()->Rotate(display::Display::ROTATE_90,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+  WaitForCopyCallback();
+  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
+  EXPECT_EQ(primary_display_id, display_manager()->GetDisplayAt(0).id());
+}
+
+// If the external primary display is removed before the second copy request
+// callback called, it should not crash.
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       RemoveExternalPrimaryDisplayBeforeSecondCopyCallback) {
+  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  UpdateDisplay("640x480,800x600");
+  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
+
+  Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(
+      display_manager()->GetDisplayAt(1).id());
+  const unsigned int secondary_display_id =
+      display_manager()->GetDisplayAt(0).id();
+  SetScreenRotationAnimator(
+      display_manager()->GetDisplayAt(1).id(), run_loop_->QuitWhenIdleClosure(),
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::RemoveSecondaryDisplay,
+          base::Unretained(this), "640x480"));
+  SetDisplayRotation(display_manager()->GetDisplayAt(1).id(),
+                     display::Display::ROTATE_0);
+  animator()->Rotate(display::Display::ROTATE_90,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+  WaitForCopyCallback();
+  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
+  EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
+}
+
 }  // namespace ash
diff --git a/ash/rotator/test/screen_rotation_animator_test_api.cc b/ash/rotator/test/screen_rotation_animator_test_api.cc
index 0c26e47..0d3d679 100644
--- a/ash/rotator/test/screen_rotation_animator_test_api.cc
+++ b/ash/rotator/test/screen_rotation_animator_test_api.cc
@@ -28,6 +28,10 @@
     animators.insert(animators.end(),
                      animator_->old_layer_tree_owner_->root()->GetAnimator());
   }
+  if (animator_->new_layer_tree_owner_) {
+    animators.insert(animators.end(),
+                     animator_->new_layer_tree_owner_->root()->GetAnimator());
+  }
   return animators;
 }
 
diff --git a/ash/system/audio/volume_view.cc b/ash/system/audio/volume_view.cc
index 7fdf571..efbdd2f 100644
--- a/ash/system/audio/volume_view.cc
+++ b/ash/system/audio/volume_view.cc
@@ -131,29 +131,6 @@
   tri_view_->AddView(TriView::Container::CENTER, slider_);
 
   set_background(views::Background::CreateSolidBackground(kBackgroundColor));
-
-  if (!is_default_view_) {
-    tri_view_->SetContainerVisible(TriView::Container::END, false);
-    Update();
-    return;
-  }
-
-  more_button_ = new ButtonListenerActionableView(
-      owner_, TrayPopupInkDropStyle::INSET_BOUNDS, this);
-  TrayPopupUtils::ConfigureContainer(TriView::Container::END, more_button_);
-
-  more_button_->SetInkDropMode(views::InkDropHostView::InkDropMode::ON);
-  more_button_->SetBorder(views::CreateEmptyBorder(gfx::Insets(
-      0, kTrayPopupButtonEndMargin)));
-  tri_view_->AddView(TriView::Container::END, more_button_);
-
-  device_type_ = TrayPopupUtils::CreateMoreImageView();
-  device_type_->SetVisible(false);
-  more_button_->AddChildView(device_type_);
-
-  more_button_->AddChildView(TrayPopupUtils::CreateMoreImageView());
-  more_button_->SetAccessibleName(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_AUDIO));
   Update();
 }
 
@@ -186,19 +163,59 @@
 
 void VolumeView::UpdateDeviceTypeAndMore() {
   CrasAudioHandler* audio_handler = CrasAudioHandler::Get();
-  bool show_more =
-      is_default_view_ && (audio_handler->has_alternative_output() ||
-                           audio_handler->has_alternative_input());
-
-  if (!show_more)
+  // There is no point in letting the user open the audio detailed submenu if
+  // there are no alternative output or input devices present, so do not show
+  // the 'more' button in the default audio row.
+  if (is_default_view_ && !audio_handler->has_alternative_output() &&
+      !audio_handler->has_alternative_input()) {
+    tri_view_->SetContainerVisible(TriView::Container::END, false);
+    // TODO(tdanderson): TriView itself should trigger a relayout when the
+    // visibility of one of its containers is changed.
+    tri_view_->InvalidateLayout();
     return;
+  }
 
   const gfx::VectorIcon& device_icon = GetActiveOutputDeviceVectorIcon();
-  const bool target_visibility = !device_icon.is_empty();
-  if (target_visibility)
+  const bool device_icon_visibility = !device_icon.is_empty();
+
+  if (is_default_view_) {
+    if (!more_button_) {
+      more_button_ = new ButtonListenerActionableView(
+          owner_, TrayPopupInkDropStyle::INSET_BOUNDS, this);
+      TrayPopupUtils::ConfigureContainer(TriView::Container::END, more_button_);
+
+      more_button_->SetInkDropMode(views::InkDropHostView::InkDropMode::ON);
+      more_button_->SetBorder(
+          views::CreateEmptyBorder(gfx::Insets(0, kTrayPopupButtonEndMargin)));
+      tri_view_->AddView(TriView::Container::END, more_button_);
+
+      device_type_ = TrayPopupUtils::CreateMoreImageView();
+      device_type_->SetVisible(false);
+      more_button_->AddChildView(device_type_);
+
+      more_button_->AddChildView(TrayPopupUtils::CreateMoreImageView());
+      more_button_->SetAccessibleName(
+          l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_AUDIO));
+    }
+  } else {
+    if (!device_icon_visibility) {
+      tri_view_->SetContainerVisible(TriView::Container::END, false);
+      tri_view_->InvalidateLayout();
+      return;
+    }
+    if (!device_type_) {
+      device_type_ = TrayPopupUtils::CreateMoreImageView();
+      device_type_->SetVisible(false);
+      tri_view_->AddView(TriView::Container::END, device_type_);
+    }
+  }
+
+  tri_view_->SetContainerVisible(TriView::Container::END, true);
+  tri_view_->InvalidateLayout();
+  if (device_icon_visibility)
     device_type_->SetImage(gfx::CreateVectorIcon(device_icon, kMenuIconColor));
-  if (device_type_->visible() != target_visibility) {
-    device_type_->SetVisible(target_visibility);
+  if (device_type_->visible() != device_icon_visibility) {
+    device_type_->SetVisible(device_icon_visibility);
     device_type_->InvalidateLayout();
   }
 }
diff --git a/ash/system/brightness/tray_brightness.cc b/ash/system/brightness/tray_brightness.cc
index 88a3d5d0a..9560b45 100644
--- a/ash/system/brightness/tray_brightness.cc
+++ b/ash/system/brightness/tray_brightness.cc
@@ -117,9 +117,8 @@
     SetVisible(Shell::Get()
                    ->maximize_mode_controller()
                    ->IsMaximizeModeWindowManagerEnabled());
-  } else {
-    tri_view->SetContainerVisible(TriView::Container::END, false);
   }
+  tri_view->SetContainerVisible(TriView::Container::END, false);
 }
 
 BrightnessView::~BrightnessView() {
diff --git a/ash/utility/transformer_util.cc b/ash/utility/transformer_util.cc
new file mode 100644
index 0000000..f5499b3f
--- /dev/null
+++ b/ash/utility/transformer_util.cc
@@ -0,0 +1,56 @@
+// 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 "ash/utility/transformer_util.h"
+
+#include <cmath>
+
+#include "third_party/skia/include/core/SkMatrix44.h"
+#include "ui/gfx/transform.h"
+
+namespace ash {
+
+// Round near zero value to zero.
+void RoundNearZero(gfx::Transform* transform) {
+  const float kEpsilon = 0.001f;
+  SkMatrix44& matrix = transform->matrix();
+  for (int x = 0; x < 4; ++x) {
+    for (int y = 0; y < 4; ++y) {
+      if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon)
+        matrix.set(x, y, SkFloatToMScalar(0.0f));
+    }
+  }
+}
+
+gfx::Transform CreateRotationTransform(display::Display::Rotation old_rotation,
+                                       display::Display::Rotation new_rotation,
+                                       const display::Display& display) {
+  const int rotation_angle = 90 * (((new_rotation - old_rotation) + 4) % 4);
+  gfx::Transform rotate;
+  // The origin is (0, 0), so the translate width/height must be reduced by
+  // 1 pixel.
+  float one_pixel = 1.0f / display.device_scale_factor();
+  switch (rotation_angle) {
+    case 0:
+      break;
+    case 90:
+      rotate.Translate(display.bounds().height() - one_pixel, 0);
+      rotate.Rotate(90);
+      break;
+    case 180:
+      rotate.Translate(display.bounds().width() - one_pixel,
+                       display.bounds().height() - one_pixel);
+      rotate.Rotate(180);
+      break;
+    case 270:
+      rotate.Translate(0, display.bounds().width() - one_pixel);
+      rotate.Rotate(270);
+      break;
+  }
+
+  RoundNearZero(&rotate);
+  return rotate;
+}
+
+}  // namespace ash
diff --git a/ash/utility/transformer_util.h b/ash/utility/transformer_util.h
new file mode 100644
index 0000000..d75c5fa
--- /dev/null
+++ b/ash/utility/transformer_util.h
@@ -0,0 +1,26 @@
+// 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 ASH_TRANSFORMER_UTIL_H_
+#define ASH_TRANSFORMER_UTIL_H_
+
+#include "ash/ash_export.h"
+#include "ui/display/display.h"
+
+namespace gfx {
+class Transform;
+}
+
+namespace ash {
+
+// Creates rotation transform from |old_rotation| to |new_rotation| based on the
+// |display| info.
+ASH_EXPORT gfx::Transform CreateRotationTransform(
+    display::Display::Rotation old_rotation,
+    display::Display::Rotation new_rotation,
+    const display::Display& display);
+
+}  // namespace ash
+
+#endif  // ASH_TRANSFORMER_UTIL_H_
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
index 465c23a5..1235452 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
@@ -13,6 +13,7 @@
 import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
 
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.test.BaseTestResult.PreTestHook;
 import org.chromium.base.test.util.DisableIfSkipCheck;
 import org.chromium.base.test.util.MinAndroidSdkLevelSkipCheck;
@@ -21,7 +22,6 @@
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -29,8 +29,8 @@
  *
  *  This ClassRunner imports from AndroidJUnit4ClassRunner which is a hidden but accessible
  *  class. The reason is that default JUnit4 runner for Android is a final class,
- *  {@link AndroidJUnit4}. We need to extends an inheritable class to change {@link runChild}
- *  and {@link isIgnored} to add SkipChecks and PreTesthook.
+ *  AndroidJUnit4. We need to extends an inheritable class to change {@link #runChild}
+ *  and {@link #isIgnored} to add SkipChecks and PreTesthook.
  */
 public class BaseJUnit4ClassRunner extends AndroidJUnit4ClassRunner {
     private final List<SkipCheck> mSkipChecks;
@@ -108,11 +108,9 @@
      * Change this static function to add or take out default {@code SkipCheck}s.
      */
     private static List<SkipCheck> defaultSkipChecks() {
-        return Arrays.asList(new SkipCheck[]{
+        return CollectionUtil.newArrayList(
             new RestrictionSkipCheck(InstrumentationRegistry.getTargetContext()),
-            new MinAndroidSdkLevelSkipCheck(),
-            new DisableIfSkipCheck()
-        });
+            new MinAndroidSdkLevelSkipCheck(), new DisableIfSkipCheck());
     }
 
     /**
diff --git a/cc/animation/keyframed_animation_curve_unittest.cc b/cc/animation/keyframed_animation_curve_unittest.cc
index a7b0e34..df3a0b1 100644
--- a/cc/animation/keyframed_animation_curve_unittest.cc
+++ b/cc/animation/keyframed_animation_curve_unittest.cc
@@ -818,13 +818,13 @@
 
 // Tests that a step timing function works as expected for inputs outside of
 // range [0,1]
-TEST(KeyframedAnimationCurveTest, StepsTimingInputsOutsideZeroOneRange) {
+TEST(KeyframedAnimationCurveTest, StepsTimingStartInputsOutsideZeroOneRange) {
   std::unique_ptr<KeyframedFloatAnimationCurve> curve(
       KeyframedFloatAnimationCurve::Create());
   curve->AddKeyframe(
       FloatKeyframe::Create(base::TimeDelta(), 0.f,
                             StepsTimingFunction::Create(
-                                4, StepsTimingFunction::StepPosition::MIDDLE)));
+                                4, StepsTimingFunction::StepPosition::START)));
   curve->AddKeyframe(
       FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 2.f, nullptr));
   // Curve timing function producing timing outputs outside of range [0,1].
@@ -832,6 +832,22 @@
       CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f));
 
   EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f)));
+  EXPECT_FLOAT_EQ(2.5f, curve->GetValue(base::TimeDelta::FromSecondsD(0.75f)));
+}
+
+TEST(KeyframedAnimationCurveTest, StepsTimingEndInputsOutsideZeroOneRange) {
+  std::unique_ptr<KeyframedFloatAnimationCurve> curve(
+      KeyframedFloatAnimationCurve::Create());
+  curve->AddKeyframe(FloatKeyframe::Create(
+      base::TimeDelta(), 0.f,
+      StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::END)));
+  curve->AddKeyframe(
+      FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 2.f, nullptr));
+  // Curve timing function producing timing outputs outside of range [0,1].
+  curve->SetTimingFunction(
+      CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f));
+
+  EXPECT_FLOAT_EQ(-0.5f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f)));
   EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.75f)));
 }
 
diff --git a/cc/animation/timing_function.cc b/cc/animation/timing_function.cc
index b7308bb..d0d55ad 100644
--- a/cc/animation/timing_function.cc
+++ b/cc/animation/timing_function.cc
@@ -109,8 +109,12 @@
 
 double StepsTimingFunction::GetPreciseValue(double t) const {
   const double steps = static_cast<double>(steps_);
-  return MathUtil::ClampToRange(
-      std::floor((steps * t) + GetStepsStartOffset()) / steps, 0.0, 1.0);
+  double current_step = std::floor((steps * t) + GetStepsStartOffset());
+  if (t >= 0 && current_step < 0)
+    current_step = 0;
+  if (t <= 1 && current_step > steps)
+    current_step = steps;
+  return current_step / steps;
 }
 
 float StepsTimingFunction::GetStepsStartOffset() const {
diff --git a/cc/paint/paint_canvas.cc b/cc/paint/paint_canvas.cc
index 4aab065..a49b2b4 100644
--- a/cc/paint/paint_canvas.cc
+++ b/cc/paint/paint_canvas.cc
@@ -18,10 +18,6 @@
 
 namespace cc {
 
-bool ToPixmap(PaintCanvas* canvas, SkPixmap* output) {
-  return canvas->ToPixmap(output);
-}
-
 #if defined(OS_MACOSX)
 void SetIsPreviewMetafile(PaintCanvas* canvas, bool is_preview) {
   SkMetaData& meta = canvas->getMetaData();
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h
index b163809..86348f0 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -164,8 +164,6 @@
   virtual bool isClipRect() const = 0;
   virtual const SkMatrix& getTotalMatrix() const = 0;
 
-  virtual bool ToPixmap(SkPixmap* output) = 0;
-
   enum class AnnotationType {
     URL,
     NAMED_DESTINATION,
@@ -182,7 +180,6 @@
  protected:
   friend class PaintSurface;
   friend class PaintRecorder;
-  friend CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output);
 };
 
 class CC_PAINT_EXPORT PaintCanvasAutoRestore {
@@ -219,9 +216,6 @@
 // the base PaintCanvas type equivalent to the SkCanvas interface and
 // all these helper functions potentially operating on both.
 
-// PaintCanvas equivalent of skia::GetWritablePixels.
-CC_PAINT_EXPORT bool ToPixmap(PaintCanvas* canvas, SkPixmap* output);
-
 // Following routines are used in print preview workflow to mark the
 // preview metafile.
 #if defined(OS_MACOSX)
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index 57901af..44aad20 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -259,19 +259,6 @@
   record->playback(canvas_);
 }
 
-bool SkiaPaintCanvas::ToPixmap(SkPixmap* output) {
-  SkImageInfo info;
-  size_t row_bytes;
-  void* pixels = canvas_->accessTopLayerPixels(&info, &row_bytes);
-  if (!pixels) {
-    output->reset();
-    return false;
-  }
-
-  output->reset(info, pixels, row_bytes);
-  return true;
-}
-
 void SkiaPaintCanvas::Annotate(AnnotationType type,
                                const SkRect& rect,
                                sk_sp<SkData> data) {
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index 8b29bd6..8e016f0 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -128,7 +128,6 @@
   bool isClipRect() const override;
   const SkMatrix& getTotalMatrix() const override;
 
-  bool ToPixmap(SkPixmap* output) override;
   void Annotate(AnnotationType type,
                 const SkRect& rect,
                 sk_sp<SkData> data) override;
diff --git a/chrome/VERSION b/chrome/VERSION
index c0083be..c89584c 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=60
 MINOR=0
-BUILD=3076
+BUILD=3077
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java
index f0398fc..2f9fbc51 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java
@@ -11,6 +11,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.SysUtils;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.blink.mojom.document_metadata.CopylessPaste;
 import org.chromium.blink.mojom.document_metadata.WebPage;
 import org.chromium.chrome.browser.historyreport.AppIndexingReporter;
@@ -32,6 +33,13 @@
 
     private static Callback<WebPage> sCallbackForTesting;
 
+    // Constants used to log UMA "enum" histograms about the cache state.
+    // The values should not be changed or reused, and CACHE_HISTOGRAM_BOUNDARY should be the last.
+    private static final int CACHE_HIT_WITH_ENTITY = 0;
+    private static final int CACHE_HIT_WITHOUT_ENTITY = 1;
+    private static final int CACHE_MISS = 2;
+    private static final int CACHE_HISTOGRAM_BOUNDARY = 3;
+
     /**
      * Extracts entities from document metadata and reports it to on-device App Indexing.
      * This call can cache entities from recently parsed webpages, in which case, only the url and
@@ -52,11 +60,18 @@
         if (wasPageVisitedRecently(url)) {
             if (lastPageVisitContainedEntity(url)) {
                 // Condition 1
+                RecordHistogram.recordEnumeratedHistogram(
+                        "CopylessPaste.CacheHit", CACHE_HIT_WITH_ENTITY, CACHE_HISTOGRAM_BOUNDARY);
                 getAppIndexingReporter().reportWebPageView(url, tab.getTitle());
+                return;
             }
             // Condition 2
+            RecordHistogram.recordEnumeratedHistogram(
+                    "CopylessPaste.CacheHit", CACHE_HIT_WITHOUT_ENTITY, CACHE_HISTOGRAM_BOUNDARY);
         } else {
             // Condition 3
+            RecordHistogram.recordEnumeratedHistogram(
+                    "CopylessPaste.CacheHit", CACHE_MISS, CACHE_HISTOGRAM_BOUNDARY);
             CopylessPaste copylessPaste = getCopylessPasteInterface(tab);
             if (copylessPaste == null) {
                 return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
index 52fa4931..d51b043 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
@@ -356,11 +356,19 @@
     }
 
     /**
-     * Informs this cache of the relevant {@link Tab} {@code id}s that will be used in the
-     * near future.
+     * Informs this cache of the visible {@link Tab} {@code id}s, as well as the
+     * primary screen-filling tab.
      */
-    protected void updateCacheVisibleIds(List<Integer> priority) {
-        if (mTabContentManager != null) mTabContentManager.updateVisibleIds(priority);
+    protected void updateCacheVisibleIdsAndPrimary(List<Integer> visible, int primaryTabId) {
+        if (mTabContentManager != null) mTabContentManager.updateVisibleIds(visible, primaryTabId);
+    }
+
+    /**
+     * Informs this cache of the visible {@link Tab} {@code id}s, in cases where there
+     * is no primary screen-filling tab.
+     */
+    protected void updateCacheVisibleIds(List<Integer> visible) {
+        if (mTabContentManager != null) mTabContentManager.updateVisibleIds(visible, -1);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
index 147cda0..fa1475d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
@@ -158,7 +158,9 @@
         }
         TabModel model = mTabModelSelector.getModelForTabId(id);
         if (model == null) return;
-        updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id)));
+
+        updateCacheVisibleIdsAndPrimary(new LinkedList<Integer>(Arrays.asList(id)), id);
+
         if (mLayoutTabs == null || mLayoutTabs.length != 1) mLayoutTabs = new LayoutTab[1];
         mLayoutTabs[0] = createLayoutTab(id, model.isIncognito(), NO_CLOSE_BUTTON, NO_TITLE);
         mLayoutTabs[0].setDrawDecoration(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
index 64383ec..72f390b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
@@ -281,7 +281,7 @@
      * Update the priority-ordered list of visible tabs.
      * @param priority The list of tab ids ordered in terms of priority.
      */
-    public void updateVisibleIds(List<Integer> priority) {
+    public void updateVisibleIds(List<Integer> priority, int primaryTabId) {
         if (mNativeTabContentManager != 0) {
             int idsSize = Math.min(mFullResThumbnailsMaxSize, priority.size());
 
@@ -292,7 +292,7 @@
             for (int i = 0; i < idsSize; i++) {
                 mPriorityTabIds[i] = priority.get(i);
             }
-            nativeUpdateVisibleIds(mNativeTabContentManager, mPriorityTabIds);
+            nativeUpdateVisibleIds(mNativeTabContentManager, mPriorityTabIds, primaryTabId);
         }
     }
 
@@ -324,7 +324,8 @@
             Object bitmap, float thumbnailScale);
     private native void nativeInvalidateIfChanged(long nativeTabContentManager, int tabId,
             String url);
-    private native void nativeUpdateVisibleIds(long nativeTabContentManager, int[] priority);
+    private native void nativeUpdateVisibleIds(
+            long nativeTabContentManager, int[] priority, int primaryTabId);
     private native void nativeRemoveTabThumbnail(long nativeTabContentManager, int tabId);
     private native void nativeGetDecompressedThumbnail(long nativeTabContentManager, int tabId);
     private static native void nativeDestroy(long nativeTabContentManager);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 1b1acce..3b1ca31 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -1606,7 +1606,7 @@
         assertNotNull("Main activity did not start", activity);
         ChromeTabbedActivity tabbedActivity =
                 (ChromeTabbedActivity) monitor.waitForActivityWithTimeout(
-                        ACTIVITY_START_TIMEOUT_MS);
+                        getActivityStartTimeoutMs());
         assertNotNull("ChromeTabbedActivity did not start", tabbedActivity);
         assertNotNull("Should have a tab switcher button.",
                 tabbedActivity.findViewById(R.id.tab_switcher_button));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialogTest.java
index 4e50957..5e87034 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialogTest.java
@@ -9,13 +9,22 @@
 import android.support.test.filters.SmallTest;
 import android.support.v7.app.AlertDialog;
 
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestCaseBase;
+import org.chromium.chrome.test.ChromeActivityTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests org.chromium.chrome.browser.webapps.AddToHomescreenDialog by verifying
@@ -24,7 +33,15 @@
  *
  * This is mostly intended as a smoke test.
  */
-public class AddToHomescreenDialogTest extends ChromeActivityTestCaseBase<ChromeActivity> {
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+        // Preconnect causes issues with the single-threaded Java test server.
+        "--disable-features=NetworkPrediction"})
+public class AddToHomescreenDialogTest {
+    @Rule
+    public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
+            new ChromeActivityTestRule<>(ChromeActivity.class);
+
     private static class MockAddToHomescreenManager extends AddToHomescreenManager {
         public MockAddToHomescreenManager(Activity activity, Tab tab) {
             super(activity, tab);
@@ -36,15 +53,12 @@
         public void onFinished() {}
     }
 
-    public AddToHomescreenDialogTest() {
-        super(ChromeActivity.class);
+    @Before
+    public void setUp() throws InterruptedException {
+        mActivityTestRule.startMainActivityOnBlankPage();
     }
 
-    @Override
-    public void startMainActivity() throws InterruptedException {
-        startMainActivityOnBlankPage();
-    }
-
+    @Test
     @SmallTest
     @Feature("{Webapp}")
     @RetryOnFailure
@@ -52,21 +66,21 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                AddToHomescreenDialog dialog =
-                        new AddToHomescreenDialog(new MockAddToHomescreenManager(
-                                getActivity(), getActivity().getActivityTab()));
-                dialog.show(getActivity());
+                AddToHomescreenDialog dialog = new AddToHomescreenDialog(
+                        new MockAddToHomescreenManager(mActivityTestRule.getActivity(),
+                                mActivityTestRule.getActivity().getActivityTab()));
+                dialog.show(mActivityTestRule.getActivity());
 
                 AlertDialog alertDialog = dialog.getAlertDialogForTesting();
-                assertNotNull(alertDialog);
+                Assert.assertNotNull(alertDialog);
 
-                assertTrue(alertDialog.isShowing());
+                Assert.assertTrue(alertDialog.isShowing());
 
-                assertNotNull(alertDialog.findViewById(R.id.spinny));
-                assertNotNull(alertDialog.findViewById(R.id.icon));
-                assertNotNull(alertDialog.findViewById(R.id.text));
-                assertNotNull(alertDialog.getButton(DialogInterface.BUTTON_POSITIVE));
-                assertNotNull(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE));
+                Assert.assertNotNull(alertDialog.findViewById(R.id.spinny));
+                Assert.assertNotNull(alertDialog.findViewById(R.id.icon));
+                Assert.assertNotNull(alertDialog.findViewById(R.id.text));
+                Assert.assertNotNull(alertDialog.getButton(DialogInterface.BUTTON_POSITIVE));
+                Assert.assertNotNull(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE));
             }
         });
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/AppIndexingUtilTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/AppIndexingUtilTest.java
index e7a7b00..ecda0a7d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/AppIndexingUtilTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/AppIndexingUtilTest.java
@@ -14,6 +14,7 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -37,6 +38,8 @@
 @RunWith(LocalRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class AppIndexingUtilTest {
+    @Rule
+    public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
     @Spy
     AppIndexingUtil mUtil = new AppIndexingUtil();
     @Mock
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 64d07df..6d1fa04 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -97,7 +97,7 @@
 #include "ui/gl/gl_features.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/keyboard/keyboard_switches.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 #include "ui/views/views_switches.h"
 
 #if defined(OS_ANDROID)
@@ -1067,9 +1067,7 @@
      flag_descriptions::kOverlayScrollbarsDescription,
      // Uses the system preference on Mac (a different implementation).
      // On Android, this is always enabled.
-     kOsAura,
-     ENABLE_DISABLE_VALUE_TYPE(switches::kEnableOverlayScrollbar,
-                               switches::kDisableOverlayScrollbar)},
+     kOsAura, FEATURE_VALUE_TYPE(features::kOverlayScrollbar)},
 #endif  // USE_AURA
     {   // See http://crbug.com/120416 for how to remove this flag.
      "save-page-as-mhtml", flag_descriptions::kSavePageAsMhtmlName,
@@ -2746,6 +2744,12 @@
      flag_descriptions::kColorCorrectRenderingDescription, kOsAll,
      MULTI_VALUE_TYPE(kColorCorrectRenderingChoices)},
 
+#if defined(OS_CHROMEOS)
+    {"quick-unlock-pin-signin", flag_descriptions::kQuickUnlockPinSignin,
+     flag_descriptions::kQuickUnlockPinSigninDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(features::kQuickUnlockPinSignin)},
+#endif  // OS_CHROMEOS
+
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms.xml. See note in
     // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/after_startup_task_utils.cc b/chrome/browser/after_startup_task_utils.cc
index 96f4fad..051dd173 100644
--- a/chrome/browser/after_startup_task_utils.cc
+++ b/chrome/browser/after_startup_task_utils.cc
@@ -70,7 +70,7 @@
   scoped_refptr<base::TaskRunner> target_runner = queued_task->task_runner;
   tracked_objects::Location from_here = queued_task->from_here;
   target_runner->PostDelayedTask(
-      from_here, base::Bind(&RunTask, base::Passed(std::move(queued_task))),
+      from_here, base::BindOnce(&RunTask, base::Passed(std::move(queued_task))),
       base::TimeDelta::FromSeconds(base::RandInt(kMinDelaySec, kMaxDelaySec)));
 }
 
@@ -84,7 +84,7 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(QueueTask, base::Passed(std::move(queued_task))));
+        base::BindOnce(QueueTask, base::Passed(std::move(queued_task))));
     return;
   }
 
@@ -190,10 +190,11 @@
   delay = base::TimeDelta::FromMinutes(kLongerDelayMins);
 #endif  // !defined(OS_ANDROID)
 
-  BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
-                                 base::Bind(&StartupObserver::OnFailsafeTimeout,
-                                            weak_factory_.GetWeakPtr()),
-                                 delay);
+  BrowserThread::PostDelayedTask(
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&StartupObserver::OnFailsafeTimeout,
+                     weak_factory_.GetWeakPtr()),
+      delay);
 }
 
 }  // namespace
diff --git a/chrome/browser/after_startup_task_utils_unittest.cc b/chrome/browser/after_startup_task_utils_unittest.cc
index 6b1a9c5b..61867b0 100644
--- a/chrome/browser/after_startup_task_utils_unittest.cc
+++ b/chrome/browser/after_startup_task_utils_unittest.cc
@@ -105,7 +105,7 @@
         FROM_HERE,
         base::BindOnce(&AfterStartupTaskUtils::PostTask, from_here, task_runner,
                        std::move(task)),
-        base::Bind(&RunLoop::Quit, base::Unretained(&run_loop)));
+        base::BindOnce(&RunLoop::Quit, base::Unretained(&run_loop)));
     run_loop.Run();
   }
 
@@ -113,8 +113,8 @@
   void FlushDBThread() {
     RunLoop run_loop;
     db_thread_->real_runner()->PostTaskAndReply(
-        FROM_HERE, base::Bind(&base::DoNothing),
-        base::Bind(&RunLoop::Quit, base::Unretained(&run_loop)));
+        FROM_HERE, base::BindOnce(&base::DoNothing),
+        base::BindOnce(&RunLoop::Quit, base::Unretained(&run_loop)));
     run_loop.Run();
   }
 
@@ -154,20 +154,20 @@
   EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
   AfterStartupTaskUtils::PostTask(
       FROM_HERE, ui_thread_,
-      base::Bind(&AfterStartupTaskTest::VerifyExpectedThread,
-                 BrowserThread::UI));
+      base::BindOnce(&AfterStartupTaskTest::VerifyExpectedThread,
+                     BrowserThread::UI));
   AfterStartupTaskUtils::PostTask(
       FROM_HERE, db_thread_,
-      base::Bind(&AfterStartupTaskTest::VerifyExpectedThread,
-                 BrowserThread::DB));
+      base::BindOnce(&AfterStartupTaskTest::VerifyExpectedThread,
+                     BrowserThread::DB));
   PostAfterStartupTaskFromDBThread(
       FROM_HERE, ui_thread_,
-      base::Bind(&AfterStartupTaskTest::VerifyExpectedThread,
-                 BrowserThread::UI));
+      base::BindOnce(&AfterStartupTaskTest::VerifyExpectedThread,
+                     BrowserThread::UI));
   PostAfterStartupTaskFromDBThread(
       FROM_HERE, db_thread_,
-      base::Bind(&AfterStartupTaskTest::VerifyExpectedThread,
-                 BrowserThread::DB));
+      base::BindOnce(&AfterStartupTaskTest::VerifyExpectedThread,
+                     BrowserThread::DB));
   RunLoop().RunUntilIdle();
   EXPECT_EQ(0, db_thread_->total_task_count() + ui_thread_->total_task_count());
 
@@ -186,15 +186,15 @@
 
   // Tasks posted after startup should get posted immediately.
   AfterStartupTaskUtils::PostTask(FROM_HERE, ui_thread_,
-                                  base::Bind(&base::DoNothing));
+                                  base::BindOnce(&base::DoNothing));
   AfterStartupTaskUtils::PostTask(FROM_HERE, db_thread_,
-                                  base::Bind(&base::DoNothing));
+                                  base::BindOnce(&base::DoNothing));
   EXPECT_EQ(1, db_thread_->posted_task_count());
   EXPECT_EQ(1, ui_thread_->posted_task_count());
   PostAfterStartupTaskFromDBThread(FROM_HERE, ui_thread_,
-                                   base::Bind(&base::DoNothing));
+                                   base::BindOnce(&base::DoNothing));
   PostAfterStartupTaskFromDBThread(FROM_HERE, db_thread_,
-                                   base::Bind(&base::DoNothing));
+                                   base::BindOnce(&base::DoNothing));
   EXPECT_EQ(2, db_thread_->posted_task_count());
   EXPECT_EQ(2, ui_thread_->posted_task_count());
   FlushDBThread();
@@ -212,8 +212,8 @@
 
   EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
   after_startup_runner->PostTask(
-      FROM_HERE, base::Bind(&AfterStartupTaskTest::VerifyExpectedThread,
-                            BrowserThread::DB));
+      FROM_HERE, base::BindOnce(&AfterStartupTaskTest::VerifyExpectedThread,
+                                BrowserThread::DB));
 
   RunLoop().RunUntilIdle();
   EXPECT_FALSE(AfterStartupTaskUtils::IsBrowserStartupComplete());
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc
index 654e721..8b5e26c 100644
--- a/chrome/browser/android/compositor/tab_content_manager.cc
+++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -278,7 +278,8 @@
 void TabContentManager::UpdateVisibleIds(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jintArray>& priority) {
+    const JavaParamRef<jintArray>& priority,
+    jint primary_tab_id) {
   std::list<int> priority_ids;
   jsize length = env->GetArrayLength(priority);
   jint* ints = env->GetIntArrayElements(priority, nullptr);
@@ -286,7 +287,7 @@
     priority_ids.push_back(static_cast<int>(ints[i]));
 
   env->ReleaseIntArrayElements(priority, ints, JNI_ABORT);
-  thumbnail_cache_->UpdateVisibleIds(priority_ids);
+  thumbnail_cache_->UpdateVisibleIds(priority_ids, primary_tab_id);
 }
 
 void TabContentManager::RemoveTabThumbnail(JNIEnv* env,
diff --git a/chrome/browser/android/compositor/tab_content_manager.h b/chrome/browser/android/compositor/tab_content_manager.h
index 70b5372c..331330b 100644
--- a/chrome/browser/android/compositor/tab_content_manager.h
+++ b/chrome/browser/android/compositor/tab_content_manager.h
@@ -90,7 +90,8 @@
                            const base::android::JavaParamRef<jstring>& jurl);
   void UpdateVisibleIds(JNIEnv* env,
                         const base::android::JavaParamRef<jobject>& obj,
-                        const base::android::JavaParamRef<jintArray>& priority);
+                        const base::android::JavaParamRef<jintArray>& priority,
+                        jint primary_tab_id);
   void RemoveTabThumbnail(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj,
                           jint tab_id);
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.cc b/chrome/browser/android/offline_pages/recent_tab_helper.cc
index f248220..308afd1 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper.cc
+++ b/chrome/browser/android/offline_pages/recent_tab_helper.cc
@@ -212,18 +212,27 @@
         downloads_ongoing_snapshot_info_.get(), false);
   }
 
+  // If the previous page was saved, delete it now.
+  if (last_n_latest_saved_snapshot_info_) {
+    std::vector<int64_t> id{last_n_latest_saved_snapshot_info_->request_id};
+    page_model_->DeletePagesByOfflineId(id, DeletePageCallback());
+  }
+
   // Cancel any and all in flight snapshot tasks from the previous page.
-  DVLOG_IF(1, last_n_ongoing_snapshot_info_)
-      << " - Canceling ongoing last_n snapshot";
   CancelInFlightSnapshots();
   downloads_snapshot_on_hold_ = false;
 
   // Always reset so that posted tasks get canceled.
   snapshot_controller_->Reset();
 
-  // Check for conditions that would cause us not to snapshot.
+  // Check for conditions that should stop last_n from creating snapshots of
+  // this page:
+  // - It is an error page.
+  // - The navigation is a POST as offline pages are never loaded for them.
+  // - The navigated URL is not supported.
+  // - The page being loaded is already an offline page.
   bool can_save =
-      !navigation_handle->IsErrorPage() &&
+      !navigation_handle->IsErrorPage() && !navigation_handle->IsPost() &&
       OfflinePageModel::CanSaveURL(web_contents()->GetLastCommittedURL()) &&
       OfflinePageUtils::GetOfflinePageFromWebContents(web_contents()) ==
           nullptr;
@@ -419,8 +428,12 @@
 void RecentTabHelper::SavePageCallback(SnapshotProgressInfo* snapshot_info,
                                        OfflinePageModel::SavePageResult result,
                                        int64_t offline_id) {
-  DCHECK(snapshot_info->IsForLastN() ||
+  DCHECK((snapshot_info->IsForLastN() &&
+          snapshot_info->request_id == OfflinePageModel::kInvalidOfflineId) ||
          snapshot_info->request_id == offline_id);
+  // Store the assigned offline_id (for downloads case it will already contain
+  // the same value).
+  snapshot_info->request_id = offline_id;
   ReportSnapshotCompleted(snapshot_info, result == SavePageResult::SUCCESS);
 }
 
@@ -434,7 +447,12 @@
            << " for: " << web_contents()->GetLastCommittedURL().spec();
   if (snapshot_info->IsForLastN()) {
     DCHECK_EQ(snapshot_info, last_n_ongoing_snapshot_info_.get());
-    last_n_ongoing_snapshot_info_.reset();
+    if (success) {
+      last_n_latest_saved_snapshot_info_ =
+          std::move(last_n_ongoing_snapshot_info_);
+    } else {
+      last_n_ongoing_snapshot_info_.reset();
+    }
     return;
   }
 
@@ -481,10 +499,15 @@
 }
 
 void RecentTabHelper::CancelInFlightSnapshots() {
+  DVLOG_IF(1, last_n_ongoing_snapshot_info_)
+      << " - Canceling ongoing last_n snapshot";
+  DVLOG_IF(1, downloads_ongoing_snapshot_info_)
+      << " - Canceling ongoing downloads snapshot";
   weak_ptr_factory_.InvalidateWeakPtrs();
   downloads_ongoing_snapshot_info_.reset();
   downloads_latest_saved_snapshot_info_.reset();
   last_n_ongoing_snapshot_info_.reset();
+  last_n_latest_saved_snapshot_info_.reset();
 }
 
 }  // namespace offline_pages
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.h b/chrome/browser/android/offline_pages/recent_tab_helper.h
index b547240..c61fbd74 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper.h
+++ b/chrome/browser/android/offline_pages/recent_tab_helper.h
@@ -128,13 +128,18 @@
   bool downloads_snapshot_on_hold_ = false;
 
   // Snapshot information for the last successful snapshot requested by
-  // downloads. Null if no successful one has ever completed.
+  // downloads. Null if no successful one has ever completed for the current
+  // page.
   std::unique_ptr<SnapshotProgressInfo> downloads_latest_saved_snapshot_info_;
 
   // Snapshot progress information for a last_n triggered request. Null if
   // last_n is not currently capturing the current page.
   std::unique_ptr<SnapshotProgressInfo> last_n_ongoing_snapshot_info_;
 
+  // Snapshot information for the last successful snapshot requested by
+  // last_n. Null if no successful one has ever completed for the current page.
+  std::unique_ptr<SnapshotProgressInfo> last_n_latest_saved_snapshot_info_;
+
   // If empty, the tab does not have AndroidId and can not capture pages.
   std::string tab_id_;
 
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
index 7f97d15f..3e4c535 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
+++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -375,8 +375,8 @@
   ASSERT_EQ(1U, GetAllPages().size());
 }
 
-// Checks that last_n will not save a snapshot if the tab while the tab is
-// presented as a custom tab. Download requests should be unaffected though.
+// Checks that last_n will not save a snapshot while the tab is being presented
+// as a custom tab. Download requests should be unaffected though.
 TEST_F(RecentTabHelperTest, LastNWontSaveCustomTab) {
   // Simulates the tab running as a custom tab.
   default_test_delegate()->set_is_custom_tab(true);
@@ -500,15 +500,16 @@
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
   int64_t first_offline_id = GetAllPages()[0].offline_id;
 
-  // Navigate with the same URL until the page is minimally loaded then hide the
-  // tab. The previous snapshot should be removed and a new one taken.
+  // Reload the same URL until the page is minimally loaded. The previous
+  // snapshot should have been removed.
   NavigateAndCommitTyped(kTestPageUrl);
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
   EXPECT_EQ(1U, page_added_count());
-  EXPECT_EQ(0U, model_removed_count());
-  ASSERT_EQ(1U, GetAllPages().size());
+  EXPECT_EQ(1U, model_removed_count());
+  ASSERT_EQ(0U, GetAllPages().size());
 
+  // Hide the tab and a new snapshot should be taken.
   recent_tab_helper()->WasHidden();
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
@@ -565,15 +566,15 @@
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
 
-  // Fully load the second URL then hide the tab and check for a single snapshot
-  // of the new page.
+  // Fully load the second URL. The previous snapshot should have been deleted.
   NavigateAndCommitTyped(kTestPageUrlOther);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   EXPECT_EQ(1U, page_added_count());
-  EXPECT_EQ(0U, model_removed_count());
-  ASSERT_EQ(1U, GetAllPages().size());
+  EXPECT_EQ(1U, model_removed_count());
+  ASSERT_EQ(0U, GetAllPages().size());
 
+  // Then hide the tab and check for a single snapshot of the new page.
   recent_tab_helper()->WasHidden();
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
@@ -731,7 +732,7 @@
 }
 
 // Simulates a download request to offline the current page made after loading
-// is completed. Should end up with one offline pages.
+// is completed. Should end up with one offline page.
 TEST_F(RecentTabHelperTest, DownloadRequestAfterFullyLoad) {
   NavigateAndCommit(kTestPageUrl);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
@@ -897,7 +898,8 @@
   RunUntilIdle();
   ASSERT_EQ(1U, GetAllPages().size());
 
-  // Starts a reload and hides the tab. No new snapshot should be saved.
+  // Starts a reload and hides the tab before it minimally load. The previous
+  // snapshot should be removed.
   controller().Reload(content::ReloadType::NORMAL, false);
   content::WebContentsTester* web_contents_tester =
       content::WebContentsTester::For(web_contents());
@@ -905,8 +907,8 @@
   recent_tab_helper()->WasHidden();
   RunUntilIdle();
   EXPECT_EQ(1U, page_added_count());
-  EXPECT_EQ(0U, model_removed_count());
-  ASSERT_EQ(1U, GetAllPages().size());
+  EXPECT_EQ(1U, model_removed_count());
+  ASSERT_EQ(0U, GetAllPages().size());
 
   // Finish loading and hide the tab. A new snapshot should be created.
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
diff --git a/chrome/browser/android/thumbnail/thumbnail_cache.cc b/chrome/browser/android/thumbnail/thumbnail_cache.cc
index c75c19e..e8b6256 100644
--- a/chrome/browser/android/thumbnail/thumbnail_cache.cc
+++ b/chrome/browser/android/thumbnail/thumbnail_cache.cc
@@ -209,7 +209,8 @@
     return thumbnail;
   }
 
-  if (force_disk_read && base::ContainsValue(visible_ids_, tab_id) &&
+  if (force_disk_read && primary_tab_id_ != tab_id &&
+      base::ContainsValue(visible_ids_, tab_id) &&
       !base::ContainsValue(read_queue_, tab_id)) {
     read_queue_.push_back(tab_id);
     ReadNextThumbnail();
@@ -264,17 +265,23 @@
   return true;
 }
 
-void ThumbnailCache::UpdateVisibleIds(const TabIdList& priority) {
-  if (priority.empty()) {
-    visible_ids_.clear();
-    return;
+void ThumbnailCache::UpdateVisibleIds(const TabIdList& priority,
+                                      TabId primary_tab_id) {
+  bool needs_update = false;
+  if (primary_tab_id_ != primary_tab_id) {
+    // The primary screen-filling tab (if any) is not pushed onto the read
+    // queue, under the assumption that it either has a live layer or will have
+    // one very soon.
+    primary_tab_id_ = primary_tab_id;
+    needs_update = true;
   }
 
   size_t ids_size = std::min(priority.size(), cache_.MaximumCacheSize());
-  if (visible_ids_.size() == ids_size) {
+  if (visible_ids_.size() != ids_size) {
+    needs_update = true;
+  } else {
     // Early out if called with the same input as last time (We only care
     // about the first mCache.MaximumCacheSize() entries).
-    bool needs_update = false;
     TabIdList::const_iterator visible_iter = visible_ids_.begin();
     TabIdList::const_iterator priority_iter = priority.begin();
     while (visible_iter != visible_ids_.end() &&
@@ -286,11 +293,11 @@
       visible_iter++;
       priority_iter++;
     }
-
-    if (!needs_update)
-      return;
   }
 
+  if (!needs_update)
+    return;
+
   read_queue_.clear();
   visible_ids_.clear();
   size_t count = 0;
@@ -298,7 +305,8 @@
   while (iter != priority.end() && count < ids_size) {
     TabId tab_id = *iter;
     visible_ids_.push_back(tab_id);
-    if (!cache_.Get(tab_id) && !base::ContainsValue(read_queue_, tab_id))
+    if (!cache_.Get(tab_id) && primary_tab_id_ != tab_id &&
+        !base::ContainsValue(read_queue_, tab_id))
       read_queue_.push_back(tab_id);
     iter++;
     count++;
diff --git a/chrome/browser/android/thumbnail/thumbnail_cache.h b/chrome/browser/android/thumbnail/thumbnail_cache.h
index e67e29b..cd0378f 100644
--- a/chrome/browser/android/thumbnail/thumbnail_cache.h
+++ b/chrome/browser/android/thumbnail/thumbnail_cache.h
@@ -62,7 +62,7 @@
 
   void InvalidateThumbnailIfChanged(TabId tab_id, const GURL& url);
   bool CheckAndUpdateThumbnailMetaData(TabId tab_id, const GURL& url);
-  void UpdateVisibleIds(const TabIdList& priority);
+  void UpdateVisibleIds(const TabIdList& priority, TabId primary_tab_id);
   void DecompressThumbnailFromFile(
       TabId tab_id,
       const base::Callback<void(bool, SkBitmap)>&
@@ -160,6 +160,7 @@
   ThumbnailMetaDataMap thumbnail_meta_data_;
   TabIdList read_queue_;
   TabIdList visible_ids_;
+  TabId primary_tab_id_ = -1;
 
   ui::UIResourceProvider* ui_resource_provider_;
 
diff --git a/chrome/browser/android/webapk/webapk.proto b/chrome/browser/android/webapk/webapk.proto
index 614d514..7c12390 100644
--- a/chrome/browser/android/webapk/webapk.proto
+++ b/chrome/browser/android/webapk/webapk.proto
@@ -16,13 +16,6 @@
   // Version code of the WebAPK.
   optional string version = 2;
 
-  // URL to download WebAPK. If the URL is empty, the client should not attempt
-  // to download or install anything. For example, this may be empty when the
-  // client requests an update even though no content has changed. The WebAPK
-  // server can then let the client know that it is up-to-date already and does
-  // not need to spend bandwidth re-downloading a WebAPK it has.
-  optional string signed_download_url = 3;
-
   // Unique id identifying session with WebAPK server.
   optional string token = 6;
 
@@ -34,7 +27,7 @@
   // from spamming update requests too often.
   optional bool relax_updates = 8;
 
-  reserved 4, 5, 7;
+  reserved 3, 4, 5, 7;
 }
 
 // Sent as part of request to create or update a WebAPK.
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc
index 0f13ea69..5e999a28 100644
--- a/chrome/browser/android/webapk/webapk_installer.cc
+++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -399,8 +399,8 @@
     return;
   }
 
-  GURL signed_download_url(response->signed_download_url());
-  if (task_type_ == UPDATE && signed_download_url.is_empty()) {
+  const std::string& token = response->token();
+  if (task_type_ == UPDATE && token.empty()) {
     // https://crbug.com/680131. The server sends an empty URL if the server
     // does not have a newer WebAPK to update to.
     relax_updates_ = response->relax_updates();
@@ -408,7 +408,7 @@
     return;
   }
 
-  if (!signed_download_url.is_valid() || response->package_name().empty()) {
+  if (token.empty() || response->package_name().empty()) {
     LOG(WARNING) << "WebAPK server returned incomplete proto.";
     OnResult(WebApkInstallResult::FAILURE);
     return;
@@ -421,7 +421,7 @@
 
   int version = 1;
   base::StringToInt(response->version(), &version);
-  InstallOrUpdateWebApk(response->package_name(), version, response->token());
+  InstallOrUpdateWebApk(response->package_name(), version, token);
 }
 
 void WebApkInstaller::OnGotPrimaryIconMurmur2Hash(
diff --git a/chrome/browser/android/webapk/webapk_installer_unittest.cc b/chrome/browser/android/webapk/webapk_installer_unittest.cc
index 87abf28..7418381 100644
--- a/chrome/browser/android/webapk/webapk_installer_unittest.cc
+++ b/chrome/browser/android/webapk/webapk_installer_unittest.cc
@@ -47,9 +47,10 @@
 const char* kBestPrimaryIconUrl = "/simple.html";
 const char* kBestBadgeIconUrl = "/nostore.html";
 
-// URL of file to download from the WebAPK server. We use a random file in the
-// test data directory.
-const char* kDownloadUrl = "/simple.html";
+// Token from the WebAPK server. In production, the token is sent to Google
+// Play. Google Play uses the token to retrieve the WebAPK from the WebAPK
+// server.
+const char* kToken = "token";
 
 // The package name of the downloaded WebAPK.
 const char* kDownloadedWebApkPackageName = "party.unicode";
@@ -180,14 +181,14 @@
   DISALLOW_COPY_AND_ASSIGN(WebApkInstallerRunner);
 };
 
-// Builds a webapk::WebApkResponse with |download_url| as the WebAPK download
-// URL.
+// Builds a webapk::WebApkResponse with |token| as the token from the WebAPK
+// server.
 std::unique_ptr<net::test_server::HttpResponse> BuildValidWebApkResponse(
-    const GURL& download_url) {
+    const std::string& token) {
   std::unique_ptr<webapk::WebApkResponse> response_proto(
       new webapk::WebApkResponse);
   response_proto->set_package_name(kDownloadedWebApkPackageName);
-  response_proto->set_signed_download_url(download_url.spec());
+  response_proto->set_token(token);
   std::string response_content;
   response_proto->SerializeToString(&response_content);
 
@@ -316,8 +317,7 @@
     SetBestPrimaryIconUrl(test_server_.GetURL(kBestPrimaryIconUrl));
     SetBestBadgeIconUrl(test_server_.GetURL(kBestBadgeIconUrl));
     SetWebApkServerUrl(test_server_.GetURL(kServerUrl));
-    SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse,
-                                        test_server_.GetURL(kDownloadUrl)));
+    SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse, kToken));
   }
 
   std::unique_ptr<net::test_server::HttpResponse> HandleWebApkRequest(
@@ -411,14 +411,14 @@
 }
 
 // Test that an update suceeds if the WebAPK server returns a HTTP response with
-// an empty download URL. The WebAPK server sends an empty download URL when:
+// an empty token. The WebAPK server sends an empty download URL when:
 // - The server is unable to update the WebAPK in the way that the client
 //   requested.
 // AND
 // - The most up to date version of the WebAPK on the server is identical to the
 //   one installed on the client.
 TEST_F(WebApkInstallerTest, UpdateSuccessWithEmptyDownloadUrlInResponse) {
-  SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse, GURL()));
+  SetWebApkResponseBuilder(base::Bind(&BuildValidWebApkResponse, ""));
 
   std::unique_ptr<WebApkInstallerRunner> runner = CreateWebApkInstallerRunner();
   runner->RunUpdateWebApk();
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index c05d022..74e2add 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -165,8 +165,8 @@
     ++num_times_shown_;
     auto* context_menu = content::Source<RenderViewContextMenu>(source).ptr();
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&RenderViewContextMenuBase::Cancel,
-                              base::Unretained(context_menu)));
+        FROM_HERE, base::BindOnce(&RenderViewContextMenuBase::Cancel,
+                                  base::Unretained(context_menu)));
     return true;
   }
 
@@ -310,8 +310,8 @@
         mouse_event_);
 
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, base::Bind(&LeftMouseClick::SendMouseUp,
-                              base::Unretained(this)),
+        FROM_HERE,
+        base::BindOnce(&LeftMouseClick::SendMouseUp, base::Unretained(this)),
         base::TimeDelta::FromMilliseconds(duration_ms));
   }
 
@@ -2209,8 +2209,8 @@
     const content::NotificationDetails& details) {
   auto* context_menu = content::Source<RenderViewContextMenu>(source).ptr();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&RenderViewContextMenuBase::Cancel,
-                            base::Unretained(context_menu)));
+      FROM_HERE, base::BindOnce(&RenderViewContextMenuBase::Cancel,
+                                base::Unretained(context_menu)));
   return true;
 }
 
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
index 2a7094e..4bfebfb2 100644
--- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -351,7 +351,7 @@
     void ScheduleWait() {
       base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
           FROM_HERE,
-          base::Bind(&PopupCreatedObserver::Wait, base::Unretained(this)),
+          base::BindOnce(&PopupCreatedObserver::Wait, base::Unretained(this)),
           base::TimeDelta::FromMilliseconds(200));
     }
 
@@ -424,8 +424,9 @@
 
     // Now wait a bit before moving mouse to initiate drag/drop.
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, base::Bind(&WebViewInteractiveTestBase::DragTestStep2,
-                              base::Unretained(this)),
+        FROM_HERE,
+        base::BindOnce(&WebViewInteractiveTestBase::DragTestStep2,
+                       base::Unretained(this)),
         base::TimeDelta::FromMilliseconds(200));
   }
 
diff --git a/chrome/browser/apps/shortcut_manager.cc b/chrome/browser/apps/shortcut_manager.cc
index 91f2330..761714da 100644
--- a/chrome/browser/apps/shortcut_manager.cc
+++ b/chrome/browser/apps/shortcut_manager.cc
@@ -138,8 +138,8 @@
     return;
   content::BrowserThread::PostTask(
       content::BrowserThread::FILE, FROM_HERE,
-      base::Bind(&web_app::internals::DeleteAllShortcutsForProfile,
-                 profile_path));
+      base::BindOnce(&web_app::internals::DeleteAllShortcutsForProfile,
+                     profile_path));
 }
 
 void AppShortcutManager::UpdateShortcutsForAllAppsIfNeeded() {
@@ -151,10 +151,8 @@
     return;
 
   content::BrowserThread::PostDelayedTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&web_app::UpdateShortcutsForAllApps,
-                 profile_,
-                 base::Bind(&SetCurrentAppShortcutsVersion, prefs_)),
+      content::BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&web_app::UpdateShortcutsForAllApps, profile_,
+                     base::Bind(&SetCurrentAppShortcutsVersion, prefs_)),
       base::TimeDelta::FromSeconds(kUpdateShortcutsForAllAppsDelay));
 }
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc
index 1be0bc7..0f0247b 100644
--- a/chrome/browser/background/background_contents_service.cc
+++ b/chrome/browser/background/background_contents_service.cc
@@ -90,8 +90,9 @@
   if (g_disable_close_balloon_for_testing)
     return;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&CloseBalloon, kNotificationPrefix + extension_id,
-                            NotificationUIManager::GetProfileID(profile)));
+      FROM_HERE,
+      base::BindOnce(&CloseBalloon, kNotificationPrefix + extension_id,
+                     NotificationUIManager::GetProfileID(profile)));
 }
 
 // Delegate for the app/extension crash notification balloon. Restarts the
@@ -480,10 +481,11 @@
         component_backoff_map_.find(extension->id());
     if (it != component_backoff_map_.end()) {
       net::BackoffEntry* entry = component_backoff_map_[extension->id()].get();
-      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
-          base::Bind(&BackgroundContentsService::MaybeClearBackoffEntry,
-              weak_ptr_factory_.GetWeakPtr(), extension->id(),
-              entry->failure_count()),
+      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+          FROM_HERE,
+          base::BindOnce(&BackgroundContentsService::MaybeClearBackoffEntry,
+                         weak_ptr_factory_.GetWeakPtr(), extension->id(),
+                         entry->failure_count()),
           base::TimeDelta::FromSeconds(60));
     }
   }
@@ -570,7 +572,7 @@
   }
 
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, base::Bind(&ReloadExtension, extension->id(), profile),
+      FROM_HERE, base::BindOnce(&ReloadExtension, extension->id(), profile),
       base::TimeDelta::FromMilliseconds(restart_delay));
 }
 
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 56524fb..06724eee 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -705,8 +705,8 @@
     // alive by the browser process until after the callback is called.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&BackgroundModeManager::ReleaseStartupKeepAliveCallback,
-                   base::Unretained(this)));
+        base::BindOnce(&BackgroundModeManager::ReleaseStartupKeepAliveCallback,
+                       base::Unretained(this)));
   }
 }
 
diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc
index 77d83cb..5bfecb94 100644
--- a/chrome/browser/bookmarks/bookmark_html_writer.cc
+++ b/chrome/browser/bookmarks/bookmark_html_writer.cc
@@ -451,7 +451,7 @@
   BookmarkCodec codec;
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &Writer::DoWrite,
           new Writer(codec.Encode(
                          BookmarkModelFactory::GetForBrowserContext(profile_)),
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc
index a89d62b..e576359 100644
--- a/chrome/browser/browser_about_handler.cc
+++ b/chrome/browser/browser_about_handler.cc
@@ -147,11 +147,11 @@
     // Call AttemptRestart after chrome::Navigate() completes to avoid access of
     // gtk objects after they are destroyed by BrowserWindowGtk::Close().
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&chrome::AttemptRestart));
+        FROM_HERE, base::BindOnce(&chrome::AttemptRestart));
     return true;
   } else if (base::LowerCaseEqualsASCII(spec, chrome::kChromeUIQuitURL)) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&chrome::AttemptExit));
+        FROM_HERE, base::BindOnce(&chrome::AttemptExit));
     return true;
   }
 
diff --git a/chrome/browser/browser_encoding_browsertest.cc b/chrome/browser/browser_encoding_browsertest.cc
index 29eeff9..79325655 100644
--- a/chrome/browser/browser_encoding_browsertest.cc
+++ b/chrome/browser/browser_encoding_browsertest.cc
@@ -147,7 +147,7 @@
 
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
+        base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
   }
 
   base::ScopedTempDir temp_dir_;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 39dc70e..a0d1638 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -447,8 +447,8 @@
 
   // The task must be non-nestable to guarantee that it runs after all tasks
   // currently scheduled on |task_runner| have completed.
-  task_runner->PostNonNestableTask(FROM_HERE,
-      base::Bind(&RundownTaskCounter::Decrement, this));
+  task_runner->PostNonNestableTask(
+      FROM_HERE, base::BindOnce(&RundownTaskCounter::Decrement, this));
 }
 
 void RundownTaskCounter::Decrement() {
@@ -1319,7 +1319,7 @@
 #if !defined(OS_ANDROID)
   CHECK(BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           base::IgnoreResult(&GoogleUpdateSettings::SetCollectStatsConsent),
           ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled())));
 #endif
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index 3dd6bb3..a62b7162 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -335,7 +335,7 @@
   // Read and delete the file on the file thread.
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      base::Bind(&ReadLastShutdownFile, type, num_procs, num_procs_slow));
+      base::BindOnce(&ReadLastShutdownFile, type, num_procs, num_procs_slow));
 }
 
 void SetTryingToQuit(bool quitting) {
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc
index 74f4586..90f95be 100644
--- a/chrome/browser/captive_portal/captive_portal_browsertest.cc
+++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -238,8 +238,8 @@
 void URLRequestTimeoutOnDemandJob::WaitForJobs(int num_jobs) {
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread,
-                 num_jobs));
+      base::BindOnce(&URLRequestTimeoutOnDemandJob::WaitForJobsOnIOThread,
+                     num_jobs));
   content::RunMessageLoop();
 }
 
@@ -247,8 +247,8 @@
 void URLRequestTimeoutOnDemandJob::FailJobs(int expected_num_jobs) {
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
-                 expected_num_jobs, FAIL_JOBS, net::SSLInfo()));
+      base::BindOnce(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
+                     expected_num_jobs, FAIL_JOBS, net::SSLInfo()));
 }
 
 // static
@@ -257,16 +257,16 @@
     const net::SSLInfo& ssl_info) {
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
-                 expected_num_jobs, FAIL_JOBS_WITH_CERT_ERROR, ssl_info));
+      base::BindOnce(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
+                     expected_num_jobs, FAIL_JOBS_WITH_CERT_ERROR, ssl_info));
 }
 
 // static
 void URLRequestTimeoutOnDemandJob::AbandonJobs(int expected_num_jobs) {
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
-                 expected_num_jobs, ABANDON_JOBS, net::SSLInfo()));
+      base::BindOnce(&URLRequestTimeoutOnDemandJob::FailOrAbandonJobsOnIOThread,
+                     expected_num_jobs, ABANDON_JOBS, net::SSLInfo()));
 }
 
 URLRequestTimeoutOnDemandJob::URLRequestTimeoutOnDemandJob(
@@ -429,7 +429,7 @@
 void URLRequestMockCaptivePortalJobFactory::AddUrlHandlers() {
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &URLRequestMockCaptivePortalJobFactory::AddUrlHandlersOnIOThread,
           base::Unretained(this)));
 }
@@ -438,9 +438,9 @@
     bool behind_captive_portal) {
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&URLRequestMockCaptivePortalJobFactory::
-                     SetBehindCaptivePortalOnIOThread,
-                 base::Unretained(this), behind_captive_portal));
+      base::BindOnce(&URLRequestMockCaptivePortalJobFactory::
+                         SetBehindCaptivePortalOnIOThread,
+                     base::Unretained(this), behind_captive_portal));
 }
 
 std::unique_ptr<net::URLRequestInterceptor>
@@ -1106,7 +1106,7 @@
   // Enable mock requests.
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
+      base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
   factory_.AddUrlHandlers();
 
   // Double-check that the captive portal service isn't enabled by default for
@@ -2801,9 +2801,10 @@
   URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_TIMED_OUT);
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&AddHstsHost,
-                 base::RetainedRef(browser()->profile()->GetRequestContext()),
-                 http_timeout_url.host()));
+      base::BindOnce(
+          &AddHstsHost,
+          base::RetainedRef(browser()->profile()->GetRequestContext()),
+          http_timeout_url.host()));
 
   SlowLoadBehindCaptivePortal(browser(), true, http_timeout_url, 1, 1);
   Login(browser(), 1, 0);
diff --git a/chrome/browser/captive_portal/captive_portal_tab_reloader.cc b/chrome/browser/captive_portal/captive_portal_tab_reloader.cc
index d66c57a0..be2efc9 100644
--- a/chrome/browser/captive_portal/captive_portal_tab_reloader.cc
+++ b/chrome/browser/captive_portal/captive_portal_tab_reloader.cc
@@ -103,8 +103,8 @@
   // issues.
   if (state_ == STATE_NEEDS_RELOAD) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&CaptivePortalTabReloader::ReloadTabIfNeeded,
-                              weak_factory_.GetWeakPtr()));
+        FROM_HERE, base::BindOnce(&CaptivePortalTabReloader::ReloadTabIfNeeded,
+                                  weak_factory_.GetWeakPtr()));
   }
 }
 
diff --git a/chrome/browser/certificate_manager_model.cc b/chrome/browser/certificate_manager_model.cc
index 4aad791..f4cbb0f3 100644
--- a/chrome/browser/certificate_manager_model.cc
+++ b/chrome/browser/certificate_manager_model.cc
@@ -83,13 +83,10 @@
 #endif
 
   BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&CertificateManagerModel::GetCertDBOnIOThread,
-                 browser_context->GetResourceContext(),
-                 observer,
-                 base::Passed(&extension_certificate_provider),
-                 callback));
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
+                     browser_context->GetResourceContext(), observer,
+                     base::Passed(&extension_certificate_provider), callback));
 }
 
 CertificateManagerModel::CertificateManagerModel(
@@ -300,15 +297,10 @@
   is_tpm_available = crypto::IsTPMTokenEnabledForNSS();
 #endif
   BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&CertificateManagerModel::DidGetCertDBOnUIThread,
-                 cert_db,
-                 is_user_db_available,
-                 is_tpm_available,
-                 observer,
-                 base::Passed(&extension_certificate_provider),
-                 callback));
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&CertificateManagerModel::DidGetCertDBOnUIThread, cert_db,
+                     is_user_db_available, is_tpm_available, observer,
+                     base::Passed(&extension_certificate_provider), callback));
 }
 
 // static
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index ce20f98..c52fbbf9 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -1397,9 +1397,8 @@
   // Set up a task to delete old WebRTC log files for all profiles. Use a delay
   // to reduce the impact on startup time.
   BrowserThread::PostDelayedTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles),
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles),
       base::TimeDelta::FromMinutes(1));
 #endif  // BUILDFLAG(ENABLE_WEBRTC)
 
@@ -1408,8 +1407,8 @@
     web_usb_detector_.reset(new WebUsbDetector());
     BrowserThread::PostAfterStartupTask(
         FROM_HERE, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
-        base::Bind(&WebUsbDetector::Initialize,
-                   base::Unretained(web_usb_detector_.get())));
+        base::BindOnce(&WebUsbDetector::Initialize,
+                       base::Unretained(web_usb_detector_.get())));
   }
 #endif
 
@@ -1446,11 +1445,9 @@
       "LightSpeed", "EarlyInitStartup").empty()) {
     // Try to compute this early on another thread so that we don't spend time
     // during profile load initializing the extensions APIs.
-    BrowserThread::PostTask(
-        BrowserThread::FILE_USER_BLOCKING,
-        FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&extensions::FeatureProvider::GetAPIFeatures)));
+    BrowserThread::PostTask(BrowserThread::FILE_USER_BLOCKING, FROM_HERE,
+                            base::BindOnce(base::IgnoreResult(
+                                &extensions::FeatureProvider::GetAPIFeatures)));
   }
 #endif
 
@@ -1812,10 +1809,8 @@
 #endif  // defined(OS_ANDROID)
 
 #if !defined(DISABLE_NACL)
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(nacl::NaClProcessHost::EarlyStartup));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(nacl::NaClProcessHost::EarlyStartup));
 #endif  // !defined(DISABLE_NACL)
 
   // Make sure initial prefs are recorded
diff --git a/chrome/browser/chrome_browser_main_extra_parts_x11.cc b/chrome/browser/chrome_browser_main_extra_parts_x11.cc
index 993f4f97..48b8aa7 100644
--- a/chrome/browser/chrome_browser_main_extra_parts_x11.cc
+++ b/chrome/browser/chrome_browser_main_extra_parts_x11.cc
@@ -29,7 +29,7 @@
 int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) {
   if (!g_in_x11_io_error_handler) {
     base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&ui::LogErrorEventDescription, d, *error));
+        FROM_HERE, base::BindOnce(&ui::LogErrorEventDescription, d, *error));
   }
   return 0;
 }
diff --git a/chrome/browser/chrome_browser_main_linux.cc b/chrome/browser/chrome_browser_main_linux.cc
index 3252c0e..fadd55cc 100644
--- a/chrome/browser/chrome_browser_main_linux.cc
+++ b/chrome/browser/chrome_browser_main_linux.cc
@@ -50,9 +50,10 @@
   // g_browser_process.  This happens in PreCreateThreads.
   // base::GetLinuxDistro() will initialize its value if needed.
   base::PostTaskWithTraits(
-      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
-                     base::TaskPriority::BACKGROUND),
-      base::Bind(base::IgnoreResult(&base::GetLinuxDistro)));
+      FROM_HERE,
+      base::TaskTraits().MayBlock().WithPriority(
+          base::TaskPriority::BACKGROUND),
+      base::BindOnce(base::IgnoreResult(&base::GetLinuxDistro)));
 #endif
 
   media::AudioManager::SetGlobalAppName(
diff --git a/chrome/browser/chrome_browser_main_posix.cc b/chrome/browser/chrome_browser_main_posix.cc
index c673660c3..03675aeb 100644
--- a/chrome/browser/chrome_browser_main_posix.cc
+++ b/chrome/browser/chrome_browser_main_posix.cc
@@ -87,7 +87,7 @@
     // gotten through browser startup, but are close). Post the task to at which
     // point the message loop is running.
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(&ExitHandler::Exit));
+                            base::BindOnce(&ExitHandler::Exit));
     delete this;
   }
 }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 90d7c25..93dfff2 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1055,8 +1055,9 @@
   // changes the pref). In this case, there will be no threads created and
   // posting will fail. When there are no threads, we can just set the string
   // without worrying about threadsafety.
-  if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-          base::Bind(&SetApplicationLocaleOnIOThread, locale))) {
+  if (!BrowserThread::PostTask(
+          BrowserThread::IO, FROM_HERE,
+          base::BindOnce(&SetApplicationLocaleOnIOThread, locale))) {
     g_io_thread_application_locale.Get() = locale;
   }
 }
@@ -2089,8 +2090,9 @@
   if (!wc_getter.is_null()) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&TabSpecificContentSettings::ServiceWorkerAccessed,
-                   wc_getter, scope, !allow_javascript, !allow_serviceworker));
+        base::BindOnce(&TabSpecificContentSettings::ServiceWorkerAccessed,
+                       wc_getter, scope, !allow_javascript,
+                       !allow_serviceworker));
   }
   return allow_javascript && allow_serviceworker;
 }
@@ -2111,8 +2113,8 @@
       base::Bind(&GetWebContents, render_process_id, render_frame_id);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&TabSpecificContentSettings::CookiesRead, wc_getter, url,
-                 first_party, cookie_list, !allow));
+      base::BindOnce(&TabSpecificContentSettings::CookiesRead, wc_getter, url,
+                     first_party, cookie_list, !allow));
   return allow;
 }
 
@@ -2134,8 +2136,8 @@
       base::Bind(&GetWebContents, render_process_id, render_frame_id);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&TabSpecificContentSettings::CookieChanged, wc_getter, url,
-                 first_party, cookie_line, options, !allow));
+      base::BindOnce(&TabSpecificContentSettings::CookieChanged, wc_getter, url,
+                     first_party, cookie_line, options, !allow));
   return allow;
 }
 
@@ -2198,19 +2200,13 @@
   DCHECK_EQ(1U, process_map.size());
   it = process_map.begin();
   BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&ChromeContentBrowserClient::
-                  RequestFileSystemPermissionOnUIThread,
-                  it->first,
-                  it->second,
-                  url,
-                  allow,
-                  base::Bind(&ChromeContentBrowserClient::FileSystemAccessed,
-                            weak_factory_.GetWeakPtr(),
-                            url,
-                            render_frames,
-                            callback)));
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(
+          &ChromeContentBrowserClient::RequestFileSystemPermissionOnUIThread,
+          it->first, it->second, url, allow,
+          base::Bind(&ChromeContentBrowserClient::FileSystemAccessed,
+                     weak_factory_.GetWeakPtr(), url, render_frames,
+                     callback)));
 }
 
 void ChromeContentBrowserClient::RequestFileSystemPermissionOnUIThread(
@@ -2238,10 +2234,9 @@
   std::vector<std::pair<int, int> >::const_iterator i;
   for (i = render_frames.begin(); i != render_frames.end(); ++i) {
     BrowserThread::PostTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&TabSpecificContentSettings::FileSystemAccessed,
-                   i->first, i->second, url, !allow));
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&TabSpecificContentSettings::FileSystemAccessed,
+                       i->first, i->second, url, !allow));
   }
   callback.Run(allow);
 }
@@ -2262,8 +2257,8 @@
   for (i = render_frames.begin(); i != render_frames.end(); ++i) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&TabSpecificContentSettings::IndexedDBAccessed,
-                   i->first, i->second, url, name, !allow));
+        base::BindOnce(&TabSpecificContentSettings::IndexedDBAccessed, i->first,
+                       i->second, url, name, !allow));
   }
 
   return allow;
@@ -2544,9 +2539,9 @@
           user_gesture)) {
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&HandleFlashDownloadActionOnUIThread,
-                   opener_render_process_id, opener_render_frame_id,
-                   opener_top_level_frame_url));
+        base::BindOnce(&HandleFlashDownloadActionOnUIThread,
+                       opener_render_process_id, opener_render_frame_id,
+                       opener_top_level_frame_url));
     return false;
   }
 #endif
@@ -2563,10 +2558,9 @@
                                             CONTENT_SETTINGS_TYPE_POPUPS,
                                             std::string()) !=
         CONTENT_SETTING_ALLOW) {
-      BrowserThread::PostTask(BrowserThread::UI,
-                              FROM_HERE,
-                              base::Bind(&HandleBlockedPopupOnUIThread,
-                                         blocked_params));
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE,
+          base::BindOnce(&HandleBlockedPopupOnUIThread, blocked_params));
       return false;
     }
   }
diff --git a/chrome/browser/chrome_plugin_browsertest.cc b/chrome/browser/chrome_plugin_browsertest.cc
index 95f1bda..5e6c17b 100644
--- a/chrome/browser/chrome_plugin_browsertest.cc
+++ b/chrome/browser/chrome_plugin_browsertest.cc
@@ -111,9 +111,8 @@
     scoped_refptr<content::MessageLoopRunner> runner =
         new content::MessageLoopRunner;
     BrowserThread::PostTask(
-        BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(&CrashFlashInternal, runner->QuitClosure()));
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&CrashFlashInternal, runner->QuitClosure()));
     runner->Run();
   }
 
@@ -142,9 +141,8 @@
     scoped_refptr<content::MessageLoopRunner> runner =
         new content::MessageLoopRunner;
     BrowserThread::PostTask(
-        BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(&CountPluginProcesses, &actual, runner->QuitClosure()));
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&CountPluginProcesses, &actual, runner->QuitClosure()));
     runner->Run();
     ASSERT_EQ(expected, actual);
   }
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc
index eb29a92d..10a6510 100644
--- a/chrome/browser/chrome_quota_permission_context.cc
+++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -249,8 +249,8 @@
   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::Bind(&ChromeQuotaPermissionContext::RequestQuotaPermission, this,
-                   params, render_process_id, callback));
+        base::BindOnce(&ChromeQuotaPermissionContext::RequestQuotaPermission,
+                       this, params, render_process_id, callback));
     return;
   }
 
@@ -299,8 +299,9 @@
   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&ChromeQuotaPermissionContext::DispatchCallbackOnIOThread,
-                   this, callback, response));
+        base::BindOnce(
+            &ChromeQuotaPermissionContext::DispatchCallbackOnIOThread, this,
+            callback, response));
     return;
   }
 
diff --git a/chrome/browser/chrome_site_per_process_browsertest.cc b/chrome/browser/chrome_site_per_process_browsertest.cc
index 905d5d4..e426d21 100644
--- a/chrome/browser/chrome_site_per_process_browsertest.cc
+++ b/chrome/browser/chrome_site_per_process_browsertest.cc
@@ -553,8 +553,8 @@
   void HandleMessage(int, int, const base::string16& text) {
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::Bind(&TestSpellCheckMessageFilter::HandleMessageOnUI, this,
-                   text));
+        base::BindOnce(&TestSpellCheckMessageFilter::HandleMessageOnUI, this,
+                       text));
   }
 
   void HandleMessageOnUI(const base::string16& text) {
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
index 40d7840..b9b9ba15 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
@@ -8,12 +8,11 @@
 #include "base/logging.h"
 #include "chrome/browser/speech/tts_controller.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
-#include "chrome/common/extensions/api/automation_api_constants.h"
 #include "content/public/browser/browser_thread.h"
-#include "ui/accessibility/ax_tree_id_registry.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
 #include "ui/events/event.h"
+#include "ui/views/focus/view_storage.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
@@ -122,15 +121,42 @@
 
   CancelEvent(event);
 
-  ui::AXTreeIDRegistry* registry = ui::AXTreeIDRegistry::GetInstance();
-  ui::AXHostDelegate* delegate =
-      registry->GetHostDelegate(extensions::api::automation::kDesktopTreeID);
-  if (delegate) {
-    ui::AXActionData action;
-    action.action = ui::AX_ACTION_HIT_TEST;
-    action.target_point = event->root_location();
-    action.hit_test_event_to_fire = ax_event;
-    delegate->PerformAction(action);
+  // Find the View to post the accessibility event on.
+  aura::Window* event_target = static_cast<aura::Window*>(event->target());
+  aura::Window* hit_window = event_target;
+  if (!hit_window)
+    return;
+
+  views::Widget* hit_widget = views::Widget::GetWidgetForNativeView(hit_window);
+  while (!hit_widget) {
+    hit_window = hit_window->parent();
+    if (!hit_window)
+      break;
+
+    hit_widget = views::Widget::GetWidgetForNativeView(hit_window);
+  }
+
+  if (!hit_window || !hit_widget)
+    return;
+
+  gfx::Point window_location = event->location();
+  aura::Window::ConvertPointToTarget(event_target, hit_window,
+                                     &window_location);
+
+  views::View* root_view = hit_widget->GetRootView();
+  views::View* hit_view = root_view->GetEventHandlerForPoint(window_location);
+
+  if (hit_view) {
+    // Send the accessibility event, then save the view so we can post the
+    // cancel event on the same view if possible.
+    hit_view->NotifyAccessibilityEvent(ax_event, true);
+    if (!last_view_storage_id_) {
+      last_view_storage_id_ =
+          views::ViewStorage::GetInstance()->CreateStorageID();
+    }
+    views::ViewStorage::GetInstance()->RemoveView(last_view_storage_id_);
+    views::ViewStorage::GetInstance()->StoreView(last_view_storage_id_,
+                                                 hit_view);
   }
 }
 
@@ -143,8 +169,20 @@
 }
 
 void SelectToSpeakEventHandler::SendCancelAXEvent() {
-  AutomationManagerAura::GetInstance()->HandleEvent(
-      nullptr, nullptr, ui::AX_EVENT_MOUSE_CANCELED);
+  // If the user releases Search while the button is still down, cancel
+  // the Select-to-speak gesture. Try to post it on the same View that
+  // was last targeted, but if that's impossible, post it on the desktop.
+  views::View* last_view =
+      last_view_storage_id_
+          ? views::ViewStorage::GetInstance()->RetrieveView(
+                last_view_storage_id_)
+          : nullptr;
+  if (last_view) {
+    last_view->NotifyAccessibilityEvent(ui::AX_EVENT_MOUSE_CANCELED, true);
+  } else {
+    AutomationManagerAura::GetInstance()->HandleEvent(
+        nullptr, nullptr, ui::AX_EVENT_MOUSE_CANCELED);
+  }
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
index 048e2cf..012fb9e 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
@@ -62,6 +62,8 @@
   // is pressed, and only cleared when all keys are released.
   std::set<ui::KeyboardCode> keys_pressed_together_;
 
+  int last_view_storage_id_ = 0;
+
   DISALLOW_COPY_AND_ASSIGN(SelectToSpeakEventHandler);
 };
 
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc
index d3a9865..20167745 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc
@@ -219,6 +219,30 @@
   EXPECT_FALSE(event_capturer_.last_key_event());
 }
 
+TEST_F(SelectToSpeakEventHandlerTest, SearchPlusMouseThenCancel) {
+  // If the user holds the Search key and then presses the mouse button,
+  // but then releases the Search key first while the mouse is still down,
+  // a cancel AX event is sent and the subsequent mouse up is canceled too.
+
+  generator_->PressKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(event_capturer_.last_key_event());
+  EXPECT_FALSE(event_capturer_.last_key_event()->handled());
+
+  generator_->set_current_location(gfx::Point(100, 12));
+  generator_->PressLeftButton();
+  EXPECT_FALSE(event_capturer_.last_mouse_event());
+  EXPECT_TRUE(event_delegate_->CapturedAXEvent(ui::AX_EVENT_MOUSE_PRESSED));
+
+  event_capturer_.Reset();
+  generator_->ReleaseKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
+  EXPECT_FALSE(event_capturer_.last_key_event());
+
+  EXPECT_TRUE(event_delegate_->CapturedAXEvent(ui::AX_EVENT_MOUSE_CANCELED));
+
+  generator_->ReleaseLeftButton();
+  EXPECT_FALSE(event_capturer_.last_mouse_event());
+}
+
 TEST_F(SelectToSpeakEventHandlerTest, SearchPlusKeyIgnoresClicks) {
   // If the user presses the Search key and then some other key,
   // we should assume the user does not want select-to-speak, and
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 f6c9b3e..ec632e4 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
@@ -296,7 +296,7 @@
 
   TimezoneSettings::GetInstance()->AddObserver(this);
 
-  if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     device::BluetoothAdapterFactory::GetAdapter(
         base::Bind(&ArcSettingsServiceImpl::OnBluetoothAdapterInitialized,
                    weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc
index 2499e1d..5c9e797 100644
--- a/chrome/browser/content_settings/content_settings_browsertest.cc
+++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -96,7 +96,7 @@
   void SetUpOnMainThread() override {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
+        base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
   }
 
   // Check the cookie for the given URL in an incognito window.
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc
index 139fed6e..bc28906 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -355,10 +355,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   default_handlers_.erase(scheme);
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&IOThreadDelegate::ClearDefault, io_thread_delegate_, scheme));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(&IOThreadDelegate::ClearDefault,
+                                         io_thread_delegate_, scheme));
   Save();
   NotifyChanged();
 }
@@ -588,8 +587,8 @@
     } else {
       BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
-          base::Bind(&IOThreadDelegate::ClearDefault, io_thread_delegate_,
-                     q->second.protocol()));
+          base::BindOnce(&IOThreadDelegate::ClearDefault, io_thread_delegate_,
+                         q->second.protocol()));
 
       default_handlers_.erase(q);
     }
@@ -623,9 +622,8 @@
   }
   enabled_ = true;
   BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&IOThreadDelegate::Enable, io_thread_delegate_));
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&IOThreadDelegate::Enable, io_thread_delegate_));
 
   ProtocolHandlerMap::const_iterator p;
   for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
@@ -642,9 +640,8 @@
   }
   enabled_ = false;
   BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&IOThreadDelegate::Disable, io_thread_delegate_));
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&IOThreadDelegate::Disable, io_thread_delegate_));
 
   ProtocolHandlerMap::const_iterator p;
   for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
@@ -725,10 +722,9 @@
   default_handlers_.erase(handler.protocol());
   default_handlers_.insert(std::make_pair(handler.protocol(), handler));
   PromoteHandler(handler);
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&IOThreadDelegate::SetDefault, io_thread_delegate_, handler));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(&IOThreadDelegate::SetDefault,
+                                         io_thread_delegate_, handler));
 }
 
 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
index 618ec4e6..db63b72 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -54,11 +54,9 @@
     const GURL& url,
     net::URLRequestJobFactory* interceptor) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(BrowserThread::IO,
-                          FROM_HERE,
-                          base::Bind(AssertInterceptedIO,
-                                     url,
-                                     base::Unretained(interceptor)));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(AssertInterceptedIO, url, base::Unretained(interceptor)));
   base::RunLoop().RunUntilIdle();
 }
 
@@ -113,12 +111,9 @@
     bool expected,
     ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(BrowserThread::IO,
-                          FROM_HERE,
-                          base::Bind(AssertWillHandleIO,
-                                     scheme,
-                                     expected,
-                                     base::Unretained(interceptor)));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(AssertWillHandleIO, scheme, expected,
+                                         base::Unretained(interceptor)));
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/chrome/browser/data_usage/tab_id_annotator_unittest.cc b/chrome/browser/data_usage/tab_id_annotator_unittest.cc
index 347fae0..d113823 100644
--- a/chrome/browser/data_usage/tab_id_annotator_unittest.cc
+++ b/chrome/browser/data_usage/tab_id_annotator_unittest.cc
@@ -80,7 +80,7 @@
   // aren't thread safe.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&base::RunLoop::Quit, base::Unretained(ui_run_loop)));
+      base::BindOnce(&base::RunLoop::Quit, base::Unretained(ui_run_loop)));
 }
 
 // Tests that for a sample URLRequest, associated with the given
@@ -137,9 +137,9 @@
   base::RunLoop ui_run_loop;
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&TestAnnotateOnIOThread, &ui_run_loop,
-                 -1 /* render_process_id */, -1 /* render_frame_id */,
-                 -1 /* expected_tab_id */));
+      base::BindOnce(&TestAnnotateOnIOThread, &ui_run_loop,
+                     -1 /* render_process_id */, -1 /* render_frame_id */,
+                     -1 /* expected_tab_id */));
   ui_run_loop.Run();
 }
 
@@ -150,10 +150,10 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&TestAnnotateOnIOThread, &ui_run_loop,
-                 web_contents()->GetMainFrame()->GetProcess()->GetID(),
-                 web_contents()->GetMainFrame()->GetRoutingID(),
-                 -1 /* expected_tab_id */));
+      base::BindOnce(&TestAnnotateOnIOThread, &ui_run_loop,
+                     web_contents()->GetMainFrame()->GetProcess()->GetID(),
+                     web_contents()->GetMainFrame()->GetRoutingID(),
+                     -1 /* expected_tab_id */));
   ui_run_loop.Run();
 }
 
@@ -167,10 +167,10 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&TestAnnotateOnIOThread, &ui_run_loop,
-                 web_contents()->GetMainFrame()->GetProcess()->GetID(),
-                 web_contents()->GetMainFrame()->GetRoutingID(),
-                 expected_tab_id));
+      base::BindOnce(&TestAnnotateOnIOThread, &ui_run_loop,
+                     web_contents()->GetMainFrame()->GetProcess()->GetID(),
+                     web_contents()->GetMainFrame()->GetRoutingID(),
+                     expected_tab_id));
   ui_run_loop.Run();
 }
 
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc
index 54cb31c..9f305a8 100644
--- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc
+++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_service.cc
@@ -83,11 +83,11 @@
 
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&ChromeDataUseAscriber::RenderFrameCreated,
-                 base::Unretained(ascriber_),
-                 render_frame_host->GetProcess()->GetID(),
-                 render_frame_host->GetRoutingID(), main_render_process_id,
-                 main_render_frame_id));
+      base::BindOnce(&ChromeDataUseAscriber::RenderFrameCreated,
+                     base::Unretained(ascriber_),
+                     render_frame_host->GetProcess()->GetID(),
+                     render_frame_host->GetRoutingID(), main_render_process_id,
+                     main_render_frame_id));
 }
 
 void ChromeDataUseAscriberService::RenderFrameDeleted(
@@ -115,11 +115,11 @@
 
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&ChromeDataUseAscriber::RenderFrameDeleted,
-                 base::Unretained(ascriber_),
-                 render_frame_host->GetProcess()->GetID(),
-                 render_frame_host->GetRoutingID(), main_render_process_id,
-                 main_render_frame_id));
+      base::BindOnce(&ChromeDataUseAscriber::RenderFrameDeleted,
+                     base::Unretained(ascriber_),
+                     render_frame_host->GetProcess()->GetID(),
+                     render_frame_host->GetRoutingID(), main_render_process_id,
+                     main_render_frame_id));
 }
 
 void ChromeDataUseAscriberService::DidStartNavigation(
@@ -133,11 +133,11 @@
   content::WebContents* web_contents = navigation_handle->GetWebContents();
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&ChromeDataUseAscriber::DidStartMainFrameNavigation,
-                 base::Unretained(ascriber_), navigation_handle->GetURL(),
-                 web_contents->GetRenderProcessHost()->GetID(),
-                 web_contents->GetMainFrame()->GetRoutingID(),
-                 navigation_handle));
+      base::BindOnce(&ChromeDataUseAscriber::DidStartMainFrameNavigation,
+                     base::Unretained(ascriber_), navigation_handle->GetURL(),
+                     web_contents->GetRenderProcessHost()->GetID(),
+                     web_contents->GetMainFrame()->GetRoutingID(),
+                     navigation_handle));
 }
 
 void ChromeDataUseAscriberService::ReadyToCommitNavigation(
@@ -153,14 +153,14 @@
   content::WebContents* web_contents = navigation_handle->GetWebContents();
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&ChromeDataUseAscriber::ReadyToCommitMainFrameNavigation,
-                 base::Unretained(ascriber_), navigation_handle->GetURL(),
-                 navigation_handle->GetGlobalRequestID(),
-                 web_contents->GetRenderProcessHost()->GetID(),
-                 web_contents->GetMainFrame()->GetRoutingID(),
-                 !navigation_handle->HasCommitted() ||
-                     navigation_handle->IsSameDocument(),
-                 navigation_handle));
+      base::BindOnce(&ChromeDataUseAscriber::ReadyToCommitMainFrameNavigation,
+                     base::Unretained(ascriber_), navigation_handle->GetURL(),
+                     navigation_handle->GetGlobalRequestID(),
+                     web_contents->GetRenderProcessHost()->GetID(),
+                     web_contents->GetMainFrame()->GetRoutingID(),
+                     !navigation_handle->HasCommitted() ||
+                         navigation_handle->IsSameDocument(),
+                     navigation_handle));
 }
 
 void ChromeDataUseAscriberService::DidFinishNavigation(
@@ -177,11 +177,11 @@
   content::WebContents* web_contents = navigation_handle->GetWebContents();
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&ChromeDataUseAscriber::DidFinishNavigation,
-                 base::Unretained(ascriber_),
-                 web_contents->GetRenderProcessHost()->GetID(),
-                 web_contents->GetMainFrame()->GetRoutingID(),
-                 navigation_handle->GetPageTransition()));
+      base::BindOnce(&ChromeDataUseAscriber::DidFinishNavigation,
+                     base::Unretained(ascriber_),
+                     web_contents->GetRenderProcessHost()->GetID(),
+                     web_contents->GetMainFrame()->GetRoutingID(),
+                     navigation_handle->GetPageTransition()));
 }
 
 void ChromeDataUseAscriberService::SetDataUseAscriber(
@@ -218,10 +218,10 @@
 
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&ChromeDataUseAscriber::WasShownOrHidden,
-                 base::Unretained(ascriber_),
-                 main_render_frame_host->GetProcess()->GetID(),
-                 main_render_frame_host->GetRoutingID(), visible));
+      base::BindOnce(&ChromeDataUseAscriber::WasShownOrHidden,
+                     base::Unretained(ascriber_),
+                     main_render_frame_host->GetProcess()->GetID(),
+                     main_render_frame_host->GetRoutingID(), visible));
 }
 
 void ChromeDataUseAscriberService::RenderFrameHostChanged(
@@ -233,10 +233,11 @@
   if (old_host) {
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&ChromeDataUseAscriber::RenderFrameHostChanged,
-                   base::Unretained(ascriber_), old_host->GetProcess()->GetID(),
-                   old_host->GetRoutingID(), new_host->GetProcess()->GetID(),
-                   new_host->GetRoutingID()));
+        base::BindOnce(
+            &ChromeDataUseAscriber::RenderFrameHostChanged,
+            base::Unretained(ascriber_), old_host->GetProcess()->GetID(),
+            old_host->GetRoutingID(), new_host->GetProcess()->GetID(),
+            new_host->GetRoutingID()));
   }
 }
 
diff --git a/chrome/browser/engagement/site_engagement_service.cc b/chrome/browser/engagement/site_engagement_service.cc
index 360d90b..70ecaf539 100644
--- a/chrome/browser/engagement/site_engagement_service.cc
+++ b/chrome/browser/engagement/site_engagement_service.cc
@@ -132,10 +132,11 @@
 SiteEngagementService::SiteEngagementService(Profile* profile)
     : SiteEngagementService(profile, base::MakeUnique<base::DefaultClock>()) {
   content::BrowserThread::PostAfterStartupTask(
-      FROM_HERE, content::BrowserThread::GetTaskRunnerForThread(
-                     content::BrowserThread::UI),
-      base::Bind(&SiteEngagementService::AfterStartupTask,
-                 weak_factory_.GetWeakPtr()));
+      FROM_HERE,
+      content::BrowserThread::GetTaskRunnerForThread(
+          content::BrowserThread::UI),
+      base::BindOnce(&SiteEngagementService::AfterStartupTask,
+                     weak_factory_.GetWeakPtr()));
 
   if (!g_updated_from_variations) {
     SiteEngagementScore::UpdateFromVariations(kEngagementParams);
diff --git a/chrome/browser/engagement/site_engagement_service_unittest.cc b/chrome/browser/engagement/site_engagement_service_unittest.cc
index 617df7f23..740e9c14 100644
--- a/chrome/browser/engagement/site_engagement_service_unittest.cc
+++ b/chrome/browser/engagement/site_engagement_service_unittest.cc
@@ -207,9 +207,9 @@
     base::RunLoop run_loop;
     content::BrowserThread::PostTaskAndReply(
         thread_id, FROM_HERE,
-        base::Bind(&SiteEngagementServiceTest::CheckScoreFromSettings,
-                   base::Unretained(this), settings_map, url, &score),
-                   run_loop.QuitClosure());
+        base::BindOnce(&SiteEngagementServiceTest::CheckScoreFromSettings,
+                       base::Unretained(this), settings_map, url, &score),
+        run_loop.QuitClosure());
     run_loop.Run();
     return score;
   }
diff --git a/chrome/browser/experiments/memory_ablation_experiment.cc b/chrome/browser/experiments/memory_ablation_experiment.cc
index 6cd3082..b5abe0a 100644
--- a/chrome/browser/experiments/memory_ablation_experiment.cc
+++ b/chrome/browser/experiments/memory_ablation_experiment.cc
@@ -58,8 +58,8 @@
     size_t memory_size) {
   task_runner->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&MemoryAblationExperiment::AllocateMemory,
-                 base::Unretained(this), memory_size),
+      base::BindOnce(&MemoryAblationExperiment::AllocateMemory,
+                     base::Unretained(this), memory_size),
       base::TimeDelta::FromSeconds(kMemoryAblationDelaySeconds));
 }
 
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index 42bbe9f..8ccffdc 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -233,11 +233,6 @@
       << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopHitTest) {
-  ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "hit_test.html"))
-      << message_;
-}
-
 // Flaky, see http://crbug.com/435449
 IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopLoadTabs) {
   ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "load_tabs.html"))
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 3871193..916d440 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -44,7 +44,6 @@
 
 #if defined(USE_AURA)
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
-#include "ui/aura/env.h"
 #endif
 
 namespace extensions {
@@ -178,9 +177,6 @@
       params.event_type = event.event_type;
       params.update = event.update;
       params.event_from = event.event_from;
-#if defined(USE_AURA)
-      params.mouse_location = aura::Env::GetInstance()->last_mouse_location();
-#endif
 
       AutomationEventRouter* router = AutomationEventRouter::GetInstance();
       router->DispatchAccessibilityEvent(params);
diff --git a/chrome/browser/favicon/content_favicon_driver_browsertest.cc b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
index 807ac0f..d1d15fd42 100644
--- a/chrome/browser/favicon/content_favicon_driver_browsertest.cc
+++ b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
@@ -147,8 +147,8 @@
       // immediately after OnFaviconUpdated() is called. Post a task to check if
       // we can stop waiting.
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(&PendingTaskWaiter::EndLoopIfCanStopWaiting,
-                                weak_factory_.GetWeakPtr()));
+          FROM_HERE, base::BindOnce(&PendingTaskWaiter::EndLoopIfCanStopWaiting,
+                                    weak_factory_.GetWeakPtr()));
     }
   }
 
diff --git a/chrome/browser/feedback/feedback_profile_observer.cc b/chrome/browser/feedback/feedback_profile_observer.cc
index 7e43034..dc4499e 100644
--- a/chrome/browser/feedback/feedback_profile_observer.cc
+++ b/chrome/browser/feedback/feedback_profile_observer.cc
@@ -51,9 +51,9 @@
 void FeedbackProfileObserver::QueueSingleReport(
     feedback::FeedbackUploader* uploader,
     const std::string& data) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE, base::Bind(&FeedbackUploader::QueueReport,
-                                               uploader->AsWeakPtr(), data));
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::BindOnce(&FeedbackUploader::QueueReport,
+                                         uploader->AsWeakPtr(), data));
 }
 
 void FeedbackProfileObserver::QueueUnsentReports(
@@ -61,9 +61,10 @@
   feedback::FeedbackUploader* uploader =
       feedback::FeedbackUploaderFactory::GetForBrowserContext(context);
   base::PostTaskWithTraits(
-      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
-                     base::TaskPriority::BACKGROUND),
-      base::Bind(
+      FROM_HERE,
+      base::TaskTraits().MayBlock().WithPriority(
+          base::TaskPriority::BACKGROUND),
+      base::BindOnce(
           &FeedbackReport::LoadReportsAndQueue,
           uploader->GetFeedbackReportsPath(),
           base::Bind(&FeedbackProfileObserver::QueueSingleReport, uploader)));
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc
index 91aa51e1..a6019952 100644
--- a/chrome/browser/file_select_helper.cc
+++ b/chrome/browser/file_select_helper.cc
@@ -339,9 +339,8 @@
 }
 
 void FileSelectHelper::DeleteTemporaryFiles() {
-  BrowserThread::PostTask(BrowserThread::FILE,
-                          FROM_HERE,
-                          base::Bind(&DeleteFiles, temporary_files_));
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          base::BindOnce(&DeleteFiles, temporary_files_));
   temporary_files_.clear();
 }
 
@@ -471,8 +470,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
-      base::Bind(&FileSelectHelper::GetFileTypesOnFileThread, this,
-                 base::Passed(&params)));
+      base::BindOnce(&FileSelectHelper::GetFileTypesOnFileThread, this,
+                     base::Passed(&params)));
 
   // Because this class returns notifications to the RenderViewHost, it is
   // difficult for callers to know how long to keep a reference to this
@@ -491,8 +490,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&FileSelectHelper::GetSanitizedFilenameOnUIThread, this,
-                 base::Passed(&params)));
+      base::BindOnce(&FileSelectHelper::GetSanitizedFilenameOnUIThread, this,
+                     base::Passed(&params)));
 }
 
 void FileSelectHelper::GetSanitizedFilenameOnUIThread(
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 0fa90f75..e42bd86f5 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2915,8 +2915,14 @@
 const char kQuickUnlockPin[] = "Quick Unlock (PIN)";
 
 const char kQuickUnlockPinDescription[] =
-    "Enabling PIN quick unlock allows you to use a PIN to unlock your "
-    "Chromebook on the lock screen after you have signed into your device.";
+    "Enabling PIN quick unlock allows you to use a PIN to unlock your ChromeOS "
+    "device on the lock screen after you have signed into your device.";
+
+const char kQuickUnlockPinSignin[] = "Enable PIN when logging in.";
+
+const char kQuickUnlockPinSigninDescription[] =
+    "Enabling PIN allows you to use a PIN to sign in and unlock your ChromeOS "
+    "device. After changing this flag PIN needs to be set up again.";
 
 const char kQuickUnlockFingerprint[] = "Quick Unlock (Fingerprint)";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e255b37..e271f36f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -3162,12 +3162,18 @@
 // Description for the flag to enable wake on packets.
 extern const char kWakeOnPacketsDescription[];
 
-// Title of the flag used to enable quick unlock pin.
+// Title of the flag used to enable quick unlock PIN.
 extern const char kQuickUnlockPin[];
 
-// Description of the flag used to enable quick unlock pin.
+// Description of the flag used to enable quick unlock PIN.
 extern const char kQuickUnlockPinDescription[];
 
+// Title of the flag used to enable PIN on signin.
+extern const char kQuickUnlockPinSignin[];
+
+// Description of the flag used to enable PIN on signin.
+extern const char kQuickUnlockPinSigninDescription[];
+
 // Title of the flag used to enable quick unlock fingerprint.
 extern const char kQuickUnlockFingerprint[];
 
diff --git a/chrome/browser/gcm/fake_gcm_profile_service.cc b/chrome/browser/gcm/fake_gcm_profile_service.cc
index 58c18f05..63276da6 100644
--- a/chrome/browser/gcm/fake_gcm_profile_service.cc
+++ b/chrome/browser/gcm/fake_gcm_profile_service.cc
@@ -104,9 +104,9 @@
   ++registration_count_;
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&CustomFakeGCMDriver::DoRegister, weak_factory_.GetWeakPtr(),
-                 app_id, sender_ids, registration_id));
+      FROM_HERE, base::BindOnce(&CustomFakeGCMDriver::DoRegister,
+                                weak_factory_.GetWeakPtr(), app_id, sender_ids,
+                                registration_id));
 }
 
 void FakeGCMProfileService::CustomFakeGCMDriver::DoRegister(
@@ -131,8 +131,8 @@
     service_->unregister_responses_.pop_front();
   }
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&CustomFakeGCMDriver::UnregisterFinished,
-                            weak_factory_.GetWeakPtr(), app_id, result));
+      FROM_HERE, base::BindOnce(&CustomFakeGCMDriver::UnregisterFinished,
+                                weak_factory_.GetWeakPtr(), app_id, result));
 }
 
 void FakeGCMProfileService::CustomFakeGCMDriver::UnregisterWithSenderIdImpl(
@@ -150,8 +150,8 @@
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&CustomFakeGCMDriver::DoSend, weak_factory_.GetWeakPtr(),
-                 app_id, receiver_id, message));
+      base::BindOnce(&CustomFakeGCMDriver::DoSend, weak_factory_.GetWeakPtr(),
+                     app_id, receiver_id, message));
 }
 
 void FakeGCMProfileService::CustomFakeGCMDriver::DoSend(
diff --git a/chrome/browser/geolocation/access_token_store_browsertest.cc b/chrome/browser/geolocation/access_token_store_browsertest.cc
index 2e588d4..3ad8692 100644
--- a/chrome/browser/geolocation/access_token_store_browsertest.cc
+++ b/chrome/browser/geolocation/access_token_store_browsertest.cc
@@ -55,9 +55,8 @@
 
   BrowserThread::PostTask(
       kExpectedClientThreadId, FROM_HERE,
-      base::Bind(
-          &AccessTokenStore::LoadAccessTokens,
-          token_store_,
+      base::BindOnce(
+          &AccessTokenStore::LoadAccessTokens, token_store_,
           base::Bind(
               &GeolocationAccessTokenStoreTest::OnAccessTokenStoresLoaded,
               base::Unretained(this))));
diff --git a/chrome/browser/geolocation/chrome_access_token_store.cc b/chrome/browser/geolocation/chrome_access_token_store.cc
index 0aaa8301..633344e 100644
--- a/chrome/browser/geolocation/chrome_access_token_store.cc
+++ b/chrome/browser/geolocation/chrome_access_token_store.cc
@@ -47,10 +47,9 @@
 
   void Run() {
     BrowserThread::PostTaskAndReply(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&TokenLoadingJob::PerformWorkOnUIThread, this),
-        base::Bind(&TokenLoadingJob::RespondOnOriginatingThread, this));
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&TokenLoadingJob::PerformWorkOnUIThread, this),
+        base::BindOnce(&TokenLoadingJob::RespondOnOriginatingThread, this));
   }
 
  private:
@@ -127,5 +126,5 @@
     const base::string16& access_token) {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&SetAccessTokenOnUIThread, server_url, access_token));
+      base::BindOnce(&SetAccessTokenOnUIThread, server_url, access_token));
 }
diff --git a/chrome/browser/predictors/autocomplete_action_predictor.cc b/chrome/browser/predictors/autocomplete_action_predictor.cc
index eed8b9a..ac80bb6 100644
--- a/chrome/browser/predictors/autocomplete_action_predictor.cc
+++ b/chrome/browser/predictors/autocomplete_action_predictor.cc
@@ -329,9 +329,10 @@
       new std::vector<AutocompleteActionPredictorTable::Row>();
   content::BrowserThread::PostTaskAndReply(
       content::BrowserThread::DB, FROM_HERE,
-      base::Bind(&AutocompleteActionPredictorTable::GetAllRows, table_, rows),
-      base::Bind(&AutocompleteActionPredictor::CreateCaches, AsWeakPtr(),
-                 base::Owned(rows)));
+      base::BindOnce(&AutocompleteActionPredictorTable::GetAllRows, table_,
+                     rows),
+      base::BindOnce(&AutocompleteActionPredictor::CreateCaches, AsWeakPtr(),
+                     base::Owned(rows)));
 }
 
 void AutocompleteActionPredictor::DeleteAllRows() {
@@ -343,7 +344,8 @@
   if (table_.get()) {
     content::BrowserThread::PostTask(
         content::BrowserThread::DB, FROM_HERE,
-        base::Bind(&AutocompleteActionPredictorTable::DeleteAllRows, table_));
+        base::BindOnce(&AutocompleteActionPredictorTable::DeleteAllRows,
+                       table_));
   }
 
   UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.DatabaseAction",
@@ -373,8 +375,8 @@
   if (table_.get()) {
     content::BrowserThread::PostTask(
         content::BrowserThread::DB, FROM_HERE,
-        base::Bind(&AutocompleteActionPredictorTable::DeleteRows, table_,
-                   id_list));
+        base::BindOnce(&AutocompleteActionPredictorTable::DeleteRows, table_,
+                       id_list));
   }
 
   UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.DatabaseAction",
@@ -414,9 +416,10 @@
   }
 
   if (table_.get()) {
-    content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE,
-        base::Bind(&AutocompleteActionPredictorTable::AddAndUpdateRows,
-                   table_, rows_to_add, rows_to_update));
+    content::BrowserThread::PostTask(
+        content::BrowserThread::DB, FROM_HERE,
+        base::BindOnce(&AutocompleteActionPredictorTable::AddAndUpdateRows,
+                       table_, rows_to_add, rows_to_update));
   }
 }
 
@@ -472,9 +475,10 @@
   std::vector<AutocompleteActionPredictorTable::Row::Id> ids_to_delete;
   DeleteOldIdsFromCaches(url_db, &ids_to_delete);
 
-  content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE,
-      base::Bind(&AutocompleteActionPredictorTable::DeleteRows, table_,
-                 ids_to_delete));
+  content::BrowserThread::PostTask(
+      content::BrowserThread::DB, FROM_HERE,
+      base::BindOnce(&AutocompleteActionPredictorTable::DeleteRows, table_,
+                     ids_to_delete));
 
   FinishInitialization();
   if (incognito_predictor_)
diff --git a/chrome/browser/predictors/predictor_database.cc b/chrome/browser/predictors/predictor_database.cc
index 3cd3824a..eb71aff 100644
--- a/chrome/browser/predictors/predictor_database.cc
+++ b/chrome/browser/predictors/predictor_database.cc
@@ -132,8 +132,9 @@
 
 PredictorDatabase::PredictorDatabase(Profile* profile)
     : db_(new PredictorDatabaseInternal(profile)) {
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&PredictorDatabaseInternal::Initialize, db_));
+  BrowserThread::PostTask(
+      BrowserThread::DB, FROM_HERE,
+      base::BindOnce(&PredictorDatabaseInternal::Initialize, db_));
 }
 
 PredictorDatabase::~PredictorDatabase() {
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc
index ae43153..58d01b5 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -579,16 +579,16 @@
 
   BrowserThread::PostTaskAndReply(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
-                 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr,
-                 host_redirect_data_map_ptr, manifest_data_map_ptr,
-                 origin_data_map_ptr),
-      base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
-                 base::Passed(&url_data_map), base::Passed(&host_data_map),
-                 base::Passed(&url_redirect_data_map),
-                 base::Passed(&host_redirect_data_map),
-                 base::Passed(&manifest_data_map),
-                 base::Passed(&origin_data_map)));
+      base::BindOnce(&ResourcePrefetchPredictorTables::GetAllData, tables_,
+                     url_data_map_ptr, host_data_map_ptr,
+                     url_redirect_data_map_ptr, host_redirect_data_map_ptr,
+                     manifest_data_map_ptr, origin_data_map_ptr),
+      base::BindOnce(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
+                     base::Passed(&url_data_map), base::Passed(&host_data_map),
+                     base::Passed(&url_redirect_data_map),
+                     base::Passed(&host_redirect_data_map),
+                     base::Passed(&manifest_data_map),
+                     base::Passed(&origin_data_map)));
 }
 
 void ResourcePrefetchPredictor::RecordURLRequest(
@@ -666,8 +666,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch,
-                 prefetch_manager_, url, prediction.subresource_urls));
+      base::BindOnce(&ResourcePrefetcherManager::MaybeAddPrefetch,
+                     prefetch_manager_, url, prediction.subresource_urls));
 
   if (observer_)
     observer_->OnPrefetchingStarted(url);
@@ -688,8 +688,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch,
-                 prefetch_manager_, url));
+      base::BindOnce(&ResourcePrefetcherManager::MaybeRemovePrefetch,
+                     prefetch_manager_, url));
 
   if (observer_)
     observer_->OnPrefetchingStopped(url);
@@ -1091,8 +1091,9 @@
   manifest_table_cache_->clear();
   origin_table_cache_->clear();
 
-  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-      base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_));
+  BrowserThread::PostTask(
+      BrowserThread::DB, FROM_HERE,
+      base::BindOnce(&ResourcePrefetchPredictorTables::DeleteAllData, tables_));
 }
 
 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
@@ -1144,29 +1145,30 @@
   if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
-                   tables_, urls_to_delete, hosts_to_delete));
+        base::BindOnce(&ResourcePrefetchPredictorTables::DeleteResourceData,
+                       tables_, urls_to_delete, hosts_to_delete));
   }
 
   if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData,
-                   tables_, url_redirects_to_delete, host_redirects_to_delete));
+        base::BindOnce(&ResourcePrefetchPredictorTables::DeleteRedirectData,
+                       tables_, url_redirects_to_delete,
+                       host_redirects_to_delete));
   }
 
   if (!manifest_hosts_to_delete.empty()) {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData,
-                   tables_, manifest_hosts_to_delete));
+        base::BindOnce(&ResourcePrefetchPredictorTables::DeleteManifestData,
+                       tables_, manifest_hosts_to_delete));
   }
 
   if (!origin_hosts_to_delete.empty()) {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
-                   origin_hosts_to_delete));
+        base::BindOnce(&ResourcePrefetchPredictorTables::DeleteOriginData,
+                       tables_, origin_hosts_to_delete));
   }
 }
 
@@ -1189,7 +1191,7 @@
   data_map->erase(key_to_delete);
   BrowserThread::PostTask(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint,
           tables_, key_to_delete, key_type));
 }
@@ -1213,7 +1215,7 @@
   data_map->erase(key_to_delete);
   BrowserThread::PostTask(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
           tables_, key_to_delete, key_type));
 }
@@ -1234,8 +1236,8 @@
   data_map->erase(oldest_entry);
   BrowserThread::PostTask(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_,
-                 std::vector<std::string>({key_to_delete})));
+      base::BindOnce(&ResourcePrefetchPredictorTables::DeleteManifestData,
+                     tables_, std::vector<std::string>({key_to_delete})));
 }
 
 void ResourcePrefetchPredictor::RemoveOldestEntryInOriginDataMap(
@@ -1256,8 +1258,8 @@
   data_map->erase(key_to_delete);
   BrowserThread::PostTask(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
-                 std::vector<std::string>({key_to_delete})));
+      base::BindOnce(&ResourcePrefetchPredictorTables::DeleteOriginData,
+                     tables_, std::vector<std::string>({key_to_delete})));
 }
 
 void ResourcePrefetchPredictor::OnVisitCountLookup(
@@ -1444,14 +1446,14 @@
     data_map->erase(key);
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(
+        base::BindOnce(
             &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint,
             tables_, key, key_type));
   } else {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::UpdateResourceData,
-                   tables_, data, key_type));
+        base::BindOnce(&ResourcePrefetchPredictorTables::UpdateResourceData,
+                       tables_, data, key_type));
   }
 
   // Predictor learns about both redirected and non-redirected destinations to
@@ -1515,14 +1517,14 @@
     redirect_map->erase(cache_entry);
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(
+        base::BindOnce(
             &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
             tables_, key, key_type));
   } else {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::UpdateRedirectData,
-                   tables_, data, key_type));
+        base::BindOnce(&ResourcePrefetchPredictorTables::UpdateRedirectData,
+                       tables_, data, key_type));
   }
 }
 
@@ -1623,14 +1625,14 @@
     if (!new_entry) {
       BrowserThread::PostTask(
           BrowserThread::DB, FROM_HERE,
-          base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData,
-                     tables_, std::vector<std::string>({host})));
+          base::BindOnce(&ResourcePrefetchPredictorTables::DeleteOriginData,
+                         tables_, std::vector<std::string>({host})));
     }
   } else {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::UpdateOriginData, tables_,
-                   data));
+        base::BindOnce(&ResourcePrefetchPredictorTables::UpdateOriginData,
+                       tables_, data));
   }
 }
 
@@ -1730,8 +1732,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::DB, FROM_HERE,
-      base::Bind(&ResourcePrefetchPredictorTables::UpdateManifestData, tables_,
-                 host, cache_entry->second));
+      base::BindOnce(&ResourcePrefetchPredictorTables::UpdateManifestData,
+                     tables_, host, cache_entry->second));
 }
 
 void ResourcePrefetchPredictor::UpdatePrefetchDataByManifest(
@@ -1772,8 +1774,8 @@
   if (was_updated) {
     BrowserThread::PostTask(
         BrowserThread::DB, FROM_HERE,
-        base::Bind(&ResourcePrefetchPredictorTables::UpdateResourceData,
-                   tables_, data, key_type));
+        base::BindOnce(&ResourcePrefetchPredictorTables::UpdateResourceData,
+                       tables_, data, key_type));
   }
 }
 
diff --git a/chrome/browser/predictors/resource_prefetcher_manager.cc b/chrome/browser/predictors/resource_prefetcher_manager.cc
index 434c149..1fbc42e1 100644
--- a/chrome/browser/predictors/resource_prefetcher_manager.cc
+++ b/chrome/browser/predictors/resource_prefetcher_manager.cc
@@ -40,9 +40,9 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   predictor_ = NULL;
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-      base::Bind(&ResourcePrefetcherManager::ShutdownOnIOThread,
-                 this));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&ResourcePrefetcherManager::ShutdownOnIOThread, this));
 }
 
 void ResourcePrefetcherManager::ShutdownOnIOThread() {
@@ -86,9 +86,9 @@
   const GURL& main_frame_url = resource_prefetcher->main_frame_url();
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&ResourcePrefetchPredictor::OnPrefetchingFinished,
-                 base::Unretained(predictor_), main_frame_url,
-                 base::Passed(std::move(stats))));
+      base::BindOnce(&ResourcePrefetchPredictor::OnPrefetchingFinished,
+                     base::Unretained(predictor_), main_frame_url,
+                     base::Passed(std::move(stats))));
 
   const std::string key = main_frame_url.host();
   auto it = prefetcher_map_.find(key);
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 012fb67..4c76404 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -290,7 +290,7 @@
 
   ui_test_utils::NavigateToURL(browser(), GURL(url_to_test));
   EXPECT_TRUE(RunJavascriptTest("testPodFocused",
-                                new base::Value(expected_path.AsUTF8Unsafe())));
+                                base::Value(expected_path.AsUTF8Unsafe())));
 }
 
 #endif  // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
diff --git a/chrome/browser/resources/ntp4/incognito_tab.html b/chrome/browser/resources/ntp4/incognito_tab.html
index fc50f77..5d4a519 100644
--- a/chrome/browser/resources/ntp4/incognito_tab.html
+++ b/chrome/browser/resources/ntp4/incognito_tab.html
@@ -1,11 +1,11 @@
 <!doctype html>
-<html i18n-values="dir:textdirection;
-                   hascustombackground:hasCustomBackground;
-                   bookmarkbarattached:bookmarkbarattached;
-                   lang:language">
+<html dir="$i18n{textdirection}"
+    hascustombackground="$i18n{hasCustomBackground}"
+    bookmarkbarattached="$i18n{bookmarkbarattached}"
+    lang="$i18n{language}">
 <head>
 <meta charset="utf-8">
-<title i18n-content="title"></title>
+<title>$i18n{title}</title>
 <meta name="viewport" content="width=device-width">
 <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
 <link rel="stylesheet" href="incognito_and_guest_tab.css">
@@ -20,42 +20,27 @@
 <body>
 <div class="content">
   <div class="icon"></div>
-  <span>
-    <h1 i18n-content="incognitoTabHeading"></h1>
-    <p>
-      <span i18n-content="incognitoTabDescription"></span>
-    </p>
-    <p>
-      <span i18n-content="incognitoTabWarning"></span>
-    </p>
-  </span>
-  <a class="learn-more-button" i18n-content="learnMore" i18n-values=".href:learnMoreLink"></a>
+  <h1>$i18n{incognitoTabHeading}</h1>
+  <p>$i18n{incognitoTabDescription}</p>
+  <p>$i18n{incognitoTabWarning}</p>
+  <a class="learn-more-button" href="$i18n{learnMoreLink}">$i18n{learnMore}</a>
 </div>
-</body>
-<script src="chrome://resources/js/cr.js"></script>
+
 <script>
-cr.define('ntp', function() {
-  'use strict';
-  /**
-   * Set whether the bookmarks bar is attached or not.
-   * @param {boolean} attached Whether the bar is attached or not.
-   */
-  function setBookmarkBarAttached(attached) {
-    document.documentElement.setAttribute('bookmarkbarattached', !!attached);
-  }
+var ntp = {
+  /** @param {string} attached */
+  setBookmarkBarAttached: function(attached) {
+    document.documentElement.setAttribute('bookmarkbarattached', attached);
+  },
 
   /** @param {!{hasCustomBackground: boolean}} themeData */
-  function themeChanged(themeData) {
+  themeChanged: function(themeData) {
     document.documentElement.setAttribute('hascustombackground',
                                           themeData.hasCustomBackground);
     document.getElementById('incognitothemecss').href =
         'chrome://theme/css/incognito_new_tab_theme.css?' + Date.now();
-  }
-
-  return {
-    setBookmarkBarAttached: setBookmarkBarAttached,
-    themeChanged: themeChanged,
-  };
-});
+  },
+};
 </script>
+</body>
 </html>
diff --git a/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp b/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
index 8450323..582e33b 100644
--- a/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
@@ -4,12 +4,23 @@
 {
   'targets': [
     {
+      'target_name': 'languages_browser_proxy',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(EXTERNS_GYP):chrome_send',
+        '<(EXTERNS_GYP):input_method_private',
+        '<(EXTERNS_GYP):language_settings_private',
+        '<(INTERFACES_GYP):input_method_private_interface',
+        '<(INTERFACES_GYP):language_settings_private_interface',
+      ],
+      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'languages',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:promise_resolver',
-        '<(EXTERNS_GYP):chrome_send',
         '<(EXTERNS_GYP):input_method_private',
         '<(EXTERNS_GYP):language_settings_private',
         '<(INTERFACES_GYP):input_method_private_interface',
@@ -17,6 +28,7 @@
         '../prefs/compiled_resources2.gyp:prefs_types',
         '../prefs/compiled_resources2.gyp:prefs',
         'languages_types',
+        'languages_browser_proxy',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/chrome/browser/resources/settings/languages_page/languages.html b/chrome/browser/resources/settings/languages_page/languages.html
index cc25681..ebeaaad 100644
--- a/chrome/browser/resources/settings/languages_page/languages.html
+++ b/chrome/browser/resources/settings/languages_page/languages.html
@@ -4,4 +4,5 @@
 <link rel="import" href="chrome://resources/html/promise_resolver.html">
 <link rel="import" href="../prefs/prefs.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
+<link rel="import" href="languages_browser_proxy.html">
 <script src="languages.js"></script>
diff --git a/chrome/browser/resources/settings/languages_page/languages.js b/chrome/browser/resources/settings/languages_page/languages.js
index 48f91f2..dc26a82 100644
--- a/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chrome/browser/resources/settings/languages_page/languages.js
@@ -78,12 +78,6 @@
       },
     },
 
-    /** @type {!LanguageSettingsPrivate} */
-    languageSettingsPrivate: Object,
-
-    /** @type {!InputMethodPrivate} */
-    inputMethodPrivate: Object,
-
     /**
      * Hash map of supported languages by language codes for fast lookup.
      * @private {!Map<string, !chrome.languageSettingsPrivate.Language>}
@@ -148,15 +142,25 @@
   /** @private {?Function} */
   boundOnInputMethodChanged_: null,
 
+  /** @private {?settings.LanguagesBrowserProxy} */
+  browserProxy_: null,
+
+  /** @private {?LanguageSettingsPrivate} */
+  languageSettingsPrivate_: null,
+
+// <if expr="chromeos">
+  /** @private {?InputMethodPrivate} */
+  inputMethodPrivate_: null,
+// </if>
+
   /** @override */
   attached: function() {
-    this.languageSettingsPrivate =
-        settings.languageSettingsPrivateApiForTest ||
-        /** @type {!LanguageSettingsPrivate} */(chrome.languageSettingsPrivate);
-
-    this.inputMethodPrivate =
-        settings.inputMethodPrivateApiForTest ||
-        /** @type {!InputMethodPrivate} */(chrome.inputMethodPrivate);
+    this.browserProxy_ = settings.LanguagesBrowserProxyImpl.getInstance();
+    this.languageSettingsPrivate_ =
+        this.browserProxy_.getLanguageSettingsPrivate();
+// <if expr="chromeos">
+    this.inputMethodPrivate_ = this.browserProxy_.getInputMethodPrivate();
+// </if>
 
     var promises = [];
 
@@ -166,31 +170,31 @@
 
     // Get the language list.
     promises[1] = new Promise(function(resolve) {
-      this.languageSettingsPrivate.getLanguageList(resolve);
+      this.languageSettingsPrivate_.getLanguageList(resolve);
     }.bind(this));
 
     // Get the translate target language.
     promises[2] = new Promise(function(resolve) {
-      this.languageSettingsPrivate.getTranslateTargetLanguage(resolve);
+      this.languageSettingsPrivate_.getTranslateTargetLanguage(resolve);
     }.bind(this));
 
     if (cr.isChromeOS) {
       promises[3] = new Promise(function(resolve) {
-        this.languageSettingsPrivate.getInputMethodLists(function(lists) {
+        this.languageSettingsPrivate_.getInputMethodLists(function(lists) {
           resolve(lists.componentExtensionImes.concat(
               lists.thirdPartyExtensionImes));
         });
       }.bind(this));
 
       promises[4] = new Promise(function(resolve) {
-        this.inputMethodPrivate.getCurrentInputMethod(resolve);
+        this.inputMethodPrivate_.getCurrentInputMethod(resolve);
       }.bind(this));
     }
 
     if (cr.isWindows || cr.isChromeOS) {
       // Fetch the starting UI language, which affects which actions should be
       // enabled.
-      promises.push(cr.sendWithPromise('getProspectiveUILanguage').then(
+      promises.push(this.browserProxy_.getProspectiveUILanguage().then(
           function(prospectiveUILanguage) {
             this.originalProspectiveUILanguage_ =
                 prospectiveUILanguage || window.navigator.language;
@@ -212,7 +216,7 @@
 
     if (cr.isChromeOS) {
       this.boundOnInputMethodChanged_ = this.onInputMethodChanged_.bind(this);
-      this.inputMethodPrivate.onChanged.addListener(
+      this.inputMethodPrivate_.onChanged.addListener(
           assert(this.boundOnInputMethodChanged_));
     }
   },
@@ -220,7 +224,7 @@
   /** @override */
   detached: function() {
     if (cr.isChromeOS) {
-      this.inputMethodPrivate.onChanged.removeListener(
+      this.inputMethodPrivate_.onChanged.removeListener(
           assert(this.boundOnInputMethodChanged_));
       this.boundOnInputMethodChanged_ = null;
     }
@@ -492,7 +496,7 @@
    * @param {string} languageCode
    */
   setProspectiveUILanguage: function(languageCode) {
-    chrome.send('setProspectiveUILanguage', [languageCode]);
+    this.browserProxy_.setProspectiveUILanguage(languageCode);
   },
 
   /**
@@ -521,7 +525,7 @@
     if (!CrSettingsPrefs.isInitialized)
       return;
 
-    this.languageSettingsPrivate.enableLanguage(languageCode);
+    this.languageSettingsPrivate_.enableLanguage(languageCode);
     this.disableTranslateLanguage(languageCode);
   },
 
@@ -554,7 +558,7 @@
     }
 
     // Remove the language from preferred languages.
-    this.languageSettingsPrivate.disableLanguage(languageCode);
+    this.languageSettingsPrivate_.disableLanguage(languageCode);
     this.enableTranslateLanguage(languageCode);
   },
 
@@ -734,19 +738,19 @@
   addInputMethod: function(id) {
     if (!this.supportedInputMethodMap_.has(id))
       return;
-    this.languageSettingsPrivate.addInputMethod(id);
+    this.languageSettingsPrivate_.addInputMethod(id);
   },
 
   /** @param {string} id */
   removeInputMethod: function(id) {
     if (!this.supportedInputMethodMap_.has(id))
       return;
-    this.languageSettingsPrivate.removeInputMethod(id);
+    this.languageSettingsPrivate_.removeInputMethod(id);
   },
 
   /** @param {string} id */
   setCurrentInputMethod: function(id) {
-    this.inputMethodPrivate.setCurrentInputMethod(id);
+    this.inputMethodPrivate_.setCurrentInputMethod(id);
   },
 
   /**
@@ -767,7 +771,7 @@
 
   /** @param {string} id Input method ID. */
   openInputMethodOptions: function(id) {
-    this.inputMethodPrivate.openOptionsPage(id);
+    this.inputMethodPrivate_.openOptionsPage(id);
   },
 
   /** @param {string} id New current input method ID. */
diff --git a/chrome/browser/resources/settings/languages_page/languages_browser_proxy.html b/chrome/browser/resources/settings/languages_page/languages_browser_proxy.html
new file mode 100644
index 0000000..d000257
--- /dev/null
+++ b/chrome/browser/resources/settings/languages_page/languages_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="languages_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/languages_page/languages_browser_proxy.js b/chrome/browser/resources/settings/languages_page/languages_browser_proxy.js
new file mode 100644
index 0000000..a36bb2e5
--- /dev/null
+++ b/chrome/browser/resources/settings/languages_page/languages_browser_proxy.js
@@ -0,0 +1,76 @@
+// 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.
+
+/**
+ * @fileoverview A helper object used from the languages section
+ * to interact with the browser.
+ */
+
+cr.define('settings', function() {
+  /** @interface */
+  function LanguagesBrowserProxy() {}
+
+  LanguagesBrowserProxy.prototype = {
+// <if expr="chromeos or is_win">
+    /**
+     * Sets the prospective UI language to the chosen language. This won't
+     * affect the actual UI language until a restart.
+     * @param {string} languageCode
+     */
+    setProspectiveUILanguage: function(languageCode) {},
+
+    /** @return {!Promise<string>} */
+    getProspectiveUILanguage: function() {},
+// </if>
+
+    /** @return {!LanguageSettingsPrivate} */
+    getLanguageSettingsPrivate: function() {},
+
+// <if expr="chromeos">
+    /** @return {!InputMethodPrivate} */
+    getInputMethodPrivate: function() {},
+// </if>
+  };
+
+  /**
+   * @constructor
+   * @implements {settings.LanguagesBrowserProxy}
+   */
+  function LanguagesBrowserProxyImpl() {}
+  // The singleton instance_ is replaced with a test version of this wrapper
+  // during testing.
+  cr.addSingletonGetter(LanguagesBrowserProxyImpl);
+
+  LanguagesBrowserProxyImpl.prototype = {
+// <if expr="chromeos or is_win">
+    /** @override */
+    setProspectiveUILanguage: function(languageCode) {
+      chrome.send('setProspectiveUILanguage', [languageCode]);
+    },
+
+    /** @override */
+    getProspectiveUILanguage: function() {
+      return cr.sendWithPromise('getProspectiveUILanguage');
+    },
+// </if>
+
+    /** @override */
+    getLanguageSettingsPrivate: function() {
+      return /** @type {!LanguageSettingsPrivate} */ (
+          chrome.languageSettingsPrivate);
+    },
+
+// <if expr="chromeos">
+    /** @override */
+    getInputMethodPrivate: function() {
+      return /** @type {!InputMethodPrivate} */ (chrome.inputMethodPrivate);
+    },
+// </if>
+  };
+
+  return {
+    LanguagesBrowserProxy: LanguagesBrowserProxy,
+    LanguagesBrowserProxyImpl: LanguagesBrowserProxyImpl,
+  };
+});
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 4a4258b..137069d 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -608,6 +608,13 @@
                  type="chrome_html"
                  preprocess="true"
                  allowexternalscript="true" />
+      <structure name="IDR_SETTINGS_LANGUAGES_BROWSER_PROXY_HTML"
+                 file="languages_page/languages_browser_proxy.html"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_LANGUAGES_BROWSER_PROXY_JS"
+                 file="languages_page/languages_browser_proxy.js"
+                 preprocess="true"
+                 type="chrome_html" />
       <structure name="IDR_SETTINGS_LANGUAGES_ADD_LANGUAGES_DIALOG_HTML"
                  file="languages_page/add_languages_dialog.html"
                  type="chrome_html" />
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.cc b/chrome/browser/safe_browsing/browser_feature_extractor.cc
index 5b1967a..bbabc07 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor.cc
@@ -245,8 +245,8 @@
   ExtractBrowseInfoFeatures(*info, request);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&BrowserFeatureExtractor::StartExtractFeatures,
-                 weak_factory_.GetWeakPtr(), base::Passed(&req), callback));
+      base::BindOnce(&BrowserFeatureExtractor::StartExtractFeatures,
+                     weak_factory_.GetWeakPtr(), base::Passed(&req), callback));
 }
 
 void BrowserFeatureExtractor::ExtractMalwareFeatures(
@@ -269,14 +269,12 @@
 
   // IP blacklist lookups have to happen on the IO thread.
   BrowserThread::PostTaskAndReply(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&FilterBenignIpsOnIOThread,
-                 host_->database_manager(),
-                 ips_ptr),
-      base::Bind(&BrowserFeatureExtractor::FinishExtractMalwareFeatures,
-                 weak_factory_.GetWeakPtr(),
-                 base::Passed(&ips), callback, base::Passed(&req)));
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&FilterBenignIpsOnIOThread, host_->database_manager(),
+                     ips_ptr),
+      base::BindOnce(&BrowserFeatureExtractor::FinishExtractMalwareFeatures,
+                     weak_factory_.GetWeakPtr(), base::Passed(&ips), callback,
+                     base::Passed(&req)));
 }
 
 void BrowserFeatureExtractor::ExtractBrowseInfoFeatures(
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service.cc b/chrome/browser/safe_browsing/certificate_reporting_service.cc
index 7c013f5..f95c3724 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service.cc
@@ -203,10 +203,10 @@
 
   content::BrowserThread::PostTaskAndReply(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CertificateReportingService::InitializeOnIOThread,
-                 base::Unretained(this), true, url_request_context_getter,
-                 max_queued_report_count_, max_report_age_, clock_,
-                 server_public_key_, server_public_key_version_),
+      base::BindOnce(&CertificateReportingService::InitializeOnIOThread,
+                     base::Unretained(this), true, url_request_context_getter,
+                     max_queued_report_count_, max_report_age_, clock_,
+                     server_public_key_, server_public_key_version_),
       reset_callback_);
 }
 
@@ -220,7 +220,7 @@
   url_request_context_ = nullptr;
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CleanupOnIOThread, base::Passed(std::move(reporter_))));
+      base::BindOnce(&CleanupOnIOThread, base::Passed(std::move(reporter_))));
 }
 
 void CertificateReportingService::Send(const std::string& serialized_report) {
@@ -230,8 +230,8 @@
   }
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CertificateReportingService::Reporter::Send,
-                 base::Unretained(reporter_.get()), serialized_report));
+      base::BindOnce(&CertificateReportingService::Reporter::Send,
+                     base::Unretained(reporter_.get()), serialized_report));
 }
 
 void CertificateReportingService::SendPending() {
@@ -241,8 +241,8 @@
   }
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CertificateReportingService::Reporter::SendPending,
-                 base::Unretained(reporter_.get())));
+      base::BindOnce(&CertificateReportingService::Reporter::SendPending,
+                     base::Unretained(reporter_.get())));
 }
 
 void CertificateReportingService::InitializeOnIOThread(
@@ -269,10 +269,10 @@
 
   content::BrowserThread::PostTaskAndReply(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CertificateReportingService::ResetOnIOThread,
-                 base::Unretained(this), enabled, url_request_context_,
-                 max_queued_report_count_, max_report_age_, clock_,
-                 server_public_key_, server_public_key_version_),
+      base::BindOnce(&CertificateReportingService::ResetOnIOThread,
+                     base::Unretained(this), enabled, url_request_context_,
+                     max_queued_report_count_, max_report_age_, clock_,
+                     server_public_key_, server_public_key_version_),
       reset_callback_);
 }
 
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
index 8b00883..dbe29ea07 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_browsertest.cc
@@ -90,7 +90,7 @@
   void TearDownOnMainThread() override {
     test_helper()->ExpectNoRequests(service());
     content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                     base::Bind(&CleanUpOnIOThread));
+                                     base::BindOnce(&CleanUpOnIOThread));
     EXPECT_GE(num_expected_failed_report_, 0)
         << "Don't forget to set expected failed report count.";
     // Check the histogram as the last thing. This makes sure no in-flight
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
index 998d8903..c5e9ceac 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
@@ -207,8 +207,8 @@
   // Start reading asynchronously as would a normal network request.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&DelayableCertReportURLRequestJob::NotifyHeadersComplete,
-                 weak_factory_.GetWeakPtr()));
+      base::BindOnce(&DelayableCertReportURLRequestJob::NotifyHeadersComplete,
+                     weak_factory_.GetWeakPtr()));
 }
 
 CertReportJobInterceptor::CertReportJobInterceptor(
@@ -229,9 +229,9 @@
       GetReportContents(request, server_private_key_);
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&CertReportJobInterceptor::RequestCreated,
-                 weak_factory_.GetWeakPtr(), serialized_report,
-                 expected_report_result_));
+      base::BindOnce(&CertReportJobInterceptor::RequestCreated,
+                     weak_factory_.GetWeakPtr(), serialized_report,
+                     expected_report_result_));
 
   if (expected_report_result_ == REPORTS_FAIL) {
     return new DelayableCertReportURLRequestJob(
@@ -264,16 +264,16 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CertReportJobInterceptor::SetFailureModeOnIOThread,
-                 weak_factory_.GetWeakPtr(), expected_report_result));
+      base::BindOnce(&CertReportJobInterceptor::SetFailureModeOnIOThread,
+                     weak_factory_.GetWeakPtr(), expected_report_result));
 }
 
 void CertReportJobInterceptor::Resume() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&CertReportJobInterceptor::ResumeOnIOThread,
-                 base::Unretained(this)));
+      base::BindOnce(&CertReportJobInterceptor::ResumeOnIOThread,
+                     base::Unretained(this)));
 }
 
 RequestObserver* CertReportJobInterceptor::request_created_observer() const {
@@ -383,9 +383,9 @@
       new CertReportJobInterceptor(REPORTS_FAIL, server_private_key_);
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&SetUpURLHandlersOnIOThread,
-                 base::Passed(std::unique_ptr<net::URLRequestInterceptor>(
-                     url_request_interceptor_))));
+      base::BindOnce(&SetUpURLHandlersOnIOThread,
+                     base::Passed(std::unique_ptr<net::URLRequestInterceptor>(
+                         url_request_interceptor_))));
 }
 
 void CertificateReportingServiceTestHelper::SetFailureMode(
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
index f2b77813..aff63eb 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
@@ -349,7 +349,7 @@
 
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(
+        base::BindOnce(
             &CertificateReportingServiceTest::SetUpURLRequestContextOnIOThread,
             base::Unretained(this)));
     WaitForIOThread();
@@ -378,10 +378,10 @@
 
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&CertificateReportingServiceTest::TearDownOnIOThread,
-                   base::Unretained(this)));
+        base::BindOnce(&CertificateReportingServiceTest::TearDownOnIOThread,
+                       base::Unretained(this)));
     content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                     base::Bind(&ClearURLHandlers));
+                                     base::BindOnce(&ClearURLHandlers));
     WaitForIOThread();
 
     histogram_test_helper_.CheckHistogram();
@@ -410,15 +410,15 @@
   void AdvanceClock(base::TimeDelta delta) {
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&base::SimpleTestClock::Advance,
-                   base::Unretained(clock_.get()), delta));
+        base::BindOnce(&base::SimpleTestClock::Advance,
+                       base::Unretained(clock_.get()), delta));
   }
 
   void SetNow(base::Time now) {
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&base::SimpleTestClock::SetNow,
-                   base::Unretained(clock_.get()), now));
+        base::BindOnce(&base::SimpleTestClock::SetNow,
+                       base::Unretained(clock_.get()), now));
   }
 
   void SetExpectedFailedReportCountOnTearDown(unsigned int count) {
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index b5eb0d7..b12aa7d 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -133,10 +133,9 @@
     // uses the SafeBrowsing service class.
     if (ShouldClassifyForPhishing() || ShouldClassifyForMalware()) {
       BrowserThread::PostTask(
-          BrowserThread::IO,
-          FROM_HERE,
-          base::Bind(&ShouldClassifyUrlRequest::CheckSafeBrowsingDatabase,
-                     this, url_));
+          BrowserThread::IO, FROM_HERE,
+          base::BindOnce(&ShouldClassifyUrlRequest::CheckSafeBrowsingDatabase,
+                         this, url_));
     }
   }
 
@@ -233,12 +232,9 @@
       }
     }
     BrowserThread::PostTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&ShouldClassifyUrlRequest::CheckCache,
-                   this,
-                   phishing_reason,
-                   malware_reason));
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&ShouldClassifyUrlRequest::CheckCache, this,
+                       phishing_reason, malware_reason));
   }
 
   void CheckCache(PreClassificationCheckFailures phishing_reason,
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index dff9a32..7460413 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -567,8 +567,8 @@
   // Make sure the client object will be deleted.
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
-                 ui_manager_, resource.callback));
+      base::BindOnce(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
+                     ui_manager_, resource.callback));
 }
 
 TEST_F(ClientSideDetectionHostTest, OnPhishingDetectionDoneMultiplePings) {
@@ -653,8 +653,8 @@
   // Make sure the client object will be deleted.
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
-                 ui_manager_, resource.callback));
+      base::BindOnce(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
+                     ui_manager_, resource.callback));
 }
 
 TEST_F(ClientSideDetectionHostTest,
@@ -866,8 +866,8 @@
   // Make sure the client object will be deleted.
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
-                 ui_manager_, resource.callback));
+      base::BindOnce(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
+                     ui_manager_, resource.callback));
 }
 
 TEST_F(ClientSideDetectionHostTest, UpdateIPUrlMap) {
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index 275e8146..1cc9c276 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -166,9 +166,10 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&ClientSideDetectionService::StartClientReportPhishingRequest,
-                 weak_factory_.GetWeakPtr(), verdict, is_extended_reporting,
-                 callback));
+      base::BindOnce(
+          &ClientSideDetectionService::StartClientReportPhishingRequest,
+          weak_factory_.GetWeakPtr(), verdict, is_extended_reporting,
+          callback));
 }
 
 void ClientSideDetectionService::SendClientReportMalwareRequest(
@@ -177,8 +178,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&ClientSideDetectionService::StartClientReportMalwareRequest,
-                 weak_factory_.GetWeakPtr(), verdict, callback));
+      base::BindOnce(
+          &ClientSideDetectionService::StartClientReportMalwareRequest,
+          weak_factory_.GetWeakPtr(), verdict, callback));
 }
 
 bool ClientSideDetectionService::IsPrivateIPAddress(
diff --git a/chrome/browser/safe_browsing/client_side_model_loader.cc b/chrome/browser/safe_browsing/client_side_model_loader.cc
index fd52174..ea151e8 100644
--- a/chrome/browser/safe_browsing/client_side_model_loader.cc
+++ b/chrome/browser/safe_browsing/client_side_model_loader.cc
@@ -205,7 +205,7 @@
     return;
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&ModelLoader::StartFetch, weak_factory_.GetWeakPtr()),
+      base::BindOnce(&ModelLoader::StartFetch, weak_factory_.GetWeakPtr()),
       base::TimeDelta::FromMilliseconds(delay_ms));
 }
 
diff --git a/chrome/browser/safe_browsing/download_feedback.cc b/chrome/browser/safe_browsing/download_feedback.cc
index 0edcc4bd..da2a0b6 100644
--- a/chrome/browser/safe_browsing/download_feedback.cc
+++ b/chrome/browser/safe_browsing/download_feedback.cc
@@ -108,7 +108,7 @@
 
   file_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&base::DeleteFile), file_path_, false));
+      base::BindOnce(base::IgnoreResult(&base::DeleteFile), file_path_, false));
 }
 
 void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) {
diff --git a/chrome/browser/safe_browsing/download_feedback_service.cc b/chrome/browser/safe_browsing/download_feedback_service.cc
index adebf92..379bcda4 100644
--- a/chrome/browser/safe_browsing/download_feedback_service.cc
+++ b/chrome/browser/safe_browsing/download_feedback_service.cc
@@ -177,7 +177,7 @@
   } else {
     file_task_runner->PostTask(
         FROM_HERE,
-        base::Bind(base::IgnoreResult(&base::DeleteFile), path, false));
+        base::BindOnce(base::IgnoreResult(&base::DeleteFile), path, false));
   }
 }
 
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index ea22167..4909128 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -254,22 +254,18 @@
     if (threat_type != SB_THREAT_TYPE_SAFE) {
       UpdateDownloadCheckStats(dangerous_type_);
       BrowserThread::PostTask(
-          BrowserThread::UI,
-          FROM_HERE,
-          base::Bind(&DownloadUrlSBClient::ReportMalware,
-                     this, threat_type));
+          BrowserThread::UI, FROM_HERE,
+          base::BindOnce(&DownloadUrlSBClient::ReportMalware, this,
+                         threat_type));
     } else if (download_attribution_enabled_) {
         // Identify download referrer chain, which will be used in
         // ClientDownloadRequest.
         BrowserThread::PostTask(
-            BrowserThread::UI,
-            FROM_HERE,
-            base::Bind(&DownloadUrlSBClient::IdentifyReferrerChain,
-                       this));
+            BrowserThread::UI, FROM_HERE,
+            base::BindOnce(&DownloadUrlSBClient::IdentifyReferrerChain, this));
     }
-    BrowserThread::PostTask(BrowserThread::UI,
-                            FROM_HERE,
-                            base::Bind(callback_, result));
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                            base::BindOnce(callback_, result));
   }
 
   void ReportMalware(SBThreatType threat_type) {
@@ -492,10 +488,9 @@
     }
     timeout_start_time_ = base::TimeTicks::Now();
     BrowserThread::PostDelayedTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&CheckClientDownloadRequest::Cancel,
-                   weakptr_factory_.GetWeakPtr()),
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&CheckClientDownloadRequest::Cancel,
+                       weakptr_factory_.GetWeakPtr()),
         base::TimeDelta::FromMilliseconds(
             service_->download_request_timeout_ms()));
   }
@@ -662,17 +657,15 @@
     // every URL in the redirect chain.  We also should check whether the
     // download URL is hosted on the internal network.
     BrowserThread::PostTask(
-        BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this));
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&CheckClientDownloadRequest::CheckWhitelists, this));
 
     // We wait until after the file checks finish to start the timeout, as
     // windows can cause permissions errors if the timeout fired while we were
     // checking the file signature and we tried to complete the download.
     BrowserThread::PostTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&CheckClientDownloadRequest::StartTimeout, this));
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&CheckClientDownloadRequest::StartTimeout, this));
   }
 
   void StartExtractFileFeatures() {
@@ -681,13 +674,14 @@
     // Since we do blocking I/O, offload this to a worker thread.
     // The task does not need to block shutdown.
     base::PostTaskWithTraits(
-        FROM_HERE, base::TaskTraits()
-                       .MayBlock()
-                       .WithPriority(base::TaskPriority::BACKGROUND)
-                       .WithShutdownBehavior(
-                           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
-        base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures, this,
-                   item_->GetFullPath()));
+        FROM_HERE,
+        base::TaskTraits()
+            .MayBlock()
+            .WithPriority(base::TaskPriority::BACKGROUND)
+            .WithShutdownBehavior(
+                base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
+        base::BindOnce(&CheckClientDownloadRequest::ExtractFileFeatures, this,
+                       item_->GetFullPath()));
   }
 
   void ExtractFileFeatures(const base::FilePath& file_path) {
@@ -901,9 +895,8 @@
     // The URLFetcher is owned by the UI thread, so post a message to
     // start the pingback.
     BrowserThread::PostTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&CheckClientDownloadRequest::GetTabRedirects, this));
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&CheckClientDownloadRequest::GetTabRedirects, this));
   }
 
   void GetTabRedirects() {
@@ -1145,10 +1138,9 @@
   void PostFinishTask(DownloadCheckResult result,
                       DownloadCheckResultReason reason) {
     BrowserThread::PostTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&CheckClientDownloadRequest::FinishRequest, this, result,
-                   reason));
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&CheckClientDownloadRequest::FinishRequest, this, result,
+                       reason));
   }
 
   void FinishRequest(DownloadCheckResult result,
@@ -1388,16 +1380,16 @@
     // execution reaches Finish().
     BrowserThread::PostDelayedTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&PPAPIDownloadRequest::OnRequestTimedOut,
-                   weakptr_factory_.GetWeakPtr()),
+        base::BindOnce(&PPAPIDownloadRequest::OnRequestTimedOut,
+                       weakptr_factory_.GetWeakPtr()),
         base::TimeDelta::FromMilliseconds(
             service_->download_request_timeout_ms()));
 
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&PPAPIDownloadRequest::CheckWhitelistsOnIOThread,
-                   requestor_url_, database_manager_,
-                   weakptr_factory_.GetWeakPtr()));
+        base::BindOnce(&PPAPIDownloadRequest::CheckWhitelistsOnIOThread,
+                       requestor_url_, database_manager_,
+                       weakptr_factory_.GetWeakPtr()));
   }
 
  private:
@@ -1414,8 +1406,8 @@
         database_manager->MatchDownloadWhitelistUrl(requestor_url);
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&PPAPIDownloadRequest::WhitelistCheckComplete,
-                   download_request, url_was_whitelisted));
+        base::BindOnce(&PPAPIDownloadRequest::WhitelistCheckComplete,
+                       download_request, url_was_whitelisted));
   }
 
   void WhitelistCheckComplete(bool was_on_whitelist) {
@@ -1752,9 +1744,8 @@
                               database_manager_));
   // The client will release itself once it is done.
   BrowserThread::PostTask(
-        BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(&DownloadUrlSBClient::StartCheck, client));
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&DownloadUrlSBClient::StartCheck, client));
 }
 
 bool DownloadProtectionService::IsSupportedDownload(
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index c88eecb..94c4c68 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -233,10 +233,9 @@
           std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL));
   for (size_t i = 0; i < check->url_results.size(); ++i)
     check->url_results[i] = threat_type;
-  BrowserThread::PostTask(BrowserThread::IO,
-                          FROM_HERE,
-                          base::Bind(&OnSafeBrowsingResult,
-                                     base::Owned(check)));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&OnSafeBrowsingResult, base::Owned(check)));
 }
 
 class DownloadProtectionServiceTest : public testing::Test {
@@ -465,16 +464,16 @@
                               const base::Closure& quit_closure) {
     BrowserThread::PostTask(
         thread, FROM_HERE,
-        base::Bind(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI,
-                   base::Unretained(this), quit_closure));
+        base::BindOnce(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI,
+                       base::Unretained(this), quit_closure));
   }
 
   void FlushMessageLoop(BrowserThread::ID thread) {
     RunLoop run_loop;
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&DownloadProtectionServiceTest::PostRunMessageLoopTask,
-                   base::Unretained(this), thread, run_loop.QuitClosure()));
+        base::BindOnce(&DownloadProtectionServiceTest::PostRunMessageLoopTask,
+                       base::Unretained(this), thread, run_loop.QuitClosure()));
     run_loop.Run();
   }
 
@@ -1512,8 +1511,8 @@
   // Simulate the request finishing.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
-                 base::Unretained(this), fetcher));
+      base::BindOnce(&DownloadProtectionServiceTest::SendURLFetchComplete,
+                     base::Unretained(this), fetcher));
   run_loop.Run();
 }
 
@@ -1572,8 +1571,8 @@
   // Simulate the request finishing.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
-                 base::Unretained(this), fetcher));
+      base::BindOnce(&DownloadProtectionServiceTest::SendURLFetchComplete,
+                     base::Unretained(this), fetcher));
   run_loop.Run();
 }
 
@@ -1660,8 +1659,8 @@
     // Simulate the request finishing.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
-                   base::Unretained(this), fetcher));
+        base::BindOnce(&DownloadProtectionServiceTest::SendURLFetchComplete,
+                       base::Unretained(this), fetcher));
     run_loop.Run();
   }
 
@@ -1732,8 +1731,8 @@
     // Simulate the request finishing.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
-                   base::Unretained(this), fetcher));
+        base::BindOnce(&DownloadProtectionServiceTest::SendURLFetchComplete,
+                       base::Unretained(this), fetcher));
     run_loop.Run();
   }
 }
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
index 738b974..3220694 100644
--- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
@@ -129,8 +129,9 @@
 
   // Post a task to register a new callback after Start() is called.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&DelayedCallbackRunnerTest::RegisterTestCallback,
-                            base::Unretained(this), name2));
+      FROM_HERE,
+      base::BindOnce(&DelayedCallbackRunnerTest::RegisterTestCallback,
+                     base::Unretained(this), name2));
 
   RegisterTestCallback(name);
   instance_->Start();
diff --git a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
index d503f1e1..b57d1842 100644
--- a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
@@ -403,10 +403,11 @@
   // Fire off a task to load the details and return them to the caller.
   DownloadMetadata* metadata = new DownloadMetadata();
   read_runner_->PostTaskAndReply(
-      FROM_HERE, base::Bind(&ReadMetadataOnWorkerPool,
-                            GetMetadataPath(browser_context), metadata),
-      base::Bind(&ReturnResults, callback,
-                 base::Passed(base::WrapUnique(metadata))));
+      FROM_HERE,
+      base::BindOnce(&ReadMetadataOnWorkerPool,
+                     GetMetadataPath(browser_context), metadata),
+      base::BindOnce(&ReturnResults, callback,
+                     base::Passed(base::WrapUnique(metadata))));
 }
 
 content::DownloadManager*
@@ -566,18 +567,17 @@
   // Do not block shutdown on this read since nothing will come of it.
   read_runner_->PostTaskAndReply(
       FROM_HERE,
-      base::Bind(&ReadMetadataOnWorkerPool, metadata_path_, metadata),
-      base::Bind(&DownloadMetadataManager::ManagerContext::OnMetadataReady,
-                 weak_factory_.GetWeakPtr(),
-                 base::Passed(base::WrapUnique(metadata))));
+      base::BindOnce(&ReadMetadataOnWorkerPool, metadata_path_, metadata),
+      base::BindOnce(&DownloadMetadataManager::ManagerContext::OnMetadataReady,
+                     weak_factory_.GetWeakPtr(),
+                     base::Passed(base::WrapUnique(metadata))));
 }
 
 void DownloadMetadataManager::ManagerContext::WriteMetadata() {
   write_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&WriteMetadataOnWorkerPool,
-                 metadata_path_,
-                 base::Owned(new DownloadMetadata(*download_metadata_))));
+      base::BindOnce(&WriteMetadataOnWorkerPool, metadata_path_,
+                     base::Owned(new DownloadMetadata(*download_metadata_))));
 }
 
 void DownloadMetadataManager::ManagerContext::RemoveMetadata() {
@@ -591,7 +591,7 @@
   // Remove any metadata.
   download_metadata_.reset();
   write_runner_->PostTask(
-      FROM_HERE, base::Bind(&DeleteMetadataOnWorkerPool, metadata_path_));
+      FROM_HERE, base::BindOnce(&DeleteMetadataOnWorkerPool, metadata_path_));
   // Run callbacks (only present in case of a transition to LOAD_COMPLETE).
   RunCallbacks();
 }
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
index 7c8bf2d..72329940 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -229,8 +229,9 @@
   } else {
     thread_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&IncidentReportingService::Receiver::AddIncidentOnMainThread,
-                   service_, nullptr, base::Passed(&incident)));
+        base::BindOnce(
+            &IncidentReportingService::Receiver::AddIncidentOnMainThread,
+            service_, nullptr, base::Passed(&incident)));
   }
 }
 
@@ -241,7 +242,7 @@
   } else {
     thread_runner_->PostTask(
         FROM_HERE,
-        base::Bind(
+        base::BindOnce(
             &IncidentReportingService::Receiver::ClearIncidentOnMainThread,
             service_, nullptr, base::Passed(&incident)));
   }
@@ -691,10 +692,11 @@
       new ClientIncidentReport_EnvironmentData();
   environment_collection_pending_ =
       environment_collection_task_runner_->PostTaskAndReply(
-          FROM_HERE, base::Bind(collect_environment_data_fn_, environment_data),
-          base::Bind(&IncidentReportingService::OnEnvironmentDataCollected,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     base::Passed(base::WrapUnique(environment_data))));
+          FROM_HERE,
+          base::BindOnce(collect_environment_data_fn_, environment_data),
+          base::BindOnce(&IncidentReportingService::OnEnvironmentDataCollected,
+                         weak_ptr_factory_.GetWeakPtr(),
+                         base::Passed(base::WrapUnique(environment_data))));
 
   // Posting the task will fail if the runner has been shut down. This should
   // never happen since the blocking pool is shut down after this service.
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
index 0212651..b3f927c 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
@@ -374,7 +374,7 @@
       // Post a task that will provide the response.
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
-          base::Bind(&FakeUploader::FinishUpload, base::Unretained(this)));
+          base::BindOnce(&FakeUploader::FinishUpload, base::Unretained(this)));
     }
     ~FakeUploader() override { on_deleted_.Run(); }
 
@@ -405,8 +405,8 @@
             callback) {
       // Post a task to run the callback.
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(callback, base::Passed(&binary_download),
-                                base::Passed(&non_binary_download)));
+          FROM_HERE, base::BindOnce(callback, base::Passed(&binary_download),
+                                    base::Passed(&non_binary_download)));
       return std::unique_ptr<safe_browsing::LastDownloadFinder>(
           new FakeDownloadFinder(on_deleted));
     }
@@ -475,10 +475,9 @@
   // Posts a task to delete the profile.
   void DelayedDeleteProfile(Profile* profile) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::Bind(&TestingProfileManager::DeleteTestingProfile,
-                   base::Unretained(&profile_manager_),
-                   profile->GetProfileUserName()));
+        FROM_HERE, base::BindOnce(&TestingProfileManager::DeleteTestingProfile,
+                                  base::Unretained(&profile_manager_),
+                                  profile->GetProfileUserName()));
   }
 
   // A callback run by the test fixture when a profile is added. An incident
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
index 2ad335e3..033d23c8 100644
--- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
@@ -457,8 +457,9 @@
 
   // Post a task that will create a second profile once the main loop is run.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&LastDownloadFinderTest::CreateProfileWithDownload,
-                 base::Unretained(this)));
+      FROM_HERE,
+      base::BindOnce(&LastDownloadFinderTest::CreateProfileWithDownload,
+                     base::Unretained(this)));
 
   // Create a finder that we expect will find a download in the second profile.
   std::unique_ptr<LastDownloadFinder> finder(LastDownloadFinder::Create(
diff --git a/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc b/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc
index 9c8351fe..30fed1f 100644
--- a/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc
@@ -73,8 +73,8 @@
       , callback_(callback) {
     content::BrowserThread::PostTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&ResourceRequestDetectorClient::StartCheck, this,
-                   resource_url));
+        base::BindOnce(&ResourceRequestDetectorClient::StartCheck, this,
+                       resource_url));
   }
 
  private:
@@ -107,7 +107,7 @@
       incident_data->set_digest(threat_hash);
       content::BrowserThread::PostTask(
           content::BrowserThread::UI, FROM_HERE,
-          base::Bind(callback_, base::Passed(&incident_data)));
+          base::BindOnce(callback_, base::Passed(&incident_data)));
     }
     Release();  // Balanced in StartCheck.
   }
diff --git a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc
index 9949152..c35c1af 100644
--- a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc
@@ -55,10 +55,9 @@
 void VerifyVariationsSeedSignature(
     std::unique_ptr<IncidentReceiver> incident_receiver) {
   content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&VerifyVariationsSeedSignatureOnUIThread,
-                 base::Passed(&incident_receiver)));
+      content::BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&VerifyVariationsSeedSignatureOnUIThread,
+                     base::Passed(&incident_receiver)));
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc
index 2416d21..77ebd46 100644
--- a/chrome/browser/safe_browsing/local_database_manager.cc
+++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -553,7 +553,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::OnCheckDone, this, check));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::OnCheckDone, this,
+                     check));
 
   return false;
 }
@@ -620,8 +621,9 @@
   DCHECK(!callback.is_null());
   safe_browsing_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::GetAllChunksFromDatabase,
-                 this, callback));
+      base::BindOnce(
+          &LocalSafeBrowsingDatabaseManager::GetAllChunksFromDatabase, this,
+          callback));
 }
 
 void LocalSafeBrowsingDatabaseManager::AddChunks(
@@ -633,8 +635,8 @@
   DCHECK(!callback.is_null());
   safe_browsing_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::AddDatabaseChunks, this,
-                 list, base::Passed(&chunks), callback));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::AddDatabaseChunks, this,
+                     list, base::Passed(&chunks), callback));
 }
 
 void LocalSafeBrowsingDatabaseManager::DeleteChunks(
@@ -643,8 +645,8 @@
   DCHECK(enabled_);
   safe_browsing_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::DeleteDatabaseChunks, this,
-                 base::Passed(&chunk_deletes)));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::DeleteDatabaseChunks,
+                     this, base::Passed(&chunk_deletes)));
 }
 
 void LocalSafeBrowsingDatabaseManager::UpdateStarted() {
@@ -661,8 +663,9 @@
     update_in_progress_ = false;
     safe_browsing_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&LocalSafeBrowsingDatabaseManager::DatabaseUpdateFinished,
-                   this, update_succeeded));
+        base::BindOnce(
+            &LocalSafeBrowsingDatabaseManager::DatabaseUpdateFinished, this,
+            update_succeeded));
   }
 }
 
@@ -671,7 +674,7 @@
   DCHECK(enabled_);
   safe_browsing_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::OnResetDatabase, this));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::OnResetDatabase, this));
 }
 
 void LocalSafeBrowsingDatabaseManager::StartOnIOThread(
@@ -771,7 +774,8 @@
     closing_database_ = true;
     safe_browsing_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&LocalSafeBrowsingDatabaseManager::OnCloseDatabase, this));
+        base::BindOnce(&LocalSafeBrowsingDatabaseManager::OnCloseDatabase,
+                       this));
   }
 
   // Delete pending checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'.
@@ -798,9 +802,10 @@
   if (DatabaseAvailable())
     return true;
   safe_browsing_task_runner_->PostTask(
-      FROM_HERE, base::Bind(base::IgnoreResult(
-                                &LocalSafeBrowsingDatabaseManager::GetDatabase),
-                            this));
+      FROM_HERE,
+      base::BindOnce(
+          base::IgnoreResult(&LocalSafeBrowsingDatabaseManager::GetDatabase),
+          this));
   return false;
 }
 
@@ -827,8 +832,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::DatabaseLoadComplete,
-                 this));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::DatabaseLoadComplete,
+                     this));
 
   UMA_HISTOGRAM_TIMES("SB2.DatabaseOpen", base::TimeTicks::Now() - before);
   return database_;
@@ -873,8 +878,8 @@
 
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&LocalSafeBrowsingDatabaseManager::OnRequestFullHash, this,
-                   check));
+        base::BindOnce(&LocalSafeBrowsingDatabaseManager::OnRequestFullHash,
+                       this, check));
   } else {
     // We may have cached results for previous GetHash queries.  Since
     // this data comes from cache, don't histogram hits.
@@ -888,8 +893,8 @@
   check->extended_reporting_level = GetExtendedReporting();
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::RequestFullHash, this,
-                 check));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::RequestFullHash, this,
+                     check));
 }
 
 ExtendedReportingLevel
@@ -942,7 +947,7 @@
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &LocalSafeBrowsingDatabaseManager::BeforeGetAllChunksFromDatabase,
           this, lists, database_error, callback));
 }
@@ -957,9 +962,9 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::OnGetAllChunksFromDatabase,
-                 this, lists, database_error, extended_reporting_level,
-                 callback));
+      base::BindOnce(
+          &LocalSafeBrowsingDatabaseManager::OnGetAllChunksFromDatabase, this,
+          lists, database_error, extended_reporting_level, callback));
 }
 
 void LocalSafeBrowsingDatabaseManager::OnGetAllChunksFromDatabase(
@@ -1018,8 +1023,8 @@
     GetDatabase()->InsertChunks(list_name, *chunks);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::OnAddChunksComplete, this,
-                 callback));
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::OnAddChunksComplete,
+                     this, callback));
 }
 
 void LocalSafeBrowsingDatabaseManager::DeleteDatabaseChunks(
@@ -1037,7 +1042,7 @@
   database_update_in_progress_ = false;
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &LocalSafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished, this,
           update_succeeded));
 }
@@ -1248,8 +1253,8 @@
                  check_ptr->weak_ptr_factory_->GetWeakPtr(), check_ptr));
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback,
-                 check_ptr->weak_ptr_factory_->GetWeakPtr(), check_ptr),
+      base::BindOnce(&LocalSafeBrowsingDatabaseManager::TimeoutCallback,
+                     check_ptr->weak_ptr_factory_->GetWeakPtr(), check_ptr),
       check_timeout_);
 }
 
diff --git a/chrome/browser/safe_browsing/mock_permission_report_sender.cc b/chrome/browser/safe_browsing/mock_permission_report_sender.cc
index 46510c9..04c8515 100644
--- a/chrome/browser/safe_browsing/mock_permission_report_sender.cc
+++ b/chrome/browser/safe_browsing/mock_permission_report_sender.cc
@@ -35,9 +35,8 @@
 
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(
-          &MockPermissionReportSender::NotifyReportSentOnUIThread,
-          base::Unretained(this)));
+      base::BindOnce(&MockPermissionReportSender::NotifyReportSentOnUIThread,
+                     base::Unretained(this)));
 }
 
 void MockPermissionReportSender::WaitForReportSent() {
diff --git a/chrome/browser/safe_browsing/notification_image_reporter.cc b/chrome/browser/safe_browsing/notification_image_reporter.cc
index d9e53ac..89499fa 100644
--- a/chrome/browser/safe_browsing/notification_image_reporter.cc
+++ b/chrome/browser/safe_browsing/notification_image_reporter.cc
@@ -113,8 +113,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&NotificationImageReporter::ReportNotificationImageOnUI,
-                 weak_factory_on_io_.GetWeakPtr(), profile, origin, image));
+      base::BindOnce(&NotificationImageReporter::ReportNotificationImageOnUI,
+                     weak_factory_on_io_.GetWeakPtr(), profile, origin, image));
 }
 
 double NotificationImageReporter::GetReportChance() const {
@@ -146,14 +146,14 @@
   if (GetExtendedReportingLevel(*profile->GetPrefs()) != SBER_LEVEL_SCOUT) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&NotificationImageReporter::SkippedReporting,
-                   weak_this_on_io));
+        base::BindOnce(&NotificationImageReporter::SkippedReporting,
+                       weak_this_on_io));
     return;
   }
 
   BrowserThread::GetBlockingPool()->PostWorkerTask(
       FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &NotificationImageReporter::DownscaleNotificationImageOnBlockingPool,
           weak_this_on_io, origin, image));
 }
@@ -187,10 +187,11 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&NotificationImageReporter::SendReportOnIO, weak_this_on_io,
-                 origin, base::RefCountedBytes::TakeVector(&png_bytes),
-                 gfx::Size(downscaled_image.width(), downscaled_image.height()),
-                 gfx::Size(image.width(), image.height())));
+      base::BindOnce(
+          &NotificationImageReporter::SendReportOnIO, weak_this_on_io, origin,
+          base::RefCountedBytes::TakeVector(&png_bytes),
+          gfx::Size(downscaled_image.width(), downscaled_image.height()),
+          gfx::Size(image.width(), image.height())));
 }
 
 void NotificationImageReporter::SendReportOnIO(
diff --git a/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc b/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc
index 2e0a6baf..780ff24 100644
--- a/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc
+++ b/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc
@@ -51,8 +51,8 @@
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&TestingNotificationImageReporter::SkippedReportingOnUI,
-                   base::Unretained(this)));
+        base::BindOnce(&TestingNotificationImageReporter::SkippedReportingOnUI,
+                       base::Unretained(this)));
   }
 
  private:
@@ -144,8 +144,8 @@
   base::RunLoop run_loop;
   BrowserThread::PostTaskAndReply(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&NotificationImageReporterTest::SetUpOnIO,
-                 base::Unretained(this)),
+      base::BindOnce(&NotificationImageReporterTest::SetUpOnIO,
+                     base::Unretained(this)),
       run_loop.QuitClosure());
   run_loop.Run();
 }
@@ -180,8 +180,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&NotificationImageReporterTest::ReportNotificationImageOnIO,
-                 base::Unretained(this)));
+      base::BindOnce(
+          &NotificationImageReporterTest::ReportNotificationImageOnIO,
+          base::Unretained(this)));
 }
 
 void NotificationImageReporterTest::ReportNotificationImageOnIO() {
diff --git a/chrome/browser/safe_browsing/permission_reporter_browsertest.cc b/chrome/browser/safe_browsing/permission_reporter_browsertest.cc
index 00d89850..e24e0bf 100644
--- a/chrome/browser/safe_browsing/permission_reporter_browsertest.cc
+++ b/chrome/browser/safe_browsing/permission_reporter_browsertest.cc
@@ -43,7 +43,7 @@
     base::RunLoop run_loop;
     content::BrowserThread::PostTaskAndReply(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(
+        base::BindOnce(
             &PermissionReporterBrowserTest::AttachMockReportSenderOnIOThread,
             base::Unretained(this),
             make_scoped_refptr(g_browser_process->safe_browsing_service())),
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index eaa8a85..7a3ad1a 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -194,8 +194,8 @@
   // Finish the malware details collection, send it over.
   BrowserThread::PostDelayedTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&ThreatDetails::FinishCollection, threat_details_,
-                 did_proceed, num_visits),
+      base::BindOnce(&ThreatDetails::FinishCollection, threat_details_,
+                     did_proceed, num_visits),
       delay);
 }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index 6ffaeec..b7b5542 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -99,8 +99,8 @@
 
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
-                   this, gurl, client));
+        base::BindOnce(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
+                       this, gurl, client));
     return false;
   }
 
@@ -165,8 +165,8 @@
     // Notify the UI thread that we got a report.
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&FakeSafeBrowsingUIManager::OnThreatDetailsDone, this,
-                   serialized));
+        base::BindOnce(&FakeSafeBrowsingUIManager::OnThreatDetailsDone, this,
+                       serialized));
   }
 
   void OnThreatDetailsDone(const std::string& serialized) {
@@ -354,7 +354,7 @@
   void SetUpOnMainThread() override {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
+        base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
   }
 
   void SetURLThreatType(const GURL& url, SBThreatType threat_type) {
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc
index 415a35c..9215e56 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -1568,8 +1568,9 @@
   if (!reset_factory_.HasWeakPtrs()) {
     RecordFailure(FAILURE_DATABASE_CORRUPT);
     db_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase,
-                              reset_factory_.GetWeakPtr()));
+        FROM_HERE,
+        base::BindOnce(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase,
+                       reset_factory_.GetWeakPtr()));
   }
 }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc
index 3fafd01..51461b6 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -366,8 +366,8 @@
   // new requests from using it as well.
   BrowserThread::PostNonNestableTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SafeBrowsingURLRequestContextGetter::ServiceShuttingDown,
-                 url_request_context_getter_));
+      base::BindOnce(&SafeBrowsingURLRequestContextGetter::ServiceShuttingDown,
+                     url_request_context_getter_));
 
   // Release the URLRequestContextGetter after passing it to the IOThread.  It
   // has to be released now rather than in the destructor because it can only
@@ -468,7 +468,7 @@
   ResourceRequestInfo info = ResourceRequestDetector::GetRequestInfo(request);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&SafeBrowsingService::ProcessResourceRequest, this, info));
+      base::BindOnce(&SafeBrowsingService::ProcessResourceRequest, this, info));
 #endif
 }
 
@@ -625,14 +625,14 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SafeBrowsingService::StartOnIOThread, this,
-                 base::RetainedRef(url_request_context_getter_)));
+      base::BindOnce(&SafeBrowsingService::StartOnIOThread, this,
+                     base::RetainedRef(url_request_context_getter_)));
 }
 
 void SafeBrowsingService::Stop(bool shutdown) {
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
+      base::BindOnce(&SafeBrowsingService::StopOnIOThread, this, shutdown));
 }
 
 void SafeBrowsingService::Observe(int type,
@@ -744,8 +744,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SafeBrowsingService::OnSendSerializedDownloadReport, this,
-                 report));
+      base::BindOnce(&SafeBrowsingService::OnSendSerializedDownloadReport, this,
+                     report));
 }
 
 void SafeBrowsingService::OnSendSerializedDownloadReport(
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 3d13f41..d21988ce 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -405,7 +405,7 @@
                    ExtendedReportingLevel reporting_level) override {
     BrowserThread::PostDelayedTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(InvokeFullHashCallback, callback, full_hashes_), delay_);
+        base::BindOnce(InvokeFullHashCallback, callback, full_hashes_), delay_);
   }
 
   // Prepare the GetFullHash results for the next request.
@@ -1193,21 +1193,22 @@
   void CheckDownloadUrl(const std::vector<GURL>& url_chain) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&TestSBClient::CheckDownloadUrlOnIOThread, this, url_chain));
+        base::BindOnce(&TestSBClient::CheckDownloadUrlOnIOThread, this,
+                       url_chain));
     content::RunMessageLoop();  // Will stop in OnCheckDownloadUrlResult.
   }
 
   void CheckBrowseUrl(const GURL& url) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&TestSBClient::CheckBrowseUrlOnIOThread, this, url));
+        base::BindOnce(&TestSBClient::CheckBrowseUrlOnIOThread, this, url));
     content::RunMessageLoop();  // Will stop in OnCheckBrowseUrlResult.
   }
 
   void CheckResourceUrl(const GURL& url) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&TestSBClient::CheckResourceUrlOnIOThread, this, url));
+        base::BindOnce(&TestSBClient::CheckResourceUrlOnIOThread, this, url));
     content::RunMessageLoop();  // Will stop in OnCheckResourceUrlResult.
   }
 
@@ -1222,7 +1223,7 @@
     if (synchronous_safe_signal) {
       threat_type_ = SB_THREAT_TYPE_SAFE;
       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                              base::Bind(&TestSBClient::CheckDone, this));
+                              base::BindOnce(&TestSBClient::CheckDone, this));
     }
   }
 
@@ -1234,7 +1235,7 @@
     if (synchronous_safe_signal) {
       threat_type_ = SB_THREAT_TYPE_SAFE;
       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                              base::Bind(&TestSBClient::CheckDone, this));
+                              base::BindOnce(&TestSBClient::CheckDone, this));
     }
   }
 
@@ -1244,7 +1245,7 @@
     if (synchronous_safe_signal) {
       threat_type_ = SB_THREAT_TYPE_SAFE;
       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                              base::Bind(&TestSBClient::CheckDone, this));
+                              base::BindOnce(&TestSBClient::CheckDone, this));
     }
   }
 
@@ -1253,7 +1254,7 @@
                                 SBThreatType threat_type) override {
     threat_type_ = threat_type;
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(&TestSBClient::CheckDone, this));
+                            base::BindOnce(&TestSBClient::CheckDone, this));
   }
 
   // Called when the result of checking a browse URL is known.
@@ -1262,7 +1263,7 @@
                               const ThreatMetadata& /* metadata */) override {
     threat_type_ = threat_type;
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(&TestSBClient::CheckDone, this));
+                            base::BindOnce(&TestSBClient::CheckDone, this));
   }
 
   // Called when the result of checking a resource URL is known.
@@ -1272,7 +1273,7 @@
     threat_type_ = threat_type;
     threat_hash_ = threat_hash;
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(&TestSBClient::CheckDone, this));
+                            base::BindOnce(&TestSBClient::CheckDone, this));
   }
 
   void CheckDone() { base::MessageLoopForUI::current()->QuitWhenIdle(); }
@@ -1780,8 +1781,8 @@
           sb_factory_->test_safe_browsing_service()->database_manager().get()));
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SafeBrowsingDatabaseManagerCookieTest::ForceUpdate,
-                 base::Unretained(this)));
+      base::BindOnce(&SafeBrowsingDatabaseManagerCookieTest::ForceUpdate,
+                     base::Unretained(this)));
   observer.Wait();
 }
 
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
index 91ecc54..a456507 100644
--- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
+++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
@@ -32,7 +32,7 @@
           .WithPriority(base::TaskPriority::BACKGROUND)
           .WithShutdownBehavior(
               base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
-      base::Bind(&SandboxedZipAnalyzer::PrepareFileToAnalyze, this));
+      base::BindOnce(&SandboxedZipAnalyzer::PrepareFileToAnalyze, this));
 }
 
 SandboxedZipAnalyzer::~SandboxedZipAnalyzer() = default;
@@ -63,15 +63,15 @@
 
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&SandboxedZipAnalyzer::AnalyzeFile, this, base::Passed(&file),
-                 base::Passed(&temp_file)));
+      base::BindOnce(&SandboxedZipAnalyzer::AnalyzeFile, this,
+                     base::Passed(&file), base::Passed(&temp_file)));
 }
 
 void SandboxedZipAnalyzer::ReportFileFailure() {
   DCHECK(!utility_process_mojo_client_);
 
   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
-                                   base::Bind(callback_, Results()));
+                                   base::BindOnce(callback_, Results()));
 }
 
 void SandboxedZipAnalyzer::AnalyzeFile(base::File file, base::File temp_file) {
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
index 31fe8da1..24d2a22 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
@@ -253,7 +253,8 @@
   base::TimeDelta delay = config->delay_before_prompt();
   content::BrowserThread::PostDelayedTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(MaybeShowSettingsResetPrompt, base::Passed(&config)), delay);
+      base::BindOnce(MaybeShowSettingsResetPrompt, base::Passed(&config)),
+      delay);
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
index dd78583..dbac8e3d 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
@@ -144,7 +144,7 @@
   DCHECK(default_settings);
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(std::move(callback_), base::Passed(&default_settings)));
+      base::BindOnce(std::move(callback_), base::Passed(&default_settings)));
   delete this;
 }
 
diff --git a/chrome/browser/safe_browsing/threat_details.cc b/chrome/browser/safe_browsing/threat_details.cc
index 4c2d0f84..8916516 100644
--- a/chrome/browser/safe_browsing/threat_details.cc
+++ b/chrome/browser/safe_browsing/threat_details.cc
@@ -454,10 +454,11 @@
     const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params) {
   // Schedule this in IO thread, so it doesn't conflict with future users
   // of our data structures (eg GetSerializedReport).
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(&ThreatDetails::AddDOMDetails, this,
-                                     sender->GetFrameTreeNodeId(),
-                                     sender->GetLastCommittedURL(), params));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&ThreatDetails::AddDOMDetails, this,
+                     sender->GetFrameTreeNodeId(),
+                     sender->GetLastCommittedURL(), params));
 }
 
 void ThreatDetails::AddDOMDetails(
diff --git a/chrome/browser/safe_browsing/threat_details_cache.cc b/chrome/browser/safe_browsing/threat_details_cache.cc
index b5eff14..071bc9ef5 100644
--- a/chrome/browser/safe_browsing/threat_details_cache.cc
+++ b/chrome/browser/safe_browsing/threat_details_cache.cc
@@ -54,7 +54,7 @@
   // check if we call their callback immediately.
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&ThreatDetailsCacheCollector::OpenEntry, this));
+      base::BindOnce(&ThreatDetailsCacheCollector::OpenEntry, this));
 }
 
 bool ThreatDetailsCacheCollector::HasStarted() {
@@ -228,7 +228,7 @@
   // Create a task so we don't take over the IO thread for too long.
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&ThreatDetailsCacheCollector::OpenEntry, this));
+      base::BindOnce(&ThreatDetailsCacheCollector::OpenEntry, this));
 }
 
 void ThreatDetailsCacheCollector::AllDone(bool success) {
diff --git a/chrome/browser/safe_browsing/threat_details_history.cc b/chrome/browser/safe_browsing/threat_details_history.cc
index 4c0c6ec..4a0157890 100644
--- a/chrome/browser/safe_browsing/threat_details_history.cc
+++ b/chrome/browser/safe_browsing/threat_details_history.cc
@@ -46,8 +46,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&ThreatDetailsRedirectsCollector::StartGetRedirects, this,
-                 urls));
+      base::BindOnce(&ThreatDetailsRedirectsCollector::StartGetRedirects, this,
+                     urls));
 }
 
 bool ThreatDetailsRedirectsCollector::HasStarted() const {
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
index 18cb1cd..33d428d 100644
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -223,8 +223,8 @@
                                       bool did_proceed,
                                       int num_visit) {
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                            base::Bind(&ThreatDetails::FinishCollection, report,
-                                       did_proceed, num_visit));
+                            base::BindOnce(&ThreatDetails::FinishCollection,
+                                           report, did_proceed, num_visit));
     // Wait for the callback (SendSerializedThreatDetails).
     DVLOG(1) << "Waiting for SendSerializedThreatDetails";
     base::RunLoop run_loop;
@@ -1079,8 +1079,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&FillCache,
-                 base::RetainedRef(profile()->GetRequestContext())));
+      base::BindOnce(&FillCache,
+                     base::RetainedRef(profile()->GetRequestContext())));
 
   // The cache collection starts after the IPC from the DOM is fired.
   std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node> params;
@@ -1162,8 +1162,8 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&FillCacheHttps,
-                 base::RetainedRef(profile()->GetRequestContext())));
+      base::BindOnce(&FillCacheHttps,
+                     base::RetainedRef(profile()->GetRequestContext())));
 
   // The cache collection starts after the IPC from the DOM is fired.
   std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node> params;
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc
index f20caf34..99b1c30a 100644
--- a/chrome/browser/safe_browsing/ui_manager.cc
+++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -114,8 +114,8 @@
   if (hit_report.extended_reporting_level != SBER_LEVEL_OFF) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&SafeBrowsingUIManager::ReportSafeBrowsingHitOnIOThread,
-                   this, hit_report));
+        base::BindOnce(&SafeBrowsingUIManager::ReportSafeBrowsingHitOnIOThread,
+                       this, hit_report));
   }
 }
 
@@ -139,8 +139,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SafeBrowsingUIManager::ReportPermissionActionOnIOThread, this,
-                 report_info));
+      base::BindOnce(&SafeBrowsingUIManager::ReportPermissionActionOnIOThread,
+                     this, report_info));
 }
 
 // Static.
diff --git a/chrome/browser/safe_browsing/ui_manager_unittest.cc b/chrome/browser/safe_browsing/ui_manager_unittest.cc
index 74d7a839..9a421b5 100644
--- a/chrome/browser/safe_browsing/ui_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/ui_manager_unittest.cc
@@ -51,8 +51,8 @@
      DCHECK_CURRENTLY_ON(BrowserThread::IO);
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
-         base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
-                    base::Unretained(this), proceed));
+         base::BindOnce(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
+                        base::Unretained(this), proceed));
    }
 
    void WaitForCallback() {
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc
index e3c344a..e72b5b3 100644
--- a/chrome/browser/signin/easy_unlock_service.cc
+++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -119,7 +119,7 @@
   }
 
   void Initialize() {
-    if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
+    if (!device::BluetoothAdapterFactory::IsBluetoothSupported())
       return;
 
     device::BluetoothAdapterFactory::GetAdapter(
diff --git a/chrome/browser/sync/glue/sync_start_util.cc b/chrome/browser/sync/glue/sync_start_util.cc
index 504e82a..c99f1e4 100644
--- a/chrome/browser/sync/glue/sync_start_util.cc
+++ b/chrome/browser/sync/glue/sync_start_util.cc
@@ -43,7 +43,7 @@
                     syncer::ModelType type) {
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&StartSyncOnUIThread, profile, type));
+      base::BindOnce(&StartSyncOnUIThread, profile, type));
 }
 
 }  // namespace
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index 0efcc882..743d212 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -88,8 +88,8 @@
                        const base::TimeDelta& latency) {
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&UpdateNetworkTimeOnUIThread, network_time, resolution,
-                 latency, base::TimeTicks::Now()));
+      base::BindOnce(&UpdateNetworkTimeOnUIThread, network_time, resolution,
+                     latency, base::TimeTicks::Now()));
 }
 
 }  // anonymous namespace
diff --git a/chrome/browser/sync/test/integration/autofill_helper.cc b/chrome/browser/sync/test/integration/autofill_helper.cc
index 1a7c868..7a331510 100644
--- a/chrome/browser/sync/test/integration/autofill_helper.cc
+++ b/chrome/browser/sync/test/integration/autofill_helper.cc
@@ -70,9 +70,8 @@
 void RunOnDBThreadAndBlock(base::Closure task) {
   WaitableEvent done_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  BrowserThread::PostTask(BrowserThread::DB,
-                          FROM_HERE,
-                          Bind(&RunOnDBThreadAndSignal, task, &done_event));
+  BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+                          BindOnce(&RunOnDBThreadAndSignal, task, &done_event));
   done_event.Wait();
 }
 
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
index 4c664c2..1768ca8c 100644
--- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
@@ -56,7 +56,7 @@
 bool WaitForExistingTasksOnLoop(base::MessageLoop* loop) {
   base::WaitableEvent e(base::WaitableEvent::ResetPolicy::MANUAL,
                         base::WaitableEvent::InitialState::NOT_SIGNALED);
-  loop->task_runner()->PostTask(FROM_HERE, base::Bind(&SignalEvent, &e));
+  loop->task_runner()->PostTask(FROM_HERE, base::BindOnce(&SignalEvent, &e));
   // Timeout stolen from StatusChangeChecker::GetTimeoutDuration().
   return e.TimedWait(base::TimeDelta::FromSeconds(45));
 }
diff --git a/chrome/browser/sync/test/integration/sync_extension_installer.cc b/chrome/browser/sync/test/integration/sync_extension_installer.cc
index e149f8e5..ad603cc 100644
--- a/chrome/browser/sync/test/integration/sync_extension_installer.cc
+++ b/chrome/browser/sync/test/integration/sync_extension_installer.cc
@@ -40,8 +40,8 @@
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&SyncedExtensionInstaller::DoInstallSyncedExtensions,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindOnce(&SyncedExtensionInstaller::DoInstallSyncedExtensions,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void SyncedExtensionInstaller::DoInstallSyncedExtensions() {
diff --git a/chrome/browser/sync_file_system/drive_backend/callback_helper.h b/chrome/browser/sync_file_system/drive_backend/callback_helper.h
index e1064b2..d4fac2f2 100644
--- a/chrome/browser/sync_file_system/drive_backend/callback_helper.h
+++ b/chrome/browser/sync_file_system/drive_backend/callback_helper.h
@@ -78,7 +78,7 @@
   static void Run(CallbackHolder<void(Args...)>* holder, Args... args) {
     holder->task_runner()->PostTask(
         holder->from_here(),
-        base::Bind(holder->callback(), RebindForward(args)...));
+        base::BindOnce(holder->callback(), RebindForward(args)...));
   }
 };
 
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
index 300fdc8..c2079d21 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
@@ -597,11 +597,9 @@
     base::RunLoop run_loop;
     worker_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&SyncWorker::CallOnIdleForTesting,
-                   base::Unretained(sync_worker()),
-                   RelayCallbackToCurrentThread(
-                       FROM_HERE,
-                       run_loop.QuitClosure())));
+        base::BindOnce(
+            &SyncWorker::CallOnIdleForTesting, base::Unretained(sync_worker()),
+            RelayCallbackToCurrentThread(FROM_HERE, run_loop.QuitClosure())));
     run_loop.Run();
   }
 
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc b/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc
index feb163f..90956d3 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_service_on_worker.cc
@@ -37,13 +37,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::AddNewDirectory,
-                 wrapper_,
-                 parent_resource_id,
-                 directory_title,
-                 options,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::AddNewDirectory, wrapper_,
+                     parent_resource_id, directory_title, options,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -56,12 +53,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::DeleteResource,
-                 wrapper_,
-                 resource_id,
-                 etag,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::DeleteResource, wrapper_,
+                     resource_id, etag,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -76,17 +71,15 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(
-          &DriveServiceWrapper::DownloadFile,
-          wrapper_,
-          local_cache_path,
+      base::BindOnce(
+          &DriveServiceWrapper::DownloadFile, wrapper_, local_cache_path,
           resource_id,
-          RelayCallbackToTaskRunner(
-              worker_task_runner_.get(), FROM_HERE, download_action_callback),
-          RelayCallbackToTaskRunner(
-              worker_task_runner_.get(), FROM_HERE, get_content_callback),
-          RelayCallbackToTaskRunner(
-              worker_task_runner_.get(), FROM_HERE, progress_callback)));
+          RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
+                                    download_action_callback),
+          RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
+                                    get_content_callback),
+          RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
+                                    progress_callback)));
 
   return google_apis::CancelCallback();
 }
@@ -97,10 +90,9 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::GetAboutResource,
-                 wrapper_,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::GetAboutResource, wrapper_,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -112,11 +104,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::GetChangeList,
-                 wrapper_,
-                 start_changestamp,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::GetChangeList, wrapper_,
+                     start_changestamp,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -128,11 +119,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::GetRemainingChangeList,
-                 wrapper_,
-                 next_link,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::GetRemainingChangeList, wrapper_,
+                     next_link,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -150,11 +140,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::GetRemainingFileList,
-                 wrapper_,
-                 next_link,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::GetRemainingFileList, wrapper_,
+                     next_link,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -167,11 +156,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::GetFileResource,
-                 wrapper_,
-                 resource_id,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::GetFileResource, wrapper_,
+                     resource_id,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -183,11 +171,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::GetFileListInDirectory,
-                 wrapper_,
-                 directory_resource_id,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::GetFileListInDirectory, wrapper_,
+                     directory_resource_id,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -200,12 +187,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::RemoveResourceFromDirectory,
-                 wrapper_,
-                 parent_resource_id,
-                 resource_id,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::RemoveResourceFromDirectory,
+                     wrapper_, parent_resource_id, resource_id,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -218,12 +203,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveServiceWrapper::SearchByTitle,
-                 wrapper_,
-                 title,
-                 directory_resource_id,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveServiceWrapper::SearchByTitle, wrapper_, title,
+                     directory_resource_id,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_uploader_on_worker.cc b/chrome/browser/sync_file_system/drive_backend/drive_uploader_on_worker.cc
index 0f938f9d..12def807 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_uploader_on_worker.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_uploader_on_worker.cc
@@ -45,15 +45,11 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveUploaderWrapper::UploadNewFile,
-                 wrapper_,
-                 parent_resource_id,
-                 local_file_path,
-                 title,
-                 content_type,
-                 options,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveUploaderWrapper::UploadNewFile, wrapper_,
+                     parent_resource_id, local_file_path, title, content_type,
+                     options,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
@@ -69,14 +65,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DriveUploaderWrapper::UploadExistingFile,
-                 wrapper_,
-                 resource_id,
-                 local_file_path,
-                 content_type,
-                 options,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&DriveUploaderWrapper::UploadExistingFile, wrapper_,
+                     resource_id, local_file_path, content_type, options,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 
   return google_apis::CancelCallback();
 }
diff --git a/chrome/browser/sync_file_system/drive_backend/fake_drive_uploader.cc b/chrome/browser/sync_file_system/drive_backend/fake_drive_uploader.cc
index a49bead..3d7d5989 100644
--- a/chrome/browser/sync_file_system/drive_backend/fake_drive_uploader.cc
+++ b/chrome/browser/sync_file_system/drive_backend/fake_drive_uploader.cc
@@ -38,11 +38,8 @@
   ASSERT_EQ(google_apis::HTTP_CREATED, error);
   ASSERT_TRUE(entry);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(callback,
-                 google_apis::HTTP_SUCCESS,
-                 GURL(),
-                 base::Passed(&entry)));
+      FROM_HERE, base::BindOnce(callback, google_apis::HTTP_SUCCESS, GURL(),
+                                base::Passed(&entry)));
 }
 
 void DidGetFileResourceForUploadExisting(
@@ -50,11 +47,7 @@
     DriveApiErrorCode error,
     std::unique_ptr<FileResource> entry) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(callback,
-                 error,
-                 GURL(),
-                 base::Passed(&entry)));
+      FROM_HERE, base::BindOnce(callback, error, GURL(), base::Passed(&entry)));
 }
 
 }  // namespace
diff --git a/chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.cc b/chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.cc
index 858a5b0..335b83da 100644
--- a/chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.cc
+++ b/chrome/browser/sync_file_system/drive_backend/remote_change_processor_on_worker.cc
@@ -37,11 +37,11 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&RemoteChangeProcessorWrapper::PrepareForProcessRemoteChange,
-                 wrapper_,
-                 url,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(
+          &RemoteChangeProcessorWrapper::PrepareForProcessRemoteChange,
+          wrapper_, url,
+          RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
+                                    callback)));
 }
 
 void RemoteChangeProcessorOnWorker::ApplyRemoteChange(
@@ -53,13 +53,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&RemoteChangeProcessorWrapper::ApplyRemoteChange,
-                 wrapper_,
-                 change,
-                 local_path,
-                 url,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&RemoteChangeProcessorWrapper::ApplyRemoteChange, wrapper_,
+                     change, local_path, url,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 }
 
 void RemoteChangeProcessorOnWorker::FinalizeRemoteSync(
@@ -70,13 +67,11 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(
-          &RemoteChangeProcessorWrapper::FinalizeRemoteSync,
-          wrapper_,
-          url,
+      base::BindOnce(
+          &RemoteChangeProcessorWrapper::FinalizeRemoteSync, wrapper_, url,
           clear_local_changes,
-          RelayCallbackToTaskRunner(
-              worker_task_runner_.get(), FROM_HERE, completion_callback)));
+          RelayCallbackToTaskRunner(worker_task_runner_.get(), FROM_HERE,
+                                    completion_callback)));
 }
 
 void RemoteChangeProcessorOnWorker::RecordFakeLocalChange(
@@ -87,12 +82,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&RemoteChangeProcessorWrapper::RecordFakeLocalChange,
-                 wrapper_,
-                 url,
-                 change,
-                 RelayCallbackToTaskRunner(
-                     worker_task_runner_.get(), FROM_HERE, callback)));
+      base::BindOnce(&RemoteChangeProcessorWrapper::RecordFakeLocalChange,
+                     wrapper_, url, change,
+                     RelayCallbackToTaskRunner(worker_task_runner_.get(),
+                                               FROM_HERE, callback)));
 }
 
 void RemoteChangeProcessorOnWorker::DetachFromSequence() {
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
index ac1af18..5f8fee8 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -126,10 +126,8 @@
 
     DCHECK(sequence_checker_.CalledOnValidSequence());
     ui_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&SyncEngine::OnPendingFileListUpdated,
-                   sync_engine_,
-                   item_count));
+        FROM_HERE, base::BindOnce(&SyncEngine::OnPendingFileListUpdated,
+                                  sync_engine_, item_count));
   }
 
   void OnFileStatusChanged(const storage::FileSystemURL& url,
@@ -147,9 +145,8 @@
     DCHECK(sequence_checker_.CalledOnValidSequence());
     ui_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&SyncEngine::OnFileStatusChanged,
-                   sync_engine_,
-                   url, file_type, file_status, sync_action, direction));
+        base::BindOnce(&SyncEngine::OnFileStatusChanged, sync_engine_, url,
+                       file_type, file_status, sync_action, direction));
   }
 
   void UpdateServiceState(RemoteServiceState state,
@@ -162,9 +159,8 @@
 
     DCHECK(sequence_checker_.CalledOnValidSequence());
     ui_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&SyncEngine::UpdateServiceState,
-                   sync_engine_, state, description));
+        FROM_HERE, base::BindOnce(&SyncEngine::UpdateServiceState, sync_engine_,
+                                  state, description));
   }
 
   void DetachFromSequence() {
@@ -345,10 +341,9 @@
   sync_worker_->AddObserver(worker_observer_.get());
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::Initialize,
-                 base::Unretained(sync_worker_.get()),
-                 base::Passed(&sync_engine_context)));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::Initialize,
+                                base::Unretained(sync_worker_.get()),
+                                base::Passed(&sync_engine_context)));
   if (remote_change_processor_)
     SetRemoteChangeProcessor(remote_change_processor_);
 
@@ -387,10 +382,9 @@
                             TrackCallback(callback)));
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::RegisterOrigin,
-                 base::Unretained(sync_worker_.get()),
-                 origin, relayed_callback));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::RegisterOrigin,
+                                base::Unretained(sync_worker_.get()), origin,
+                                relayed_callback));
 }
 
 void SyncEngine::EnableOrigin(
@@ -406,10 +400,9 @@
       FROM_HERE, TrackCallback(callback));
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::EnableOrigin,
-                 base::Unretained(sync_worker_.get()),
-                 origin, relayed_callback));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::EnableOrigin,
+                                base::Unretained(sync_worker_.get()), origin,
+                                relayed_callback));
 }
 
 void SyncEngine::DisableOrigin(
@@ -425,11 +418,9 @@
       FROM_HERE, TrackCallback(callback));
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::DisableOrigin,
-                 base::Unretained(sync_worker_.get()),
-                 origin,
-                 relayed_callback));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::DisableOrigin,
+                                base::Unretained(sync_worker_.get()), origin,
+                                relayed_callback));
 }
 
 void SyncEngine::UninstallOrigin(
@@ -446,10 +437,9 @@
   SyncStatusCallback relayed_callback = RelayCallbackToCurrentThread(
       FROM_HERE, TrackCallback(callback));
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::UninstallOrigin,
-                 base::Unretained(sync_worker_.get()),
-                 origin, flag, relayed_callback));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::UninstallOrigin,
+                                base::Unretained(sync_worker_.get()), origin,
+                                flag, relayed_callback));
 }
 
 void SyncEngine::ProcessRemoteChange(const SyncFileCallback& callback) {
@@ -472,9 +462,8 @@
       FROM_HERE, tracked_callback);
   worker_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorkerInterface::ProcessRemoteChange,
-                 base::Unretained(sync_worker_.get()),
-                 relayed_callback));
+      base::BindOnce(&SyncWorkerInterface::ProcessRemoteChange,
+                     base::Unretained(sync_worker_.get()), relayed_callback));
 }
 
 void SyncEngine::SetRemoteChangeProcessor(RemoteChangeProcessor* processor) {
@@ -492,10 +481,9 @@
       worker_task_runner_.get()));
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::SetRemoteChangeProcessor,
-                 base::Unretained(sync_worker_.get()),
-                 remote_change_processor_on_worker_.get()));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::SetRemoteChangeProcessor,
+                                base::Unretained(sync_worker_.get()),
+                                remote_change_processor_on_worker_.get()));
 }
 
 LocalChangeProcessor* SyncEngine::GetLocalChangeProcessor() {
@@ -526,9 +514,8 @@
 
   worker_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorkerInterface::GetOriginStatusMap,
-                 base::Unretained(sync_worker_.get()),
-                 relayed_callback));
+      base::BindOnce(&SyncWorkerInterface::GetOriginStatusMap,
+                     base::Unretained(sync_worker_.get()), relayed_callback));
 }
 
 void SyncEngine::DumpFiles(const GURL& origin,
@@ -586,9 +573,8 @@
 
     worker_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&SyncWorkerInterface::SetSyncEnabled,
-                   base::Unretained(sync_worker_.get()),
-                   sync_enabled_));
+        base::BindOnce(&SyncWorkerInterface::SetSyncEnabled,
+                       base::Unretained(sync_worker_.get()), sync_enabled_));
     return;
   }
 
@@ -599,9 +585,8 @@
   // let SyncEngine handle the flag.
   worker_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorkerInterface::SetSyncEnabled,
-                 base::Unretained(sync_worker_.get()),
-                 sync_enabled_));
+      base::BindOnce(&SyncWorkerInterface::SetSyncEnabled,
+                     base::Unretained(sync_worker_.get()), sync_enabled_));
   Reset();
 }
 
@@ -616,9 +601,8 @@
 
   worker_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorkerInterface::PromoteDemotedChanges,
-                 base::Unretained(sync_worker_.get()),
-                 relayed_callback));
+      base::BindOnce(&SyncWorkerInterface::PromoteDemotedChanges,
+                     base::Unretained(sync_worker_.get()), relayed_callback));
 }
 
 void SyncEngine::ApplyLocalChange(const FileChange& local_change,
@@ -640,13 +624,9 @@
       FROM_HERE, TrackCallback(callback));
   worker_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorkerInterface::ApplyLocalChange,
-                 base::Unretained(sync_worker_.get()),
-                 local_change,
-                 local_path,
-                 local_metadata,
-                 url,
-                 relayed_callback));
+      base::BindOnce(&SyncWorkerInterface::ApplyLocalChange,
+                     base::Unretained(sync_worker_.get()), local_change,
+                     local_path, local_metadata, url, relayed_callback));
 }
 
 void SyncEngine::OnNotificationReceived() {
@@ -655,10 +635,9 @@
 
   worker_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorkerInterface::ActivateService,
-                 base::Unretained(sync_worker_.get()),
-                 REMOTE_SERVICE_OK,
-                 "Got push notification for Drive"));
+      base::BindOnce(&SyncWorkerInterface::ActivateService,
+                     base::Unretained(sync_worker_.get()), REMOTE_SERVICE_OK,
+                     "Got push notification for Drive"));
 }
 
 void SyncEngine::OnPushNotificationEnabled(bool /* enabled */) {}
@@ -669,11 +648,9 @@
     return;
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::ActivateService,
-                 base::Unretained(sync_worker_.get()),
-                 REMOTE_SERVICE_OK,
-                 "Authenticated"));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::ActivateService,
+                                base::Unretained(sync_worker_.get()),
+                                REMOTE_SERVICE_OK, "Authenticated"));
 }
 
 void SyncEngine::OnRefreshTokenInvalid() {
@@ -682,10 +659,9 @@
     return;
 
   worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&SyncWorkerInterface::DeactivateService,
-                 base::Unretained(sync_worker_.get()),
-                 "Found invalid refresh token."));
+      FROM_HERE, base::BindOnce(&SyncWorkerInterface::DeactivateService,
+                                base::Unretained(sync_worker_.get()),
+                                "Found invalid refresh token."));
 }
 
 void SyncEngine::OnNetworkChanged(
@@ -698,17 +674,14 @@
 
   if (!network_available_old && network_available_) {
     worker_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&SyncWorkerInterface::ActivateService,
-                   base::Unretained(sync_worker_.get()),
-                   REMOTE_SERVICE_OK,
-                   "Connected"));
+        FROM_HERE, base::BindOnce(&SyncWorkerInterface::ActivateService,
+                                  base::Unretained(sync_worker_.get()),
+                                  REMOTE_SERVICE_OK, "Connected"));
   } else if (network_available_old && !network_available_) {
     worker_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&SyncWorkerInterface::DeactivateService,
-                   base::Unretained(sync_worker_.get()),
-                   "Disconnected"));
+        base::BindOnce(&SyncWorkerInterface::DeactivateService,
+                       base::Unretained(sync_worker_.get()), "Disconnected"));
   }
 }
 
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
index e26153f..4959849 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
@@ -97,11 +97,9 @@
   void PostUpdateServiceState(RemoteServiceState state,
                               const std::string& description) {
     worker_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&FakeSyncWorker::UpdateServiceState,
-                   base::Unretained(fake_sync_worker()),
-                   state,
-                   description));
+        FROM_HERE, base::BindOnce(&FakeSyncWorker::UpdateServiceState,
+                                  base::Unretained(fake_sync_worker()), state,
+                                  description));
     WaitForWorkerTaskRunner();
   }
 
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc b/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc
index b971db1..08cc59d 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc
@@ -262,8 +262,8 @@
   // making the call-chaing longer.
   task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&SyncTaskManager::MaybeStartNextForegroundTask,
-                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
+      base::BindOnce(&SyncTaskManager::MaybeStartNextForegroundTask,
+                     weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
 }
 
 void SyncTaskManager::UpdateTaskBlockerBody(
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
index 730cfad..f6f22e8 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
@@ -34,8 +34,8 @@
 
 void DumbTask(SyncStatusCode status,
               const SyncStatusCallback& callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                base::Bind(callback, status));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(callback, status));
 }
 
 void IncrementAndAssign(int expected_before_counter,
@@ -110,7 +110,7 @@
     if (is_idle_task)
       ++idle_task_scheduled_count_;
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, status_to_return));
+        FROM_HERE, base::BindOnce(callback, status_to_return));
   }
 
   std::unique_ptr<SyncTaskManager> task_manager_;
@@ -141,8 +141,8 @@
     DCHECK(!*task_started_);
     *task_started_ = true;
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&MultihopSyncTask::CompleteTask,
-                              weak_ptr_factory_.GetWeakPtr(), callback));
+        FROM_HERE, base::BindOnce(&MultihopSyncTask::CompleteTask,
+                                  weak_ptr_factory_.GetWeakPtr(), callback));
   }
 
  private:
@@ -203,8 +203,8 @@
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&BackgroundTask::CompleteTask,
-                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
+        base::BindOnce(&BackgroundTask::CompleteTask,
+                       weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
   }
 
   void CompleteTask(std::unique_ptr<SyncTaskToken> token) {
@@ -273,8 +273,8 @@
     log_->push_back(name_ + ": updated to " + updated_to);
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&BlockerUpdateTestHelper::UpdateBlocker,
-                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
+        base::BindOnce(&BlockerUpdateTestHelper::UpdateBlocker,
+                       weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
   }
 
   std::string name_;
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_worker.cc b/chrome/browser/sync_file_system/drive_backend/sync_worker.cc
index ab007c4..31716e3d7 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_worker.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_worker.cc
@@ -290,9 +290,8 @@
 
   context_->GetUITaskRunner()->PostTask(
       FROM_HERE,
-      base::Bind(&TaskLogger::RecordLog,
-                 context_->GetTaskLogger(),
-                 base::Passed(&task_log)));
+      base::BindOnce(&TaskLogger::RecordLog, context_->GetTaskLogger(),
+                     base::Passed(&task_log)));
 }
 
 void SyncWorker::ActivateService(RemoteServiceState service_state,
@@ -408,13 +407,10 @@
 
   context_->GetUITaskRunner()->PostTask(
       FROM_HERE,
-      base::Bind(&SyncWorker::QueryAppStatusOnUIThread,
-                 extension_service_,
-                 base::Owned(app_ids.release()),
-                 app_status,
-                 RelayCallbackToTaskRunner(
-                     context_->GetWorkerTaskRunner(),
-                     FROM_HERE, callback)));
+      base::BindOnce(&SyncWorker::QueryAppStatusOnUIThread, extension_service_,
+                     base::Owned(app_ids.release()), app_status,
+                     RelayCallbackToTaskRunner(context_->GetWorkerTaskRunner(),
+                                               FROM_HERE, callback)));
 }
 
 void SyncWorker::QueryAppStatusOnUIThread(
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_worker_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_worker_unittest.cc
index c1a0b57..8c9e2b1 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_worker_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_worker_unittest.cc
@@ -39,8 +39,8 @@
 const char kAppID[] = "app_id";
 
 void EmptyTask(SyncStatusCode status, const SyncStatusCallback& callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                base::Bind(callback, status));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(callback, status));
 }
 
 }  // namespace
diff --git a/chrome/browser/sync_file_system/fake_remote_change_processor.cc b/chrome/browser/sync_file_system/fake_remote_change_processor.cc
index 5ea713d..efe450b 100644
--- a/chrome/browser/sync_file_system/fake_remote_change_processor.cc
+++ b/chrome/browser/sync_file_system/fake_remote_change_processor.cc
@@ -61,8 +61,7 @@
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(callback, SYNC_STATUS_OK,
-                 local_metadata, change_list));
+      base::BindOnce(callback, SYNC_STATUS_OK, local_metadata, change_list));
 }
 
 void FakeRemoteChangeProcessor::ApplyRemoteChange(
@@ -99,7 +98,7 @@
     status = SYNC_STATUS_OK;
   }
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(callback, status));
+      FROM_HERE, base::BindOnce(callback, status));
 }
 
 void FakeRemoteChangeProcessor::FinalizeRemoteSync(
@@ -115,7 +114,7 @@
     const SyncStatusCallback& callback) {
   local_changes_[url].Update(change);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+      FROM_HERE, base::BindOnce(callback, SYNC_STATUS_OK));
 }
 
 void FakeRemoteChangeProcessor::UpdateLocalFileMetadata(
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
index e22924b..47be60a 100644
--- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
+++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -68,10 +68,10 @@
   base::RunLoop run_loop;
   task_runner->PostTask(
       location,
-      base::Bind(task, base::Bind(&AssignAndQuit<R>,
-                                  base::RetainedRef(
-                                      base::ThreadTaskRunnerHandle::Get()),
-                                  run_loop.QuitClosure(), &result)));
+      base::BindOnce(task, base::Bind(&AssignAndQuit<R>,
+                                      base::RetainedRef(
+                                          base::ThreadTaskRunnerHandle::Get()),
+                                      run_loop.QuitClosure(), &result)));
   run_loop.Run();
   return result;
 }
@@ -80,12 +80,11 @@
                  const tracked_objects::Location& location,
                  const base::Closure& task) {
   base::RunLoop run_loop;
-  task_runner->PostTaskAndReply(
-      location, task,
-      base::Bind(base::IgnoreResult(
-          base::Bind(&base::SingleThreadTaskRunner::PostTask,
-                     base::ThreadTaskRunnerHandle::Get(),
-                     FROM_HERE, run_loop.QuitClosure()))));
+  task_runner->PostTaskAndReply(location, task,
+                                base::BindOnce(base::IgnoreResult(base::Bind(
+                                    &base::SingleThreadTaskRunner::PostTask,
+                                    base::ThreadTaskRunnerHandle::Get(),
+                                    FROM_HERE, run_loop.QuitClosure()))));
   run_loop.Run();
 }
 
@@ -98,8 +97,8 @@
     base::SingleThreadTaskRunner* runner2) {
   ASSERT_TRUE(runner1 != nullptr);
   ASSERT_TRUE(runner2 != nullptr);
-  runner1->PostTask(FROM_HERE,
-                    base::Bind(&EnsureRunningOn, base::RetainedRef(runner2)));
+  runner1->PostTask(
+      FROM_HERE, base::BindOnce(&EnsureRunningOn, base::RetainedRef(runner2)));
 }
 
 void OnCreateSnapshotFileAndVerifyData(
@@ -206,8 +205,8 @@
 
 void EnsureLastTaskRuns(base::SingleThreadTaskRunner* runner) {
   base::RunLoop run_loop;
-  runner->PostTaskAndReply(
-      FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure());
+  runner->PostTaskAndReply(FROM_HERE, base::BindOnce(&base::DoNothing),
+                           run_loop.QuitClosure());
   run_loop.Run();
 }
 
@@ -291,7 +290,7 @@
   base::RunLoop run_loop;
   io_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &CannedSyncableFileSystem::DoOpenFileSystem, base::Unretained(this),
           base::Bind(&CannedSyncableFileSystem::DidOpenFileSystem,
                      base::Unretained(this),
@@ -737,10 +736,10 @@
   if (!original_task_runner->RunsTasksOnCurrentThread()) {
     DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
     original_task_runner->PostTask(
-        FROM_HERE, base::Bind(&CannedSyncableFileSystem::DidOpenFileSystem,
-                              base::Unretained(this),
-                              base::RetainedRef(original_task_runner),
-                              quit_closure, root, name, result));
+        FROM_HERE, base::BindOnce(&CannedSyncableFileSystem::DidOpenFileSystem,
+                                  base::Unretained(this),
+                                  base::RetainedRef(original_task_runner),
+                                  quit_closure, root, name, result));
     return;
   }
   result_ = result;
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
index 90dec528..b1591527 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
@@ -71,7 +71,8 @@
   if (base::ContainsKey(file_system_contexts_, file_system_context)) {
     // The context has been already initialized. Just dispatch the callback
     // with SYNC_STATUS_OK.
-    ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+    ui_task_runner_->PostTask(FROM_HERE,
+                              base::BindOnce(callback, SYNC_STATUS_OK));
     return;
   }
 
@@ -90,13 +91,11 @@
                  this, source_url, base::RetainedRef(file_system_context));
   io_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&storage::SandboxFileSystemBackendDelegate::OpenFileSystem,
-                 base::Unretained(file_system_context->sandbox_delegate()),
-                 source_url,
-                 storage::kFileSystemTypeSyncable,
-                 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
-                 open_filesystem_callback,
-                 GURL()));
+      base::BindOnce(&storage::SandboxFileSystemBackendDelegate::OpenFileSystem,
+                     base::Unretained(file_system_context->sandbox_delegate()),
+                     source_url, storage::kFileSystemTypeSyncable,
+                     storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+                     open_filesystem_callback, GURL()));
 }
 
 void LocalFileSyncContext::ShutdownOnUIThread() {
@@ -104,7 +103,7 @@
   shutdown_on_ui_ = true;
   io_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&LocalFileSyncContext::ShutdownOnIOThread, this));
+      base::BindOnce(&LocalFileSyncContext::ShutdownOnIOThread, this));
 }
 
 void LocalFileSyncContext::GetFileForLocalSync(
@@ -131,9 +130,9 @@
           RunsTasksOnCurrentThread()) {
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     file_system_context->default_file_task_runner()->PostTask(
-        FROM_HERE,
-        base::Bind(&LocalFileSyncContext::ClearChangesForURL, this,
-                   base::RetainedRef(file_system_context), url, done_callback));
+        FROM_HERE, base::BindOnce(&LocalFileSyncContext::ClearChangesForURL,
+                                  this, base::RetainedRef(file_system_context),
+                                  url, done_callback));
     return;
   }
 
@@ -157,9 +156,9 @@
   if (!file_system_context->default_file_task_runner()->
           RunsTasksOnCurrentThread()) {
     file_system_context->default_file_task_runner()->PostTask(
-        FROM_HERE, base::Bind(&LocalFileSyncContext::FinalizeSnapshotSync, this,
-                              base::RetainedRef(file_system_context), url,
-                              sync_finish_status, done_callback));
+        FROM_HERE, base::BindOnce(&LocalFileSyncContext::FinalizeSnapshotSync,
+                                  this, base::RetainedRef(file_system_context),
+                                  url, sync_finish_status, done_callback));
     return;
   }
 
@@ -180,8 +179,9 @@
   // We've been keeping it in writing mode, so clear the writing counter
   // to unblock sync activities.
   io_task_runner_->PostTask(
-      FROM_HERE, base::Bind(
-          &LocalFileSyncContext::FinalizeSnapshotSyncOnIOThread, this, url));
+      FROM_HERE,
+      base::BindOnce(&LocalFileSyncContext::FinalizeSnapshotSyncOnIOThread,
+                     this, url));
 
   // Call the completion callback on UI thread.
   ui_task_runner_->PostTask(FROM_HERE, done_callback);
@@ -207,9 +207,8 @@
   }
 
   io_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LocalFileSyncContext::ClearSyncFlagOnIOThread,
-                 this, url, false /* for_snapshot_sync */));
+      FROM_HERE, base::BindOnce(&LocalFileSyncContext::ClearSyncFlagOnIOThread,
+                                this, url, false /* for_snapshot_sync */));
 
   done_callback.Run();
 }
@@ -223,9 +222,9 @@
   if (!io_task_runner_->RunsTasksOnCurrentThread()) {
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     io_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&LocalFileSyncContext::PrepareForSync, this,
-                              base::RetainedRef(file_system_context), url,
-                              sync_mode, callback));
+        FROM_HERE, base::BindOnce(&LocalFileSyncContext::PrepareForSync, this,
+                                  base::RetainedRef(file_system_context), url,
+                                  sync_mode, callback));
     return;
   }
   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
@@ -234,10 +233,11 @@
   if (syncable)
     sync_status()->StartSyncing(url);
   ui_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&LocalFileSyncContext::DidGetWritingStatusForSync,
-                            this, base::RetainedRef(file_system_context),
-                            syncable ? SYNC_STATUS_OK : SYNC_STATUS_FILE_BUSY,
-                            url, sync_mode, callback));
+      FROM_HERE,
+      base::BindOnce(&LocalFileSyncContext::DidGetWritingStatusForSync, this,
+                     base::RetainedRef(file_system_context),
+                     syncable ? SYNC_STATUS_OK : SYNC_STATUS_FILE_BUSY, url,
+                     sync_mode, callback));
 }
 
 void LocalFileSyncContext::RegisterURLForWaitingSync(
@@ -248,8 +248,8 @@
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     io_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::RegisterURLForWaitingSync,
-                   this, url, on_syncable_callback));
+        base::BindOnce(&LocalFileSyncContext::RegisterURLForWaitingSync, this,
+                       url, on_syncable_callback));
     return;
   }
   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
@@ -273,9 +273,9 @@
   if (!io_task_runner_->RunsTasksOnCurrentThread()) {
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     io_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&LocalFileSyncContext::ApplyRemoteChange, this,
-                              base::RetainedRef(file_system_context), change,
-                              local_path, url, callback));
+        FROM_HERE, base::BindOnce(&LocalFileSyncContext::ApplyRemoteChange,
+                                  this, base::RetainedRef(file_system_context),
+                                  change, local_path, url, callback));
     return;
   }
   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
@@ -410,9 +410,9 @@
           RunsTasksOnCurrentThread()) {
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     file_system_context->default_file_task_runner()->PostTask(
-        FROM_HERE, base::Bind(&LocalFileSyncContext::RecordFakeLocalChange,
-                              this, base::RetainedRef(file_system_context), url,
-                              change, callback));
+        FROM_HERE, base::BindOnce(&LocalFileSyncContext::RecordFakeLocalChange,
+                                  this, base::RetainedRef(file_system_context),
+                                  url, change, callback));
     return;
   }
 
@@ -425,8 +425,7 @@
 
   // Fire the callback on UI thread.
   ui_task_runner_->PostTask(FROM_HERE,
-                            base::Bind(callback,
-                                       SYNC_STATUS_OK));
+                            base::BindOnce(callback, SYNC_STATUS_OK));
 }
 
 void LocalFileSyncContext::GetFileMetadata(
@@ -438,8 +437,8 @@
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     io_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::GetFileMetadata, this,
-                   base::RetainedRef(file_system_context), url, callback));
+        base::BindOnce(&LocalFileSyncContext::GetFileMetadata, this,
+                       base::RetainedRef(file_system_context), url, callback));
     return;
   }
   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
@@ -464,8 +463,8 @@
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     file_system_context->default_file_task_runner()->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::HasPendingLocalChanges, this,
-                   base::RetainedRef(file_system_context), url, callback));
+        base::BindOnce(&LocalFileSyncContext::HasPendingLocalChanges, this,
+                       base::RetainedRef(file_system_context), url, callback));
     return;
   }
 
@@ -477,10 +476,8 @@
   backend->change_tracker()->GetChangesForURL(url, &changes);
 
   // Fire the callback on UI thread.
-  ui_task_runner_->PostTask(FROM_HERE,
-                            base::Bind(callback,
-                                       SYNC_STATUS_OK,
-                                       !changes.empty()));
+  ui_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(callback, SYNC_STATUS_OK, !changes.empty()));
 }
 
 void LocalFileSyncContext::PromoteDemotedChanges(
@@ -494,8 +491,9 @@
     DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     file_system_context->default_file_task_runner()->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::PromoteDemotedChanges, this, origin,
-                   base::RetainedRef(file_system_context), callback));
+        base::BindOnce(&LocalFileSyncContext::PromoteDemotedChanges, this,
+                       origin, base::RetainedRef(file_system_context),
+                       callback));
     return;
   }
 
@@ -509,9 +507,8 @@
   }
 
   io_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LocalFileSyncContext::UpdateChangesForOrigin,
-                 this, origin, callback));
+      FROM_HERE, base::BindOnce(&LocalFileSyncContext::UpdateChangesForOrigin,
+                                this, origin, callback));
 }
 
 void LocalFileSyncContext::UpdateChangesForOrigin(
@@ -595,9 +592,8 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&LocalFileSyncContext::NotifyAvailableChanges,
-                 this, origins_with_pending_changes_,
-                 completion_callbacks));
+      base::BindOnce(&LocalFileSyncContext::NotifyAvailableChanges, this,
+                     origins_with_pending_changes_, completion_callbacks));
   last_notified_changes_ = base::Time::Now();
   origins_with_pending_changes_.clear();
 }
@@ -736,8 +732,8 @@
   if (!ui_task_runner_->RunsTasksOnCurrentThread()) {
     ui_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::DidInitialize, this, source_url,
-                   base::RetainedRef(file_system_context), status));
+        base::BindOnce(&LocalFileSyncContext::DidInitialize, this, source_url,
+                       base::RetainedRef(file_system_context), status));
     return;
   }
   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
@@ -755,7 +751,7 @@
       pending_initialize_callbacks_[file_system_context];
   for (StatusCallbackQueue::iterator iter = callback_queue.begin();
        iter != callback_queue.end(); ++iter) {
-    ui_task_runner_->PostTask(FROM_HERE, base::Bind(*iter, status));
+    ui_task_runner_->PostTask(FROM_HERE, base::BindOnce(*iter, status));
   }
   pending_initialize_callbacks_.erase(file_system_context);
 }
@@ -841,8 +837,8 @@
       return;
     file_system_context->default_file_task_runner()->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::PromoteDemotedChangesForURL, this,
-                   base::RetainedRef(file_system_context), url));
+        base::BindOnce(&LocalFileSyncContext::PromoteDemotedChangesForURL, this,
+                       base::RetainedRef(file_system_context), url));
     return;
   }
 
@@ -864,9 +860,9 @@
       return;
     file_system_context->default_file_task_runner()->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::PromoteDemotedChangesForURLs, this,
-                   base::RetainedRef(file_system_context),
-                   base::Passed(&urls)));
+        base::BindOnce(&LocalFileSyncContext::PromoteDemotedChangesForURLs,
+                       this, base::RetainedRef(file_system_context),
+                       base::Passed(&urls)));
     return;
   }
 
@@ -892,9 +888,10 @@
       return;
     }
     file_system_context->default_file_task_runner()->PostTask(
-        FROM_HERE, base::Bind(&LocalFileSyncContext::DidGetWritingStatusForSync,
-                              this, base::RetainedRef(file_system_context),
-                              status, url, sync_mode, callback));
+        FROM_HERE,
+        base::BindOnce(&LocalFileSyncContext::DidGetWritingStatusForSync, this,
+                       base::RetainedRef(file_system_context), status, url,
+                       sync_mode, callback));
     return;
   }
 
@@ -964,13 +961,13 @@
     // the same URL)
     io_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&LocalFileSyncContext::ClearSyncFlagOnIOThread,
-                   this, url, true /* for_snapshot_sync */));
+        base::BindOnce(&LocalFileSyncContext::ClearSyncFlagOnIOThread, this,
+                       url, true /* for_snapshot_sync */));
   }
 
   ui_task_runner_->PostTask(FROM_HERE,
-                            base::Bind(callback, status, sync_file_info,
-                                       base::Passed(&snapshot)));
+                            base::BindOnce(callback, status, sync_file_info,
+                                           base::Passed(&snapshot)));
 }
 
 void LocalFileSyncContext::ClearSyncFlagOnIOThread(
@@ -1010,7 +1007,7 @@
   root_delete_helper_.reset();
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(callback_on_ui, FileErrorToSyncStatusCode(file_error)));
+      base::BindOnce(callback_on_ui, FileErrorToSyncStatusCode(file_error)));
 }
 
 void LocalFileSyncContext::DidGetFileMetadata(
@@ -1026,8 +1023,8 @@
     metadata.last_modified = file_info.last_modified;
   }
   ui_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(callback, FileErrorToSyncStatusCode(file_error), metadata));
+      FROM_HERE, base::BindOnce(callback, FileErrorToSyncStatusCode(file_error),
+                                metadata));
 }
 
 base::TimeDelta LocalFileSyncContext::NotifyChangesDuration() {
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
index 1fc9024..1edaeab8 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
@@ -184,8 +184,8 @@
       ASSERT_TRUE(ui_task_runner_->RunsTasksOnCurrentThread());
       io_task_runner_->PostTask(
           FROM_HERE,
-          base::Bind(&LocalFileSyncContextTest::StartModifyFileOnIOThread,
-                     base::Unretained(this), file_system, url));
+          base::BindOnce(&LocalFileSyncContextTest::StartModifyFileOnIOThread,
+                         base::Unretained(this), file_system, url));
       return;
     }
     ASSERT_TRUE(io_task_runner_->RunsTasksOnCurrentThread());
@@ -205,9 +205,8 @@
     if (!ui_task_runner_->RunsTasksOnCurrentThread()) {
       ASSERT_TRUE(io_task_runner_->RunsTasksOnCurrentThread());
       ui_task_runner_->PostTask(
-          FROM_HERE,
-          base::Bind(&LocalFileSyncContextTest::DidModifyFile,
-                     base::Unretained(this), error));
+          FROM_HERE, base::BindOnce(&LocalFileSyncContextTest::DidModifyFile,
+                                    base::Unretained(this), error));
       return;
     }
     ASSERT_TRUE(ui_task_runner_->RunsTasksOnCurrentThread());
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service.cc b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
index d1478919..9b96290 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
@@ -187,7 +187,7 @@
   if (!base::ContainsKey(origin_to_contexts_, url.origin())) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(callback, SYNC_FILE_ERROR_INVALID_URL, false));
+        base::BindOnce(callback, SYNC_FILE_ERROR_INVALID_URL, false));
     return;
   }
   sync_context_->HasPendingLocalChanges(
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
index 0efab188..e4b5ad43 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
@@ -91,13 +91,13 @@
 }
 
 ACTION_P(MockStatusCallback, status) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(arg4, status));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                base::BindOnce(arg4, status));
 }
 
 ACTION_P2(MockStatusCallbackAndRecordChange, status, changes) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(arg4, status));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                base::BindOnce(arg4, status));
   changes->push_back(arg0);
 }
 
diff --git a/chrome/browser/sync_file_system/local/root_delete_helper.cc b/chrome/browser/sync_file_system/local/root_delete_helper.cc
index ff36cef..64d9bd6 100644
--- a/chrome/browser/sync_file_system/local/root_delete_helper.cc
+++ b/chrome/browser/sync_file_system/local/root_delete_helper.cc
@@ -76,10 +76,11 @@
   // TODO(kinuko): This should be probably automatically handled in
   // DeleteFileSystem via QuotaUtil::DeleteOriginDataOnFileThread.
   file_system_context_->default_file_task_runner()->PostTaskAndReply(
-      FROM_HERE, base::Bind(&ResetFileChangeTracker,
-                            base::RetainedRef(file_system_context_), url_),
-      base::Bind(&RootDeleteHelper::DidResetFileChangeTracker,
-                 weak_factory_.GetWeakPtr()));
+      FROM_HERE,
+      base::BindOnce(&ResetFileChangeTracker,
+                     base::RetainedRef(file_system_context_), url_),
+      base::BindOnce(&RootDeleteHelper::DidResetFileChangeTracker,
+                     weak_factory_.GetWeakPtr()));
 }
 
 void RootDeleteHelper::DidResetFileChangeTracker() {
diff --git a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
index 3499e351..a66562e 100644
--- a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
+++ b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
@@ -272,8 +272,8 @@
     // It is safe to pass Unretained(this) (see comments in OpenFileSystem()).
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&SyncFileSystemBackend::InitializeSyncFileSystemService,
-                   base::Unretained(this), origin_url, callback));
+        base::BindOnce(&SyncFileSystemBackend::InitializeSyncFileSystemService,
+                       base::Unretained(this), origin_url, callback));
     return;
   }
 
@@ -302,9 +302,10 @@
     // It is safe to pass Unretained(this) since |context| owns it.
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService,
-                   base::Unretained(this), base::RetainedRef(context),
-                   origin_url, type, mode, callback, status));
+        base::BindOnce(
+            &SyncFileSystemBackend::DidInitializeSyncFileSystemService,
+            base::Unretained(this), base::RetainedRef(context), origin_url,
+            type, mode, callback, status));
     return;
   }
 
diff --git a/chrome/browser/sync_file_system/mock_local_change_processor.cc b/chrome/browser/sync_file_system/mock_local_change_processor.cc
index fb8cc78..f1be848 100644
--- a/chrome/browser/sync_file_system/mock_local_change_processor.cc
+++ b/chrome/browser/sync_file_system/mock_local_change_processor.cc
@@ -34,7 +34,7 @@
     const storage::FileSystemURL& url,
     const SyncStatusCallback& callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+      FROM_HERE, base::BindOnce(callback, SYNC_STATUS_OK));
 }
 
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc b/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc
index 35cea61..d76a25b 100644
--- a/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/mock_remote_file_sync_service.cc
@@ -93,8 +93,7 @@
     const GURL& origin,
     const SyncStatusCallback& callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, SYNC_STATUS_OK));
+      FROM_HERE, base::BindOnce(callback, SYNC_STATUS_OK));
 }
 
 void MockRemoteFileSyncService::DeleteOriginDirectoryStub(
@@ -102,16 +101,14 @@
     UninstallFlag flag,
     const SyncStatusCallback& callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(callback, SYNC_STATUS_OK));
+      FROM_HERE, base::BindOnce(callback, SYNC_STATUS_OK));
 }
 
 void MockRemoteFileSyncService::ProcessRemoteChangeStub(
     const SyncFileCallback& callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(
-          callback, SYNC_STATUS_NO_CHANGE_TO_SYNC, storage::FileSystemURL()));
+      FROM_HERE, base::BindOnce(callback, SYNC_STATUS_NO_CHANGE_TO_SYNC,
+                                storage::FileSystemURL()));
 }
 
 RemoteServiceState MockRemoteFileSyncService::GetCurrentStateStub() const {
diff --git a/chrome/browser/sync_file_system/sync_file_system_service.cc b/chrome/browser/sync_file_system/sync_file_system_service.cc
index 235c0dd..1852210 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service.cc
@@ -334,10 +334,8 @@
   // It's possible to get an invalid FileEntry.
   if (!url.is_valid()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::Bind(callback,
-                   SYNC_FILE_ERROR_INVALID_URL,
-                   SYNC_FILE_STATUS_UNKNOWN));
+        FROM_HERE, base::BindOnce(callback, SYNC_FILE_ERROR_INVALID_URL,
+                                  SYNC_FILE_STATUS_UNKNOWN));
     return;
   }
 
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
index 8475219..ec053959 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
@@ -104,7 +104,7 @@
   mock_remote_service->NotifyRemoteServiceStateUpdated(
       service_state, "Test event.");
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(arg1, operation_status));
+      FROM_HERE, base::BindOnce(arg1, operation_status));
 }
 
 ACTION_P(RecordState, states) {
@@ -112,13 +112,13 @@
 }
 
 ACTION_P(MockStatusCallback, status) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(arg4, status));
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                base::BindOnce(arg4, status));
 }
 
 ACTION_P2(MockSyncFileCallback, status, url) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(arg0, status, url));
+      FROM_HERE, base::BindOnce(arg0, status, url));
 }
 
 ACTION(InvokeCompletionClosure) {
@@ -424,12 +424,11 @@
   // Start a local operation on the same file (to make it BUSY).
   base::RunLoop verify_file_error_run_loop;
   BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&CannedSyncableFileSystem::DoCreateFile,
-                 base::Unretained(file_system_.get()),
-                 kFile, base::Bind(&VerifyFileError,
-                                   verify_file_error_run_loop.QuitClosure())));
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&CannedSyncableFileSystem::DoCreateFile,
+                     base::Unretained(file_system_.get()), kFile,
+                     base::Bind(&VerifyFileError,
+                                verify_file_error_run_loop.QuitClosure())));
 
   run_loop.Run();
 
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
index 1818c11..462a087 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -15,11 +15,9 @@
 #include "chrome/common/extensions/chrome_extension_messages.h"
 #include "content/public/browser/ax_event_notification_details.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/render_frame_host.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_enums.h"
 #include "ui/accessibility/ax_tree_id_registry.h"
-#include "ui/accessibility/platform/aura_window_properties.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/views/accessibility/ax_aura_obj_wrapper.h"
@@ -27,7 +25,6 @@
 #include "ui/views/widget/widget.h"
 
 #if defined(OS_CHROMEOS)
-#include "ash/shell.h"           // nogncheck
 #include "ash/wm/window_util.h"  // nogncheck
 #endif
 
@@ -84,16 +81,10 @@
   SendEvent(context, obj, ui::AX_EVENT_ALERT);
 }
 
-void AutomationManagerAura::PerformAction(const ui::AXActionData& data) {
+void AutomationManagerAura::PerformAction(
+    const ui::AXActionData& data) {
   CHECK(enabled_);
 
-  // Unlike all of the other actions, a hit test requires determining the
-  // node to perform the action on first.
-  if (data.action == ui::AX_ACTION_HIT_TEST) {
-    PerformHitTest(data);
-    return;
-  }
-
   current_tree_->HandleAccessibleAction(data);
 }
 
@@ -170,60 +161,3 @@
               pending_events_copy[i].second);
   }
 }
-
-void AutomationManagerAura::PerformHitTest(
-    const ui::AXActionData& original_action) {
-#if defined(OS_CHROMEOS)
-  ui::AXActionData action = original_action;
-  aura::Window* root_window = ash::Shell::Get()->GetPrimaryRootWindow();
-  if (!root_window)
-    return;
-
-  // Determine which aura Window is associated with the target point.
-  aura::Window* window =
-      root_window->GetEventHandlerForPoint(action.target_point);
-  if (!window)
-    return;
-
-  // Convert point to local coordinates of the hit window.
-  aura::Window::ConvertPointToTarget(root_window, window, &action.target_point);
-
-  // If the window has a child AX tree ID, forward the action to the
-  // associated AXHostDelegate or RenderFrameHost.
-  ui::AXTreeIDRegistry::AXTreeID child_ax_tree_id =
-      window->GetProperty(ui::kChildAXTreeID);
-  if (child_ax_tree_id != ui::AXTreeIDRegistry::kNoAXTreeID) {
-    ui::AXTreeIDRegistry* registry = ui::AXTreeIDRegistry::GetInstance();
-    ui::AXHostDelegate* delegate = registry->GetHostDelegate(child_ax_tree_id);
-    if (delegate) {
-      delegate->PerformAction(action);
-      return;
-    }
-
-    content::RenderFrameHost* rfh =
-        content::RenderFrameHost::FromAXTreeID(child_ax_tree_id);
-    if (rfh)
-      rfh->AccessibilityPerformAction(action);
-    return;
-  }
-
-  // If the window doesn't have a child tree ID, try to fire the event
-  // on a View.
-  views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
-  if (widget) {
-    views::View* root_view = widget->GetRootView();
-    views::View* hit_view =
-        root_view->GetEventHandlerForPoint(action.target_point);
-    if (hit_view) {
-      hit_view->NotifyAccessibilityEvent(action.hit_test_event_to_fire, true);
-      return;
-    }
-  }
-
-  // Otherwise, fire the event directly on the Window.
-  views::AXAuraObjWrapper* window_wrapper =
-      views::AXAuraObjCache::GetInstance()->GetOrCreate(window);
-  if (window_wrapper)
-    SendEvent(nullptr, window_wrapper, action.hit_test_event_to_fire);
-#endif
-}
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.h b/chrome/browser/ui/aura/accessibility/automation_manager_aura.h
index ecb3c60..1d1baef 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.h
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.h
@@ -78,8 +78,6 @@
                  views::AXAuraObjWrapper* aura_obj,
                  ui::AXEvent event_type);
 
-  void PerformHitTest(const ui::AXActionData& data);
-
   // Whether automation support for views is enabled.
   bool enabled_;
 
diff --git a/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc b/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
index 3617800..e31d412 100644
--- a/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
+++ b/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
@@ -103,8 +103,8 @@
 void WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(
     const std::string& page_url, bool is_rtl) {
   ui_test_utils::NavigateToURL(browser(), GURL(page_url));
-  ASSERT_TRUE(RunJavascriptTest("runBidiChecker", new base::Value(page_url),
-                                new base::Value(is_rtl)));
+  ASSERT_TRUE(RunJavascriptTest("runBidiChecker", base::Value(page_url),
+                                base::Value(is_rtl)));
 }
 
 void DISABLED_WebUIBidiCheckerBrowserTestLTR::RunBidiCheckerOnPage(
diff --git a/chrome/browser/ui/webui/inspect_ui_browsertest.cc b/chrome/browser/ui/webui/inspect_ui_browsertest.cc
index 2d9d4064..8be94d2 100644
--- a/chrome/browser/ui/webui/inspect_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/inspect_ui_browsertest.cc
@@ -39,9 +39,9 @@
 IN_PROC_BROWSER_TEST_F(InspectUITest, InspectUIPage) {
   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIInspectURL));
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testTargetListed", new base::Value("#pages"),
-      new base::Value("populateWebContentsTargets"),
-      new base::Value(chrome::kChromeUIInspectURL)));
+      "testTargetListed", base::Value("#pages"),
+      base::Value("populateWebContentsTargets"),
+      base::Value(chrome::kChromeUIInspectURL)));
 }
 
 IN_PROC_BROWSER_TEST_F(InspectUITest, SharedWorker) {
@@ -55,14 +55,13 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testTargetListed", new base::Value("#workers"),
-      new base::Value("populateWorkerTargets"),
-      new base::Value(kSharedWorkerJs)));
+      "testTargetListed", base::Value("#workers"),
+      base::Value("populateWorkerTargets"), base::Value(kSharedWorkerJs)));
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testTargetListed", new base::Value("#pages"),
-      new base::Value("populateWebContentsTargets"),
-      new base::Value(kSharedWorkerTestPage)));
+      "testTargetListed", base::Value("#pages"),
+      base::Value("populateWebContentsTargets"),
+      base::Value(kSharedWorkerTestPage)));
 }
 
 // Flaky due to failure to bind a hardcoded port. crbug.com/566057
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 393ef9d..0410f286 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -272,52 +272,38 @@
 }
 
 void NTPResourceCache::CreateNewTabIncognitoHTML() {
-  base::DictionaryValue localized_strings;
-  localized_strings.SetString("title",
-      l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
-  int new_tab_description_ids = IDS_NEW_TAB_OTR_DESCRIPTION;
-  int new_tab_heading_ids = IDS_NEW_TAB_OTR_HEADING;
-  int new_tab_link_ids = IDS_NEW_TAB_OTR_LEARN_MORE_LINK;
-  int new_tab_warning_ids = IDS_NEW_TAB_OTR_MESSAGE_WARNING;
-  int new_tab_html_idr = IDR_INCOGNITO_TAB_HTML;
-  const char* new_tab_link = kLearnMoreIncognitoUrl;
-
-  if (profile_->IsGuestSession()) {
-    localized_strings.SetString("guestTabDescription",
-        l10n_util::GetStringUTF16(new_tab_description_ids));
-    localized_strings.SetString("guestTabHeading",
-        l10n_util::GetStringUTF16(new_tab_heading_ids));
-  } else {
-    localized_strings.SetString("incognitoTabDescription",
-        l10n_util::GetStringUTF16(new_tab_description_ids));
-    localized_strings.SetString("incognitoTabHeading",
-        l10n_util::GetStringUTF16(new_tab_heading_ids));
-    localized_strings.SetString("incognitoTabWarning",
-        l10n_util::GetStringUTF16(new_tab_warning_ids));
-  }
-
-  localized_strings.SetString("learnMore",
-      l10n_util::GetStringUTF16(new_tab_link_ids));
-  localized_strings.SetString("learnMoreLink", new_tab_link);
-
-  bool bookmark_bar_attached =
-      profile_->GetPrefs()->GetBoolean(bookmarks::prefs::kShowBookmarkBar);
-  localized_strings.SetBoolean("bookmarkbarattached", bookmark_bar_attached);
+  ui::TemplateReplacements replacements;
+  // Note: there's specific rules in CSS that look for this attribute's content
+  // being equal to "true" as a string.
+  replacements["bookmarkbarattached"] =
+      profile_->GetPrefs()->GetBoolean(bookmarks::prefs::kShowBookmarkBar)
+          ? "true"
+          : "false";
+  replacements["incognitoTabDescription"] =
+      l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_DESCRIPTION);
+  replacements["incognitoTabHeading"] =
+      l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_HEADING);
+  replacements["incognitoTabWarning"] =
+      l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_MESSAGE_WARNING);
+  replacements["learnMore"] =
+      l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_LEARN_MORE_LINK);
+  replacements["learnMoreLink"] = kLearnMoreIncognitoUrl;
+  replacements["title"] = l10n_util::GetStringUTF8(IDS_NEW_TAB_TITLE);
 
   const ui::ThemeProvider& tp =
       ThemeService::GetThemeProviderForProfile(profile_);
-  localized_strings.SetBoolean("hasCustomBackground",
-                               tp.HasCustomImage(IDR_THEME_NTP_BACKGROUND));
+  replacements["hasCustomBackground"] =
+      tp.HasCustomImage(IDR_THEME_NTP_BACKGROUND) ? "true" : "false";
 
   const std::string& app_locale = g_browser_process->GetApplicationLocale();
-  webui::SetLoadTimeDataDefaults(app_locale, &localized_strings);
+  webui::SetLoadTimeDataDefaults(app_locale, &replacements);
 
   static const base::StringPiece incognito_tab_html(
       ResourceBundle::GetSharedInstance().GetRawDataResource(
-          new_tab_html_idr));
+          IDR_INCOGNITO_TAB_HTML));
 
-  std::string full_html = webui::GetI18nTemplateHtml(
-      incognito_tab_html, &localized_strings);
+  std::string full_html =
+      ui::ReplaceTemplateExpressions(incognito_tab_html, replacements);
 
   new_tab_incognito_html_ = base::RefCountedString::TakeString(&full_html);
 }
@@ -391,8 +377,9 @@
   // profile is not the default.
   PrefService* prefs = profile_->GetPrefs();
   base::DictionaryValue load_time_data;
-  load_time_data.SetBoolean("bookmarkbarattached",
-      prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
+  load_time_data.SetString(
+      "bookmarkbarattached",
+      prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar) ? "true" : "false");
   load_time_data.SetBoolean("showAppLauncherPromo",
       ShouldShowAppLauncherPromo());
   load_time_data.SetString("title",
diff --git a/chrome/browser/ui/webui/theme_handler.cc b/chrome/browser/ui/webui/theme_handler.cc
index 71e825c..b1aaf4c 100644
--- a/chrome/browser/ui/webui/theme_handler.cc
+++ b/chrome/browser/ui/webui/theme_handler.cc
@@ -41,6 +41,7 @@
   InitializeCSSCaches();
   bool has_custom_bg = ThemeService::GetThemeProviderForProfile(GetProfile())
                            .HasCustomImage(IDR_THEME_NTP_BACKGROUND);
+  // TODO(dbeam): why does this need to be a dictionary?
   base::DictionaryValue dictionary;
   dictionary.SetBoolean("hasCustomBackground", has_custom_bg);
   web_ui()->CallJavascriptFunctionUnsafe("ntp.themeChanged", dictionary);
diff --git a/chrome/browser/ui/webui/webui_webview_browsertest.cc b/chrome/browser/ui/webui/webui_webview_browsertest.cc
index d260748..636e059a 100644
--- a/chrome/browser/ui/webui/webui_webview_browsertest.cc
+++ b/chrome/browser/ui/webui/webui_webview_browsertest.cc
@@ -140,15 +140,14 @@
   ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL());
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testDisplayNone", new base::Value(GetTestUrl("empty.html").spec())));
+      "testDisplayNone", base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, ExecuteScriptCode) {
   ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL());
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testExecuteScriptCode",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      "testExecuteScriptCode", base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, ExecuteScriptCodeFromFile) {
@@ -156,15 +155,14 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testExecuteScriptCodeFromFile",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddContentScript) {
   ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL());
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testAddContentScript",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      "testAddContentScript", base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddMultiContentScripts) {
@@ -172,7 +170,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testAddMultiContentScripts",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(
@@ -182,7 +180,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testAddContentScriptWithSameNameShouldOverwriteTheExistingOne",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(
@@ -192,7 +190,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testAddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddAndRemoveContentScripts) {
@@ -200,7 +198,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testAddAndRemoveContentScripts",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest,
@@ -209,7 +207,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testAddContentScriptsWithNewWindowAPI",
-      new base::Value(GetTestUrl("guest_from_opener.html").spec())));
+      base::Value(GetTestUrl("guest_from_opener.html").spec())));
 }
 
 // https://crbug.com/665512.
@@ -220,7 +218,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testContentScriptIsInjectedAfterTerminateAndReloadWebView",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 // TODO(crbug.com/662673) Flaky on CrOS trybots.
@@ -237,7 +235,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testContentScriptExistsAsLongAsWebViewTagExists",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddContentScriptWithCode) {
@@ -245,7 +243,7 @@
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
       "testAddContentScriptWithCode",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      base::Value(GetTestUrl("empty.html").spec())));
 }
 
 #if defined(OS_CHROMEOS)
@@ -259,8 +257,7 @@
       incognito_browser->tab_strip_model()->GetActiveWebContents()->GetWebUI());
 
   ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
-      "testAddContentScript",
-      new base::Value(GetTestUrl("empty.html").spec())));
+      "testAddContentScript", base::Value(GetTestUrl("empty.html").spec())));
 }
 #endif
 
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index d65c807..3949411 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -311,10 +311,14 @@
 const base::Feature kOptInImeMenu{"OptInImeMenu",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enables or disables PIN quick unlock.
+// Enables or disables pin quick unlock.
 const base::Feature kQuickUnlockPin{"QuickUnlockPin",
                                     base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables pin on the login screen.
+const base::Feature kQuickUnlockPinSignin{"QuickUnlockPinSignin",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables or disables fingerprint quick unlock.
 const base::Feature kQuickUnlockFingerprint{"QuickUnlockFingerprint",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 0196603..7c5f8c7 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -177,6 +177,8 @@
 
 extern const base::Feature kQuickUnlockPin;
 
+extern const base::Feature kQuickUnlockPinSignin;
+
 extern const base::Feature kQuickUnlockFingerprint;
 
 extern const base::Feature kEHVInputOnImeMenu;
diff --git a/chrome/renderer/autofill/form_classifier_browsertest.cc b/chrome/renderer/autofill/form_classifier_browsertest.cc
index 38f45631..2cccb25 100644
--- a/chrome/renderer/autofill/form_classifier_browsertest.cc
+++ b/chrome/renderer/autofill/form_classifier_browsertest.cc
@@ -11,7 +11,7 @@
 #include "third_party/WebKit/public/web/WebFormElement.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 namespace autofill {
 
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 e8e3a1a..48b39e95 100644
--- a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
@@ -29,7 +29,7 @@
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
 #include "third_party/WebKit/public/web/WebScriptSource.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 using ::testing::DoAll;
 using ::testing::Invoke;
diff --git a/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc b/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
index 27792e9..e5dc97b 100644
--- a/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
+++ b/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
@@ -16,7 +16,7 @@
 #include "net/base/escape.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 namespace {
 
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index e747858..e05a9f9 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -9,6 +9,8 @@
   java_files = [
     "javatests/src/org/chromium/chrome/test/BottomSheetTestCaseBase.java",
     "javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java",
+    "javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java",
+    "javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java",
     "javatests/src/org/chromium/chrome/test/ChromeInstrumentationTestRunner.java",
     "javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java",
     "javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestBase.java",
@@ -83,6 +85,7 @@
     "//net/android:net_java",
     "//net/android:net_java_test_support",
     "//testing/android/reporter:reporter_java",
+    "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_transition_java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
index 725048b..21259b8 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
@@ -4,84 +4,32 @@
 
 package org.chromium.chrome.test;
 
-import android.app.Activity;
 import android.app.Instrumentation;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.net.Uri;
 import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Browser;
-import android.test.InstrumentationTestRunner;
-import android.text.TextUtils;
 import android.view.View;
-import android.widget.ListView;
 
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.ApplicationStatus.ActivityStateListener;
-import org.chromium.base.Log;
-import org.chromium.base.PerfTraceEvent;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.BaseActivityInstrumentationTestCase;
-import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.PerfTest;
 import org.chromium.base.test.util.parameter.BaseParameter;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.DeferredStartupHandler;
-import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.infobar.InfoBar;
-import org.chromium.chrome.browser.ntp.NewTabPage;
-import org.chromium.chrome.browser.omnibox.AutocompleteController;
-import org.chromium.chrome.browser.omnibox.LocationBarLayout;
-import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxResultItem;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestion;
-import org.chromium.chrome.browser.omnibox.UrlBar;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.test.ChromeActivityTestCommon.ChromeTestCommonCallback;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.chrome.test.util.MenuUtils;
-import org.chromium.chrome.test.util.NewTabPageTestUtils;
 import org.chromium.chrome.test.util.parameters.AddFakeAccountToAppParameter;
 import org.chromium.chrome.test.util.parameters.AddFakeAccountToOsParameter;
 import org.chromium.chrome.test.util.parameters.AddGoogleAccountToOsParameter;
-import org.chromium.content.browser.test.util.Criteria;
-import org.chromium.content.browser.test.util.CriteriaHelper;
-import org.chromium.content.browser.test.util.JavaScriptUtils;
-import org.chromium.content.browser.test.util.RenderProcessLimit;
 import org.chromium.content.browser.test.util.TestTouchUtils;
 import org.chromium.content.browser.test.util.TouchCommon;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.ui.base.PageTransition;
 
-import java.io.File;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Method;
-import java.util.Calendar;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Base class for all Chrome instrumentation tests.
@@ -89,72 +37,28 @@
  * See ChromeTabbedActivityTestBase.java for example.
  * @param <T> A {@link ChromeActivity} class
  */
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         // Preconnect causes issues with the single-threaded Java test server.
         "--disable-features=NetworkPrediction"})
 public abstract class ChromeActivityTestCaseBase<T extends ChromeActivity>
-        extends BaseActivityInstrumentationTestCase<T> {
-
-    private static final String TAG = "cr_CATestCaseBase";
-
-    // The number of ms to wait for the rendering activity to be started.
-    protected static final int ACTIVITY_START_TIMEOUT_MS = 1000;
-
-    private static final String PERF_ANNOTATION_FORMAT = "**PERFANNOTATION(%s):";
-
-    private static final String MEMORY_TRACE_GRAPH_SUFFIX = " - browser PSS";
-
-    private static final String PERF_OUTPUT_FILE = "PerfTestData.txt";
-
-    private static final long OMNIBOX_FIND_SUGGESTION_TIMEOUT_MS = 10 * 1000;
-
-    protected boolean mSkipClearAppData;
-    private Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler;
-    private Class<T> mChromeActivityClass;
+        extends BaseActivityInstrumentationTestCase<T> implements ChromeTestCommonCallback<T> {
+    private final ChromeActivityTestCommon<T> mTestCommon;
 
     public ChromeActivityTestCaseBase(Class<T> activityClass) {
         super(activityClass);
-        mChromeActivityClass = activityClass;
-    }
-
-    private class ChromeUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
-        @Override
-        public void uncaughtException(Thread t, Throwable e) {
-            String stackTrace = android.util.Log.getStackTraceString(e);
-            if (e.getClass().getName().endsWith("StrictModeViolation")) {
-                stackTrace += "\nSearch logcat for \"StrictMode policy violation\" for full stack.";
-            }
-            Bundle resultsBundle = new Bundle();
-            resultsBundle.putString(InstrumentationTestRunner.REPORT_KEY_NAME_CLASS,
-                    getClass().getName());
-            resultsBundle.putString(InstrumentationTestRunner.REPORT_KEY_NAME_TEST, getName());
-            resultsBundle.putString(InstrumentationTestRunner.REPORT_KEY_STACK, stackTrace);
-            getInstrumentation().sendStatus(-1, resultsBundle);
-            mDefaultUncaughtExceptionHandler.uncaughtException(t, e);
-        }
+        mTestCommon = new ChromeActivityTestCommon<>(activityClass, this);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
-        Thread.setDefaultUncaughtExceptionHandler(new ChromeUncaughtExceptionHandler());
-        ApplicationTestUtils.setUp(getInstrumentation().getTargetContext(), !mSkipClearAppData);
-        setActivityInitialTouchMode(false);
-
-        // Preload Calendar so that it does not trigger ReadFromDisk Strict mode violations if
-        // called on the UI Thread. See https://crbug.com/705477 and https://crbug.com/577185
-        Calendar.getInstance();
-
+        mTestCommon.setUp();
         startMainActivity();
     }
 
     @Override
     protected void tearDown() throws Exception {
-        ApplicationTestUtils.tearDown(getInstrumentation().getTargetContext());
-        Thread.setDefaultUncaughtExceptionHandler(mDefaultUncaughtExceptionHandler);
-        super.tearDown();
+        mTestCommon.tearDown();
     }
 
     /**
@@ -165,17 +69,18 @@
     public abstract void startMainActivity() throws InterruptedException;
 
     /**
+     * Return the timeout limit for Chrome activty start in tests
+     */
+    protected static int getActivityStartTimeoutMs() {
+        return ChromeActivityTestCommon.ACTIVITY_START_TIMEOUT_MS;
+    }
+
+    /**
      * Matches testString against baseString.
      * Returns 0 if there is no match, 1 if an exact match and 2 if a fuzzy match.
      */
     protected static int matchUrl(String baseString, String testString) {
-        if (baseString.equals(testString)) {
-            return 1;
-        }
-        if (baseString.contains(testString)) {
-            return 2;
-        }
-        return 0;
+        return ChromeActivityTestCommon.matchUrl(baseString, testString);
     }
 
     /**
@@ -186,42 +91,12 @@
      * and the activity's main looper has become idle.
      */
     protected void startActivityCompletely(Intent intent) {
-        final CallbackHelper activityCallback = new CallbackHelper();
-        final AtomicReference<T> activityRef = new AtomicReference<>();
-        ActivityStateListener stateListener = new ActivityStateListener() {
-            @SuppressWarnings("unchecked")
-            @Override
-            public void onActivityStateChange(Activity activity, int newState) {
-                if (newState == ActivityState.RESUMED) {
-                    if (!mChromeActivityClass.isAssignableFrom(activity.getClass())) {
-                        return;
-                    }
-
-                    activityRef.set((T) activity);
-                    activityCallback.notifyCalled();
-                    ApplicationStatus.unregisterActivityStateListener(this);
-                }
-            }
-        };
-        ApplicationStatus.registerStateListenerForAllActivities(stateListener);
-
-        try {
-            getInstrumentation().startActivitySync(intent);
-            activityCallback.waitForCallback("Activity did not start as expected", 0);
-            T activity = activityRef.get();
-            assertNotNull("Activity reference is null.", activity);
-            setActivity(activity);
-            Log.d(TAG, "startActivityCompletely <<");
-        } catch (InterruptedException | TimeoutException e) {
-            throw new RuntimeException(e);
-        } finally {
-            ApplicationStatus.unregisterActivityStateListener(stateListener);
-        }
+        mTestCommon.startActivityCompletely(intent);
     }
 
     /** Convenience function for {@link ApplicationTestUtils#clearAppData(Context)}. */
     protected void clearAppData() {
-        ApplicationTestUtils.clearAppData(getInstrumentation().getTargetContext());
+        mTestCommon.clearAppData();
     }
 
     /**
@@ -229,12 +104,7 @@
      * etc. Network predictions are enabled by default.
      */
     protected void setNetworkPredictionEnabled(final boolean enabled) {
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                PrefServiceBridge.getInstance().setNetworkPredictionEnabled(enabled);
-            }
-        });
+        mTestCommon.setNetworkPredictionEnabled(enabled);
     }
 
     /**
@@ -245,7 +115,7 @@
      * @param downTime (in ms)
      * @see TestTouchUtils
      */
-    protected void dragStart(float x, float y, long downTime) {
+    public void dragStart(float x, float y, long downTime) {
         TouchCommon.dragStart(getActivity(), x, y, downTime);
     }
 
@@ -261,8 +131,8 @@
      * @param downTime (in ms)
      * @see TestTouchUtils
      */
-    protected void dragTo(float fromX, float toX, float fromY,
-            float toY, int stepCount, long downTime) {
+    public void dragTo(
+            float fromX, float toX, float fromY, float toY, int stepCount, long downTime) {
         TouchCommon.dragTo(getActivity(), fromX, toX, fromY, toY, stepCount, downTime);
     }
 
@@ -275,7 +145,7 @@
      * @param downTime (in ms)
      * @see TestTouchUtils
      */
-    protected void dragEnd(float x, float y, long downTime) {
+    public void dragEnd(float x, float y, long downTime) {
         TouchCommon.dragEnd(getActivity(), x, y, downTime);
     }
 
@@ -302,15 +172,7 @@
      * @param timeout how long to wait for tasks to complete
      */
     public void waitForAsyncTasks(long timeout) throws InterruptedException {
-        final Semaphore s = new Semaphore(0);
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... arg0) {
-                s.release();
-                return null;
-            }
-        }.execute();
-        assertTrue(s.tryAcquire(timeout, TimeUnit.MILLISECONDS));
+        mTestCommon.waitForAsyncTasks(timeout);
     }
 
     /**
@@ -321,10 +183,9 @@
      * @return FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the page has been
      *         prerendered. DEFAULT_PAGE_LOAD if it had not.
      */
-    public int loadUrl(final String url, long secondsToWait)
+    public int loadUrl(String url, long secondsToWait)
             throws IllegalArgumentException, InterruptedException {
-        return loadUrlInTab(url, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR,
-                getActivity().getActivityTab(), secondsToWait);
+        return mTestCommon.loadUrl(url, secondsToWait);
     }
 
     /**
@@ -334,9 +195,8 @@
      * @return FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the page has been
      *         prerendered. DEFAULT_PAGE_LOAD if it had not.
      */
-    public int loadUrl(final String url) throws IllegalArgumentException, InterruptedException {
-        return loadUrlInTab(url, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR,
-                getActivity().getActivityTab());
+    public int loadUrl(String url) throws IllegalArgumentException, InterruptedException {
+        return mTestCommon.loadUrl(url);
     }
 
     /**
@@ -349,25 +209,9 @@
      * @return               FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the
      *                       page has been prerendered. DEFAULT_PAGE_LOAD if it had not.
      */
-    public int loadUrlInTab(final String url, final int pageTransition, final Tab tab,
-            long secondsToWait) throws InterruptedException {
-        assertNotNull("Cannot load the url in a null tab", tab);
-        final AtomicInteger result = new AtomicInteger();
-
-        ChromeTabUtils.waitForTabPageLoaded(tab, new Runnable() {
-            @Override
-            public void run() {
-                ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-                    @Override
-                    public void run() {
-                        result.set(tab.loadUrl(
-                                new LoadUrlParams(url, pageTransition)));
-                    }
-                });
-            }
-        }, secondsToWait);
-        getInstrumentation().waitForIdleSync();
-        return result.get();
+    public int loadUrlInTab(String url, int pageTransition, Tab tab, long secondsToWait)
+            throws InterruptedException {
+        return mTestCommon.loadUrlInTab(url, pageTransition, tab, secondsToWait);
     }
 
     /**
@@ -379,17 +223,16 @@
      * @return               FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the
      *                       page has been prerendered. DEFAULT_PAGE_LOAD if it had not.
      */
-    public int loadUrlInTab(final String url, final int pageTransition, final Tab tab)
-            throws InterruptedException {
-        return loadUrlInTab(url, pageTransition, tab, CallbackHelper.WAIT_TIMEOUT_SECONDS);
+    public int loadUrlInTab(String url, int pageTransition, Tab tab) throws InterruptedException {
+        return mTestCommon.loadUrlInTab(url, pageTransition, tab);
     }
 
     /**
      * Load a url in a new tab. The {@link Tab} will pretend to be created from a link.
      * @param url The url of the page to load.
      */
-    public Tab loadUrlInNewTab(final String url) throws InterruptedException {
-        return loadUrlInNewTab(url, false);
+    public Tab loadUrlInNewTab(String url) throws InterruptedException {
+        return mTestCommon.loadUrlInNewTab(url);
     }
 
     /**
@@ -399,21 +242,7 @@
      */
     public Tab loadUrlInNewTab(final String url, final boolean incognito)
             throws InterruptedException {
-        Tab tab = null;
-        try {
-            tab = ThreadUtils.runOnUiThreadBlocking(new Callable<Tab>() {
-                @Override
-                public Tab call() throws Exception {
-                    return getActivity().getTabCreator(incognito)
-                            .launchUrl(url, TabLaunchType.FROM_LINK);
-                }
-            });
-        } catch (ExecutionException e) {
-            fail("Failed to create new tab");
-        }
-        ChromeTabUtils.waitForTabPageLoaded(tab, url);
-        getInstrumentation().waitForIdleSync();
-        return tab;
+        return mTestCommon.loadUrlInNewTab(url, incognito);
     }
 
     /**
@@ -429,10 +258,7 @@
      */
     protected void startMainActivityWithURL(String url) throws InterruptedException {
         // Only launch Chrome.
-        Intent intent = new Intent(
-                TextUtils.isEmpty(url) ? Intent.ACTION_MAIN : Intent.ACTION_VIEW);
-        intent.addCategory(Intent.CATEGORY_LAUNCHER);
-        startMainActivityFromIntent(intent, url);
+        mTestCommon.startMainActivityWithURL(url);
     }
 
     /**
@@ -440,7 +266,7 @@
      * This is faster and less flakyness-prone than starting on the NTP.
      */
     protected void startMainActivityOnBlankPage() throws InterruptedException {
-        startMainActivityWithURL("about:blank");
+        mTestCommon.startMainActivityOnBlankPage();
     }
 
     /**
@@ -449,11 +275,7 @@
      */
     protected void startMainActivityFromExternalApp(String url, String appId)
             throws InterruptedException {
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        if (appId != null) {
-            intent.putExtra(Browser.EXTRA_APPLICATION_ID, appId);
-        }
-        startMainActivityFromIntent(intent, url);
+        mTestCommon.startMainActivityFromExternalApp(url, appId);
     }
 
     /**
@@ -464,34 +286,7 @@
      */
     protected void startMainActivityFromIntent(Intent intent, String url)
             throws InterruptedException {
-        prepareUrlIntent(intent, url);
-
-        startActivityCompletely(intent);
-
-        CriteriaHelper.pollUiThread(new Criteria("Tab never selected/initialized.") {
-            @Override
-            public boolean isSatisfied() {
-                return getActivity().getActivityTab() != null;
-            }
-        });
-        Tab tab = getActivity().getActivityTab();
-
-        ChromeTabUtils.waitForTabPageLoaded(tab, (String) null);
-
-        if (tab != null && NewTabPage.isNTPUrl(tab.getUrl())) {
-            NewTabPageTestUtils.waitForNtpLoaded(tab);
-        }
-
-        CriteriaHelper.pollUiThread(new Criteria("Deferred startup never completed") {
-            @Override
-            public boolean isSatisfied() {
-                return DeferredStartupHandler.getInstance().isDeferredStartupCompleteForApp();
-            }
-        });
-
-        assertNotNull(tab);
-        assertNotNull(tab.getView());
-        getInstrumentation().waitForIdleSync();
+        mTestCommon.startMainActivityFromIntent(intent, url);
     }
 
     /**
@@ -500,25 +295,7 @@
      * @param url the URL to be used (may be null)
      */
     protected Intent prepareUrlIntent(Intent intent, String url) {
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setComponent(new ComponentName(getInstrumentation().getTargetContext(),
-                ChromeLauncherActivity.class));
-
-        if (url != null) {
-            intent.setData(Uri.parse(url));
-        }
-
-        try {
-            Method method = getClass().getMethod(getName(), (Class[]) null);
-            if (((AnnotatedElement) method).isAnnotationPresent(RenderProcessLimit.class)) {
-                RenderProcessLimit limit = method.getAnnotation(RenderProcessLimit.class);
-                intent.putExtra(ChromeTabbedActivity.INTENT_EXTRA_TEST_RENDER_PROCESS_LIMIT,
-                        limit.value());
-            }
-        } catch (NoSuchMethodException ex) {
-            // Ignore exception.
-        }
-        return intent;
+        return mTestCommon.prepareUrlIntent(intent, url);
     }
 
     /**
@@ -526,46 +303,7 @@
      * Returns when receiving the 'PAGE_LOAD_FINISHED' notification.
      */
     protected void newIncognitoTabFromMenu() throws InterruptedException {
-        Tab tab = null;
-
-        final CallbackHelper createdCallback = new CallbackHelper();
-        final CallbackHelper selectedCallback = new CallbackHelper();
-
-        TabModel incognitoTabModel = getActivity().getTabModelSelector().getModel(true);
-        TabModelObserver observer = new EmptyTabModelObserver() {
-            @Override
-            public void didAddTab(Tab tab, TabLaunchType type) {
-                createdCallback.notifyCalled();
-            }
-
-            @Override
-            public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
-                selectedCallback.notifyCalled();
-            }
-        };
-        incognitoTabModel.addObserver(observer);
-
-        MenuUtils.invokeCustomMenuActionSync(getInstrumentation(), getActivity(),
-                R.id.new_incognito_tab_menu_id);
-
-        try {
-            createdCallback.waitForCallback(0);
-        } catch (TimeoutException ex) {
-            fail("Never received tab created event");
-        }
-        try {
-            selectedCallback.waitForCallback(0);
-        } catch (TimeoutException ex) {
-            fail("Never received tab selected event");
-        }
-        incognitoTabModel.removeObserver(observer);
-
-        tab = getActivity().getActivityTab();
-
-        ChromeTabUtils.waitForTabPageLoaded(tab, (String) null);
-        NewTabPageTestUtils.waitForNtpLoaded(tab);
-        getInstrumentation().waitForIdleSync();
-        Log.d(TAG, "newIncognitoTabFromMenu <<");
+        mTestCommon.newIncognitoTabFromMenu();
     }
 
     /**
@@ -574,22 +312,14 @@
      */
     protected void newIncognitoTabsFromMenu(int n)
             throws InterruptedException {
-        while (n > 0) {
-            newIncognitoTabFromMenu();
-            --n;
-        }
+        mTestCommon.newIncognitoTabsFromMenu(n);
     }
 
     /**
      * @return The number of incognito tabs currently open.
      */
     protected int incognitoTabsCount() {
-        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return getActivity().getTabModelSelector().getModel(true).getCount();
-            }
-        });
+        return mTestCommon.incognitoTabsCount();
     }
 
     /**
@@ -601,29 +331,8 @@
      *
      * @throws InterruptedException
      */
-    public void typeInOmnibox(final String text, final boolean oneCharAtATime)
-            throws InterruptedException {
-        final UrlBar urlBar = (UrlBar) getActivity().findViewById(R.id.url_bar);
-        assertNotNull(urlBar);
-
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                urlBar.requestFocus();
-                if (!oneCharAtATime) {
-                    urlBar.setText(text);
-                }
-            }
-        });
-
-        if (oneCharAtATime) {
-            final Instrumentation instrumentation = getInstrumentation();
-            for (int i = 0; i < text.length(); ++i) {
-                instrumentation.sendStringSync(text.substring(i, i + 1));
-                // Let's put some delay between key strokes to simulate a user pressing the keys.
-                Thread.sleep(20);
-            }
-        }
+    public void typeInOmnibox(String text, boolean oneCharAtATime) throws InterruptedException {
+        mTestCommon.typeInOmnibox(text, oneCharAtATime);
     }
 
     /**
@@ -638,95 +347,14 @@
      */
     protected OmniboxSuggestion findOmniboxSuggestion(String inputText, String displayText,
             String url, int type) throws InterruptedException {
-        long endTime = System.currentTimeMillis() + OMNIBOX_FIND_SUGGESTION_TIMEOUT_MS;
-
-        // Multiple suggestion events may occur before the one we're interested in is received.
-        final CallbackHelper onSuggestionsReceivedHelper = new CallbackHelper();
-        final LocationBarLayout locationBar =
-                (LocationBarLayout) getActivity().findViewById(R.id.location_bar);
-        locationBar.setAutocompleteController(new AutocompleteController(locationBar) {
-            @Override
-            public void onSuggestionsReceived(
-                    List<OmniboxSuggestion> suggestions,
-                    String inlineAutocompleteText,
-                    long currentNativeAutocompleteResult) {
-                super.onSuggestionsReceived(
-                        suggestions, inlineAutocompleteText, currentNativeAutocompleteResult);
-                onSuggestionsReceivedHelper.notifyCalled();
-            }
-        });
-
-        try {
-            typeInOmnibox(inputText, false);
-
-            while (true) {
-                try {
-                    int callbackCount = onSuggestionsReceivedHelper.getCallCount();
-                    onSuggestionsReceivedHelper.waitForCallback(
-                            callbackCount, 1,
-                            endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
-                } catch (TimeoutException exception) {
-                    return null;
-                }
-
-                // Wait for suggestions to show up.
-                CriteriaHelper.pollInstrumentationThread(new Criteria() {
-                    @Override
-                    public boolean isSatisfied() {
-                        return ((LocationBarLayout) getActivity().findViewById(
-                                R.id.location_bar)).getSuggestionList() != null;
-                    }
-                }, 3000, 10);
-                final ListView suggestionListView = locationBar.getSuggestionList();
-                OmniboxResultItem popupItem = (OmniboxResultItem) suggestionListView
-                        .getItemAtPosition(0);
-                OmniboxSuggestion suggestion = popupItem.getSuggestion();
-                if (suggestionListView.getCount() == 1
-                        && suggestion.getDisplayText().equals(inputText)
-                        && !suggestion.getDisplayText().equals(displayText)) {
-                    // If there is only one suggestion and it's the same as inputText,
-                    // wait for other suggestions before looking for the one we want.
-                    CriteriaHelper.pollInstrumentationThread(new Criteria() {
-                        @Override
-                        public boolean isSatisfied() {
-                            return suggestionListView.getCount() > 1;
-                        }
-                    }, 3000, 10);
-                }
-                int count = suggestionListView.getCount();
-                for (int i = 0; i < count; i++) {
-                    popupItem = (OmniboxResultItem) suggestionListView.getItemAtPosition(i);
-                    suggestion = popupItem.getSuggestion();
-                    if (suggestion.getType() != type) {
-                        continue;
-                    }
-                    if (displayText != null && !suggestion.getDisplayText().equals(displayText)) {
-                        continue;
-                    }
-                    if (url != null && !suggestion.getUrl().equals(url)) {
-                        continue;
-                    }
-                    return suggestion;
-                }
-            }
-        } finally {
-            locationBar.setAutocompleteController(new AutocompleteController(locationBar));
-        }
+        return mTestCommon.findOmniboxSuggestion(inputText, displayText, url, type);
     }
 
     /**
      * Returns the infobars being displayed by the current tab, or null if they don't exist.
      */
     protected List<InfoBar> getInfoBars() {
-        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<List<InfoBar>>() {
-            @Override
-            public List<InfoBar> call() throws Exception {
-                Tab currentTab = getActivity().getActivityTab();
-                assertNotNull(currentTab);
-                assertNotNull(currentTab.getInfoBarContainer());
-                return currentTab.getInfoBarContainer().getInfoBarsForTesting();
-            }
-        });
+        return mTestCommon.getInfoBars();
     }
 
     /**
@@ -734,11 +362,7 @@
      * Returns the activity that was started.
      */
     protected Preferences startPreferences(String fragmentName) {
-        Context context = getInstrumentation().getTargetContext();
-        Intent intent = PreferencesLauncher.createIntentForSettingsPage(context, fragmentName);
-        Activity activity = getInstrumentation().startActivitySync(intent);
-        assertTrue(activity instanceof Preferences);
-        return (Preferences) activity;
+        return mTestCommon.startPreferences(fragmentName);
     }
 
     /**
@@ -748,15 +372,14 @@
      */
     protected String runJavaScriptCodeInCurrentTab(String code) throws InterruptedException,
             TimeoutException {
-        return JavaScriptUtils.executeJavaScriptAndWaitForResult(
-                getActivity().getCurrentContentViewCore().getWebContents(), code);
+        return mTestCommon.runJavaScriptCodeInCurrentTab(code);
     }
 
     @Override
     protected void runTest() throws Throwable {
-        String perfTagAnalysisString = setupPotentialPerfTest();
+        String perfTagAnalysisString = mTestCommon.setupPotentialPerfTest();
         super.runTest();
-        endPerfTest(perfTagAnalysisString);
+        mTestCommon.endPerfTest(perfTagAnalysisString);
     }
 
     @Override
@@ -775,121 +398,17 @@
      * Waits till the ContentViewCore receives the expected page scale factor
      * from the compositor and asserts that this happens.
      */
-    protected void assertWaitForPageScaleFactorMatch(final float expectedScale)
-            throws InterruptedException {
-        ApplicationTestUtils.assertWaitForPageScaleFactorMatch(getActivity(), expectedScale);
+    protected void assertWaitForPageScaleFactorMatch(float expectedScale) {
+        mTestCommon.assertWaitForPageScaleFactorMatch(expectedScale);
     }
 
-    /**
-     * This method creates a special string that tells the python test harness what
-     * trace calls to track for this particular test run.  It can support multiple trace calls for
-     * each test and will make a new graph entry for all of them.  It should be noted that this
-     * method eats all exceptions.  This is so that it can never be the cause of a test failure.
-     * We still need to call this method even if we know the test will not run (ie: willTestRun is
-     * false).  This is because this method lets the python test harness know not to expect any
-     * perf output in this case.  In the case that the autoTrace parameter is set for the current
-     * test method, this will also start the PerfTrace facility automatically.
-     *
-     * @param willTestRun Whether or not this test will actually be run.
-     * @return A specially formatted string that contains which JSON perf markers to look at. This
-     *         will be analyzed by the perf test harness.
-     */
-    @SuppressFBWarnings({
-            "REC_CATCH_EXCEPTION",
-            "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE",
-            })
-    private String setupPotentialPerfTest() {
-        File perfFile = getInstrumentation().getTargetContext().getFileStreamPath(
-                PERF_OUTPUT_FILE);
-        perfFile.delete();
-        PerfTraceEvent.setOutputFile(perfFile);
-
-        String perfAnnotationString = "";
-
-        try {
-            Method method = getClass().getMethod(getName(), (Class[]) null);
-            PerfTest annotation = method.getAnnotation(PerfTest.class);
-            if (annotation != null) {
-                StringBuilder annotationData = new StringBuilder();
-                annotationData.append(String.format(PERF_ANNOTATION_FORMAT, method.getName()));
-
-                // Grab the minimum number of trace calls we will track (if names(),
-                // graphNames(), and graphValues() do not have the same number of elements, we
-                // will track as many as we can given the data available.
-                final int maxIndex = Math.min(annotation.traceNames().length, Math.min(
-                        annotation.graphNames().length, annotation.seriesNames().length));
-
-                List<String> allNames = new LinkedList<>();
-                for (int i = 0; i < maxIndex; ++i) {
-                    // Prune out all of ',' and ';' from the strings.  Replace them with '-'.
-                    String name = annotation.traceNames()[i].replaceAll("[,;]", "-");
-                    allNames.add(name);
-                    String graphName = annotation.graphNames()[i].replaceAll("[,;]", "-");
-                    String seriesName = annotation.seriesNames()[i].replaceAll("[,;]", "-");
-                    if (annotation.traceTiming()) {
-                        annotationData.append(name).append(",")
-                                .append(graphName).append(",")
-                                .append(seriesName).append(';');
-                    }
-
-                    // If memory tracing is enabled, add an additional graph for each one
-                    // defined to track timing perf that will track the corresponding memory
-                    // usage.
-                    // Keep the series name the same, but just append a memory identifying
-                    // prefix to the graph.
-                    if (annotation.traceMemory()) {
-                        String memName = PerfTraceEvent.makeMemoryTraceNameFromTimingName(name);
-                        String memGraphName = PerfTraceEvent.makeSafeTraceName(
-                                graphName, MEMORY_TRACE_GRAPH_SUFFIX);
-                        annotationData.append(memName).append(",")
-                                .append(memGraphName).append(",")
-                                .append(seriesName).append(';');
-                        allNames.add(memName);
-                    }
-                }
-                // We only record perf trace events for the names explicitly listed.
-                PerfTraceEvent.setFilter(allNames);
-
-                // Figure out if we should automatically start or stop the trace.
-                if (annotation.autoTrace()) {
-                    PerfTraceEvent.setEnabled(true);
-                }
-                PerfTraceEvent.setTimingTrackingEnabled(annotation.traceTiming());
-                PerfTraceEvent.setMemoryTrackingEnabled(annotation.traceMemory());
-
-                perfAnnotationString = annotationData.toString();
-            }
-        } catch (Exception ex) {
-            // Eat exception here.
-        }
-
-        return perfAnnotationString;
+    @Override
+    public String getTestName() {
+        return getName();
     }
 
-    /**
-     * This handles cleaning up the performance component of this test if it was a UI Perf test.
-     * This includes potentially shutting down PerfTraceEvent.  This method eats all exceptions so
-     * that it can never be the cause of a test failure.  The test harness will wait for
-     * {@code perfTagAnalysisString} to show up in the logcat before processing the JSON perf file,
-     * giving this method the chance to flush and dump the performance data before the harness reads
-     * it.
-     *
-     * @param perfTagAnalysisString A specially formatted string that tells the perf test harness
-     *                              which perf tags to analyze.
-     */
-    private void endPerfTest(String perfTagAnalysisString) {
-        try {
-            Method method = getClass().getMethod(getName(), (Class[]) null);
-            PerfTest annotation = method.getAnnotation(PerfTest.class);
-            if (annotation != null) {
-                if (PerfTraceEvent.enabled()) {
-                    PerfTraceEvent.setEnabled(false);
-                }
-
-                System.out.println(perfTagAnalysisString);
-            }
-        } catch (NoSuchMethodException ex) {
-            // Eat exception here.
-        }
+    @Override
+    public void setActivity(T t) {
+        super.setActivity(t);
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java
new file mode 100644
index 0000000..c26b1ac
--- /dev/null
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java
@@ -0,0 +1,794 @@
+// 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.
+
+package org.chromium.chrome.test;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.Browser;
+import android.support.test.internal.runner.listener.InstrumentationResultPrinter;
+import android.text.TextUtils;
+import android.widget.ListView;
+
+import org.junit.Assert;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ApplicationStatus.ActivityStateListener;
+import org.chromium.base.Log;
+import org.chromium.base.PerfTraceEvent;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.SuppressFBWarnings;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.PerfTest;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.DeferredStartupHandler;
+import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.infobar.InfoBar;
+import org.chromium.chrome.browser.ntp.NewTabPage;
+import org.chromium.chrome.browser.omnibox.AutocompleteController;
+import org.chromium.chrome.browser.omnibox.LocationBarLayout;
+import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxResultItem;
+import org.chromium.chrome.browser.omnibox.OmniboxSuggestion;
+import org.chromium.chrome.browser.omnibox.UrlBar;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.preferences.Preferences;
+import org.chromium.chrome.browser.preferences.PreferencesLauncher;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.test.util.ApplicationTestUtils;
+import org.chromium.chrome.test.util.ChromeTabUtils;
+import org.chromium.chrome.test.util.MenuUtils;
+import org.chromium.chrome.test.util.NewTabPageTestUtils;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.content.browser.test.util.JavaScriptUtils;
+import org.chromium.content.browser.test.util.RenderProcessLimit;
+import org.chromium.content_public.browser.LoadUrlParams;
+import org.chromium.ui.base.PageTransition;
+
+import java.io.File;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+final class ChromeActivityTestCommon<T extends ChromeActivity> {
+    private static final String TAG = "cr_CATestCommon";
+
+    // The number of ms to wait for the rendering activity to be started.
+    static final int ACTIVITY_START_TIMEOUT_MS = 1000;
+
+    private static final String PERF_ANNOTATION_FORMAT = "**PERFANNOTATION(%s):";
+
+    private static final String MEMORY_TRACE_GRAPH_SUFFIX = " - browser PSS";
+
+    private static final String PERF_OUTPUT_FILE = "PerfTestData.txt";
+
+    private static final long OMNIBOX_FIND_SUGGESTION_TIMEOUT_MS = 10 * 1000;
+
+    protected boolean mSkipClearAppData;
+    private Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler;
+    private Class<T> mChromeActivityClass;
+    private ChromeTestCommonCallback<T> mCallback;
+
+    ChromeActivityTestCommon(Class<T> activityClass, ChromeTestCommonCallback<T> callback) {
+        mChromeActivityClass = activityClass;
+        mCallback = callback;
+    }
+
+    private class ChromeUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
+        @Override
+        public void uncaughtException(Thread t, Throwable e) {
+            String stackTrace = android.util.Log.getStackTraceString(e);
+            if (e.getClass().getName().endsWith("StrictModeViolation")) {
+                stackTrace += "\nSearch logcat for \"StrictMode policy violation\" for full stack.";
+            }
+            Bundle resultsBundle = new Bundle();
+            resultsBundle.putString(
+                    InstrumentationResultPrinter.REPORT_KEY_NAME_CLASS, getClass().getName());
+            resultsBundle.putString(
+                    InstrumentationResultPrinter.REPORT_KEY_NAME_TEST, mCallback.getTestName());
+            resultsBundle.putString(InstrumentationResultPrinter.REPORT_KEY_STACK, stackTrace);
+            mCallback.getInstrumentation().sendStatus(-1, resultsBundle);
+            mDefaultUncaughtExceptionHandler.uncaughtException(t, e);
+        }
+    }
+
+    void setUp() throws Exception {
+        mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
+        Thread.setDefaultUncaughtExceptionHandler(new ChromeUncaughtExceptionHandler());
+        ApplicationTestUtils.setUp(
+                mCallback.getInstrumentation().getTargetContext(), !mSkipClearAppData);
+        mCallback.setActivityInitialTouchMode(false);
+
+        // Preload Calendar so that it does not trigger ReadFromDisk Strict mode violations if
+        // called on the UI Thread. See https://crbug.com/705477 and https://crbug.com/577185
+        Calendar.getInstance();
+    }
+
+    void tearDown() throws Exception {
+        ApplicationTestUtils.tearDown(mCallback.getInstrumentation().getTargetContext());
+        Thread.setDefaultUncaughtExceptionHandler(mDefaultUncaughtExceptionHandler);
+    }
+
+    /**
+     * Matches testString against baseString.
+     * Returns 0 if there is no match, 1 if an exact match and 2 if a fuzzy match.
+     */
+    static int matchUrl(String baseString, String testString) {
+        if (baseString.equals(testString)) {
+            return 1;
+        }
+        if (baseString.contains(testString)) {
+            return 2;
+        }
+        return 0;
+    }
+
+    /**
+     * Invokes {@link Instrumentation#startActivitySync(Intent)} and sets the
+     * test case's activity to the result. See the documentation for
+     * {@link Instrumentation#startActivitySync(Intent)} on the timing of the
+     * return, but generally speaking the activity's "onCreate" has completed
+     * and the activity's main looper has become idle.
+     */
+    void startActivityCompletely(Intent intent) {
+        final CallbackHelper activityCallback = new CallbackHelper();
+        final AtomicReference<T> activityRef = new AtomicReference<>();
+        ActivityStateListener stateListener = new ActivityStateListener() {
+            @SuppressWarnings("unchecked")
+            @Override
+            public void onActivityStateChange(Activity activity, int newState) {
+                if (newState == ActivityState.RESUMED) {
+                    if (!mChromeActivityClass.isAssignableFrom(activity.getClass())) {
+                        return;
+                    }
+
+                    activityRef.set((T) activity);
+                    activityCallback.notifyCalled();
+                    ApplicationStatus.unregisterActivityStateListener(this);
+                }
+            }
+        };
+        ApplicationStatus.registerStateListenerForAllActivities(stateListener);
+
+        try {
+            mCallback.getInstrumentation().startActivitySync(intent);
+            activityCallback.waitForCallback("Activity did not start as expected", 0);
+            T activity = activityRef.get();
+            Assert.assertNotNull("Activity reference is null.", activity);
+            mCallback.setActivity(activity);
+            Log.d(TAG, "startActivityCompletely <<");
+        } catch (InterruptedException | TimeoutException e) {
+            throw new RuntimeException(e);
+        } finally {
+            ApplicationStatus.unregisterActivityStateListener(stateListener);
+        }
+    }
+
+    /** Convenience function for {@link ApplicationTestUtils#clearAppData(Context)}. */
+    void clearAppData() {
+        ApplicationTestUtils.clearAppData(mCallback.getInstrumentation().getTargetContext());
+    }
+
+    /**
+     * Enables or disables network predictions, i.e. prerendering, prefetching, DNS preresolution,
+     * etc. Network predictions are enabled by default.
+     */
+    void setNetworkPredictionEnabled(final boolean enabled) {
+        mCallback.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                PrefServiceBridge.getInstance().setNetworkPredictionEnabled(enabled);
+            }
+        });
+    }
+
+    /**
+     * Waits for {@link AsyncTask}'s that have been queued to finish. Note, this
+     * only waits for tasks that have been started using the default
+     * {@link java.util.concurrent.Executor}, which executes tasks serially.
+     *
+     * @param timeout how long to wait for tasks to complete
+     */
+    void waitForAsyncTasks(long timeout) throws InterruptedException {
+        final Semaphore s = new Semaphore(0);
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... arg0) {
+                s.release();
+                return null;
+            }
+        }
+                .execute();
+        Assert.assertTrue(s.tryAcquire(timeout, TimeUnit.MILLISECONDS));
+    }
+
+    /**
+     * Navigates to a URL directly without going through the UrlBar. This bypasses the page
+     * preloading mechanism of the UrlBar.
+     * @param url            The url to load in the current tab.
+     * @param secondsToWait  The number of seconds to wait for the page to be loaded.
+     * @return FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the page has been
+     *         prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    int loadUrl(final String url, long secondsToWait)
+            throws IllegalArgumentException, InterruptedException {
+        return loadUrlInTab(url, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR,
+                mCallback.getActivity().getActivityTab(), secondsToWait);
+    }
+
+    /**
+     * Navigates to a URL directly without going through the UrlBar. This bypasses the page
+     * preloading mechanism of the UrlBar.
+     * @param url The url to load in the current tab.
+     * @return FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the page has been
+     *         prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    int loadUrl(final String url) throws IllegalArgumentException, InterruptedException {
+        return loadUrlInTab(url, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR,
+                mCallback.getActivity().getActivityTab());
+    }
+
+    /**
+     * @param url            The url of the page to load.
+     * @param pageTransition The type of transition. see
+     *                       {@link org.chromium.ui.base.PageTransition}
+     *                       for valid values.
+     * @param tab            The tab to load the url into.
+     * @param secondsToWait  The number of seconds to wait for the page to be loaded.
+     * @return               FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the
+     *                       page has been prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    int loadUrlInTab(final String url, final int pageTransition, final Tab tab, long secondsToWait)
+            throws InterruptedException {
+        Assert.assertNotNull("Cannot load the url in a null tab", tab);
+        final AtomicInteger result = new AtomicInteger();
+
+        ChromeTabUtils.waitForTabPageLoaded(tab, new Runnable() {
+            @Override
+            public void run() {
+                ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+                    @Override
+                    public void run() {
+                        result.set(tab.loadUrl(new LoadUrlParams(url, pageTransition)));
+                    }
+                });
+            }
+        }, secondsToWait);
+        mCallback.getInstrumentation().waitForIdleSync();
+        return result.get();
+    }
+
+    /**
+     * @param url            The url of the page to load.
+     * @param pageTransition The type of transition. see
+     *                       {@link org.chromium.ui.base.PageTransition}
+     *                       for valid values.
+     * @param tab            The tab to load the url into.
+     * @return               FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the
+     *                       page has been prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    int loadUrlInTab(final String url, final int pageTransition, final Tab tab)
+            throws InterruptedException {
+        return loadUrlInTab(url, pageTransition, tab, CallbackHelper.WAIT_TIMEOUT_SECONDS);
+    }
+
+    /**
+     * Load a url in a new tab. The {@link Tab} will pretend to be created from a link.
+     * @param url The url of the page to load.
+     */
+    Tab loadUrlInNewTab(final String url) throws InterruptedException {
+        return loadUrlInNewTab(url, false);
+    }
+
+    /**
+     * Load a url in a new tab. The {@link Tab} will pretend to be created from a link.
+     * @param url The url of the page to load.
+     * @param incognito Whether the new tab should be incognito.
+     */
+    Tab loadUrlInNewTab(final String url, final boolean incognito) throws InterruptedException {
+        Tab tab = null;
+        try {
+            tab = ThreadUtils.runOnUiThreadBlocking(new Callable<Tab>() {
+                @Override
+                public Tab call() throws Exception {
+                    return mCallback.getActivity().getTabCreator(incognito).launchUrl(
+                            url, TabLaunchType.FROM_LINK);
+                }
+            });
+        } catch (ExecutionException e) {
+            Assert.fail("Failed to create new tab");
+        }
+        ChromeTabUtils.waitForTabPageLoaded(tab, url);
+        mCallback.getInstrumentation().waitForIdleSync();
+        return tab;
+    }
+
+    /**
+     * Simulates starting Main Activity from launcher, blocks until it is started.
+     */
+    void startMainActivityFromLauncher() throws InterruptedException {
+        startMainActivityWithURL(null);
+    }
+
+    /**
+     * Starts the Main activity on the specified URL. Passing a null URL ensures the default page is
+     * loaded, which is the NTP with a new profile .
+     */
+    void startMainActivityWithURL(String url) throws InterruptedException {
+        // Only launch Chrome.
+        Intent intent =
+                new Intent(TextUtils.isEmpty(url) ? Intent.ACTION_MAIN : Intent.ACTION_VIEW);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        startMainActivityFromIntent(intent, url);
+    }
+
+    /**
+     * Starts the Main activity and open a blank page.
+     * This is faster and less flakyness-prone than starting on the NTP.
+     */
+    void startMainActivityOnBlankPage() throws InterruptedException {
+        startMainActivityWithURL("about:blank");
+    }
+
+    /**
+     * Starts the Main activity as if it was started from an external application, on the specified
+     * URL.
+     */
+    void startMainActivityFromExternalApp(String url, String appId) throws InterruptedException {
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        if (appId != null) {
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID, appId);
+        }
+        startMainActivityFromIntent(intent, url);
+    }
+
+    /**
+     * Starts the Main activity using the passed intent, and using the specified URL.
+     * This method waits for DEFERRED_STARTUP to fire as well as a subsequent
+     * idle-sync of the main looper thread, and the initial tab must either
+     * complete its load or it must crash before this method will return.
+     */
+    void startMainActivityFromIntent(Intent intent, String url) throws InterruptedException {
+        prepareUrlIntent(intent, url);
+
+        startActivityCompletely(intent);
+
+        CriteriaHelper.pollUiThread(new Criteria("Tab never selected/initialized.") {
+            @Override
+            public boolean isSatisfied() {
+                return mCallback.getActivity().getActivityTab() != null;
+            }
+        });
+        Tab tab = mCallback.getActivity().getActivityTab();
+
+        ChromeTabUtils.waitForTabPageLoaded(tab, (String) null);
+
+        if (tab != null && NewTabPage.isNTPUrl(tab.getUrl())) {
+            NewTabPageTestUtils.waitForNtpLoaded(tab);
+        }
+
+        CriteriaHelper.pollUiThread(new Criteria("Deferred startup never completed") {
+            @Override
+            public boolean isSatisfied() {
+                return DeferredStartupHandler.getInstance().isDeferredStartupCompleteForApp();
+            }
+        });
+
+        Assert.assertNotNull(tab);
+        Assert.assertNotNull(tab.getView());
+        mCallback.getInstrumentation().waitForIdleSync();
+    }
+
+    /**
+     * Prepares a URL intent to start the activity.
+     * @param intent the intent to be modified
+     * @param url the URL to be used (may be null)
+     */
+    Intent prepareUrlIntent(Intent intent, String url) {
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setComponent(new ComponentName(
+                mCallback.getInstrumentation().getTargetContext(), ChromeLauncherActivity.class));
+
+        if (url != null) {
+            intent.setData(Uri.parse(url));
+        }
+
+        try {
+            Method method = getClass().getMethod(mCallback.getTestName(), (Class[]) null);
+            if (((AnnotatedElement) method).isAnnotationPresent(RenderProcessLimit.class)) {
+                RenderProcessLimit limit = method.getAnnotation(RenderProcessLimit.class);
+                intent.putExtra(
+                        ChromeTabbedActivity.INTENT_EXTRA_TEST_RENDER_PROCESS_LIMIT, limit.value());
+            }
+        } catch (NoSuchMethodException ex) {
+            // Ignore exception.
+        }
+        return intent;
+    }
+
+    /**
+     * Open an incognito tab by invoking the 'new incognito' menu item.
+     * Returns when receiving the 'PAGE_LOAD_FINISHED' notification.
+     */
+    void newIncognitoTabFromMenu() throws InterruptedException {
+        Tab tab = null;
+
+        final CallbackHelper createdCallback = new CallbackHelper();
+        final CallbackHelper selectedCallback = new CallbackHelper();
+
+        TabModel incognitoTabModel = mCallback.getActivity().getTabModelSelector().getModel(true);
+        TabModelObserver observer = new EmptyTabModelObserver() {
+            @Override
+            public void didAddTab(Tab tab, TabLaunchType type) {
+                createdCallback.notifyCalled();
+            }
+
+            @Override
+            public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
+                selectedCallback.notifyCalled();
+            }
+        };
+        incognitoTabModel.addObserver(observer);
+
+        MenuUtils.invokeCustomMenuActionSync(mCallback.getInstrumentation(),
+                mCallback.getActivity(), R.id.new_incognito_tab_menu_id);
+
+        try {
+            createdCallback.waitForCallback(0);
+        } catch (TimeoutException ex) {
+            Assert.fail("Never received tab created event");
+        }
+        try {
+            selectedCallback.waitForCallback(0);
+        } catch (TimeoutException ex) {
+            Assert.fail("Never received tab selected event");
+        }
+        incognitoTabModel.removeObserver(observer);
+
+        tab = mCallback.getActivity().getActivityTab();
+
+        ChromeTabUtils.waitForTabPageLoaded(tab, (String) null);
+        NewTabPageTestUtils.waitForNtpLoaded(tab);
+        mCallback.getInstrumentation().waitForIdleSync();
+        Log.d(TAG, "newIncognitoTabFromMenu <<");
+    }
+
+    /**
+     * New multiple incognito tabs by invoking the 'new incognito' menu item n times.
+     * @param n The number of tabs you want to create.
+     */
+    void newIncognitoTabsFromMenu(int n) throws InterruptedException {
+        while (n > 0) {
+            newIncognitoTabFromMenu();
+            --n;
+        }
+    }
+
+    /**
+     * @return The number of incognito tabs currently open.
+     */
+    int incognitoTabsCount() {
+        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return mCallback.getActivity().getTabModelSelector().getModel(true).getCount();
+            }
+        });
+    }
+
+    /**
+     * Looks up the Omnibox in the view hierarchy and types the specified
+     * text into it, requesting focus and using an inter-character delay of
+     * 200ms.
+     *
+     * @param oneCharAtATime Whether to type text one character at a time or all at once.
+     *
+     * @throws InterruptedException
+     */
+    void typeInOmnibox(final String text, final boolean oneCharAtATime)
+            throws InterruptedException {
+        final UrlBar urlBar = (UrlBar) mCallback.getActivity().findViewById(R.id.url_bar);
+        Assert.assertNotNull(urlBar);
+
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                urlBar.requestFocus();
+                if (!oneCharAtATime) {
+                    urlBar.setText(text);
+                }
+            }
+        });
+
+        if (oneCharAtATime) {
+            final Instrumentation instrumentation = mCallback.getInstrumentation();
+            for (int i = 0; i < text.length(); ++i) {
+                instrumentation.sendStringSync(text.substring(i, i + 1));
+                // Let's put some delay between key strokes to simulate a user pressing the keys.
+                Thread.sleep(20);
+            }
+        }
+    }
+
+    /**
+     * Searches for a given suggestion after typing given text in the Omnibox.
+     *
+     * @param inputText Input text to type into the Omnibox.
+     * @param displayText Suggestion text expected to be found. Passing in null ignores this field.
+     * @param url URL expected to be found. Passing in null ignores this field.
+     * @param type Type of suggestion expected to be found. Passing in null ignores this field.
+     *
+     * @throws InterruptedException
+     */
+    OmniboxSuggestion findOmniboxSuggestion(String inputText, String displayText, String url,
+            int type) throws InterruptedException {
+        long endTime = System.currentTimeMillis() + OMNIBOX_FIND_SUGGESTION_TIMEOUT_MS;
+
+        // Multiple suggestion events may occur before the one we're interested in is received.
+        final CallbackHelper onSuggestionsReceivedHelper = new CallbackHelper();
+        final LocationBarLayout locationBar =
+                (LocationBarLayout) mCallback.getActivity().findViewById(R.id.location_bar);
+        locationBar.setAutocompleteController(new AutocompleteController(locationBar) {
+            @Override
+            public void onSuggestionsReceived(List<OmniboxSuggestion> suggestions,
+                    String inlineAutocompleteText, long currentNativeAutocompleteResult) {
+                super.onSuggestionsReceived(
+                        suggestions, inlineAutocompleteText, currentNativeAutocompleteResult);
+                onSuggestionsReceivedHelper.notifyCalled();
+            }
+        });
+
+        try {
+            typeInOmnibox(inputText, false);
+
+            while (true) {
+                try {
+                    int callbackCount = onSuggestionsReceivedHelper.getCallCount();
+                    onSuggestionsReceivedHelper.waitForCallback(callbackCount, 1,
+                            endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
+                } catch (TimeoutException exception) {
+                    return null;
+                }
+
+                // Wait for suggestions to show up.
+                CriteriaHelper.pollInstrumentationThread(new Criteria() {
+                    @Override
+                    public boolean isSatisfied() {
+                        return ((LocationBarLayout) mCallback.getActivity().findViewById(
+                                        R.id.location_bar))
+                                       .getSuggestionList()
+                                != null;
+                    }
+                }, 3000, 10);
+                final ListView suggestionListView = locationBar.getSuggestionList();
+                OmniboxResultItem popupItem =
+                        (OmniboxResultItem) suggestionListView.getItemAtPosition(0);
+                OmniboxSuggestion suggestion = popupItem.getSuggestion();
+                if (suggestionListView.getCount() == 1
+                        && suggestion.getDisplayText().equals(inputText)
+                        && !suggestion.getDisplayText().equals(displayText)) {
+                    // If there is only one suggestion and it's the same as inputText,
+                    // wait for other suggestions before looking for the one we want.
+                    CriteriaHelper.pollInstrumentationThread(new Criteria() {
+                        @Override
+                        public boolean isSatisfied() {
+                            return suggestionListView.getCount() > 1;
+                        }
+                    }, 3000, 10);
+                }
+                int count = suggestionListView.getCount();
+                for (int i = 0; i < count; i++) {
+                    popupItem = (OmniboxResultItem) suggestionListView.getItemAtPosition(i);
+                    suggestion = popupItem.getSuggestion();
+                    if (suggestion.getType() != type) {
+                        continue;
+                    }
+                    if (displayText != null && !suggestion.getDisplayText().equals(displayText)) {
+                        continue;
+                    }
+                    if (url != null && !suggestion.getUrl().equals(url)) {
+                        continue;
+                    }
+                    return suggestion;
+                }
+            }
+        } finally {
+            locationBar.setAutocompleteController(new AutocompleteController(locationBar));
+        }
+    }
+
+    /**
+     * Returns the infobars being displayed by the current tab, or null if they don't exist.
+     */
+    List<InfoBar> getInfoBars() {
+        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<List<InfoBar>>() {
+            @Override
+            public List<InfoBar> call() throws Exception {
+                Tab currentTab = mCallback.getActivity().getActivityTab();
+                Assert.assertNotNull(currentTab);
+                Assert.assertNotNull(currentTab.getInfoBarContainer());
+                return currentTab.getInfoBarContainer().getInfoBarsForTesting();
+            }
+        });
+    }
+
+    /**
+     * Launches the preferences menu and starts the preferences activity named fragmentName.
+     * Returns the activity that was started.
+     */
+    Preferences startPreferences(String fragmentName) {
+        Context context = mCallback.getInstrumentation().getTargetContext();
+        Intent intent = PreferencesLauncher.createIntentForSettingsPage(context, fragmentName);
+        Activity activity = mCallback.getInstrumentation().startActivitySync(intent);
+        Assert.assertTrue(activity instanceof Preferences);
+        return (Preferences) activity;
+    }
+
+    /**
+     * Executes the given snippet of JavaScript code within the current tab. Returns the result of
+     * its execution in JSON format.
+     * @throws InterruptedException
+     */
+    String runJavaScriptCodeInCurrentTab(String code)
+            throws InterruptedException, TimeoutException {
+        return JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                mCallback.getActivity().getCurrentContentViewCore().getWebContents(), code);
+    }
+
+    /**
+     * Waits till the ContentViewCore receives the expected page scale factor
+     * from the compositor and asserts that this happens.
+     */
+    void assertWaitForPageScaleFactorMatch(final float expectedScale) {
+        ApplicationTestUtils.assertWaitForPageScaleFactorMatch(
+                mCallback.getActivity(), expectedScale);
+    }
+
+    /**
+     * This method creates a special string that tells the python test harness what
+     * trace calls to track for this particular test run.  It can support multiple trace calls for
+     * each test and will make a new graph entry for all of them.  It should be noted that this
+     * method eats all exceptions.  This is so that it can never be the cause of a test failure.
+     * We still need to call this method even if we know the test will not run (ie: willTestRun is
+     * false).  This is because this method lets the python test harness know not to expect any
+     * perf output in this case.  In the case that the autoTrace parameter is set for the current
+     * test method, this will also start the PerfTrace facility automatically.
+     *
+     * @return A specially formatted string that contains which JSON perf markers to look at. This
+     *         will be analyzed by the perf test harness.
+     */
+    @SuppressFBWarnings({
+            "REC_CATCH_EXCEPTION", "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", })
+    String setupPotentialPerfTest() {
+        File perfFile = mCallback.getInstrumentation().getTargetContext().getFileStreamPath(
+                PERF_OUTPUT_FILE);
+        perfFile.delete();
+        PerfTraceEvent.setOutputFile(perfFile);
+
+        String perfAnnotationString = "";
+
+        try {
+            Method method = getClass().getMethod(mCallback.getTestName(), (Class[]) null);
+            PerfTest annotation = method.getAnnotation(PerfTest.class);
+            if (annotation != null) {
+                StringBuilder annotationData = new StringBuilder();
+                annotationData.append(String.format(PERF_ANNOTATION_FORMAT, method.getName()));
+
+                // Grab the minimum number of trace calls we will track (if names(),
+                // graphNames(), and graphValues() do not have the same number of elements, we
+                // will track as many as we can given the data available.
+                final int maxIndex = Math.min(annotation.traceNames().length,
+                        Math.min(annotation.graphNames().length, annotation.seriesNames().length));
+
+                List<String> allNames = new LinkedList<>();
+                for (int i = 0; i < maxIndex; ++i) {
+                    // Prune out all of ',' and ';' from the strings.  Replace them with '-'.
+                    String name = annotation.traceNames()[i].replaceAll("[,;]", "-");
+                    allNames.add(name);
+                    String graphName = annotation.graphNames()[i].replaceAll("[,;]", "-");
+                    String seriesName = annotation.seriesNames()[i].replaceAll("[,;]", "-");
+                    if (annotation.traceTiming()) {
+                        annotationData.append(name)
+                                .append(",")
+                                .append(graphName)
+                                .append(",")
+                                .append(seriesName)
+                                .append(';');
+                    }
+
+                    // If memory tracing is enabled, add an additional graph for each one
+                    // defined to track timing perf that will track the corresponding memory
+                    // usage.
+                    // Keep the series name the same, but just append a memory identifying
+                    // prefix to the graph.
+                    if (annotation.traceMemory()) {
+                        String memName = PerfTraceEvent.makeMemoryTraceNameFromTimingName(name);
+                        String memGraphName = PerfTraceEvent.makeSafeTraceName(
+                                graphName, MEMORY_TRACE_GRAPH_SUFFIX);
+                        annotationData.append(memName)
+                                .append(",")
+                                .append(memGraphName)
+                                .append(",")
+                                .append(seriesName)
+                                .append(';');
+                        allNames.add(memName);
+                    }
+                }
+                // We only record perf trace events for the names explicitly listed.
+                PerfTraceEvent.setFilter(allNames);
+
+                // Figure out if we should automatically start or stop the trace.
+                if (annotation.autoTrace()) {
+                    PerfTraceEvent.setEnabled(true);
+                }
+                PerfTraceEvent.setTimingTrackingEnabled(annotation.traceTiming());
+                PerfTraceEvent.setMemoryTrackingEnabled(annotation.traceMemory());
+
+                perfAnnotationString = annotationData.toString();
+            }
+        } catch (Exception ex) {
+            // Eat exception here.
+        }
+
+        return perfAnnotationString;
+    }
+
+    /**
+     * This handles cleaning up the performance component of this test if it was a UI Perf test.
+     * This includes potentially shutting down PerfTraceEvent.  This method eats all exceptions so
+     * that it can never be the cause of a test failure.  The test harness will wait for
+     * {@code perfTagAnalysisString} to show up in the logcat before processing the JSON perf file,
+     * giving this method the chance to flush and dump the performance data before the harness reads
+     * it.
+     *
+     * @param perfTagAnalysisString A specially formatted string that tells the perf test harness
+     *                              which perf tags to analyze.
+     */
+    void endPerfTest(String perfTagAnalysisString) {
+        try {
+            Method method = getClass().getMethod(mCallback.getTestName(), (Class[]) null);
+            PerfTest annotation = method.getAnnotation(PerfTest.class);
+            if (annotation != null) {
+                if (PerfTraceEvent.enabled()) {
+                    PerfTraceEvent.setEnabled(false);
+                }
+
+                System.out.println(perfTagAnalysisString);
+            }
+        } catch (NoSuchMethodException ex) {
+            // Eat exception here.
+        }
+    }
+
+    public interface ChromeTestCommonCallback<T extends ChromeActivity> {
+        String getTestName();
+        void setActivity(T t);
+        Instrumentation getInstrumentation();
+        void setActivityInitialTouchMode(boolean touchMode);
+        T getActivity();
+    }
+}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
new file mode 100644
index 0000000..f9818431
--- /dev/null
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -0,0 +1,378 @@
+// 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.
+
+package org.chromium.chrome.test;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.infobar.InfoBar;
+import org.chromium.chrome.browser.omnibox.OmniboxSuggestion;
+import org.chromium.chrome.browser.preferences.Preferences;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.test.ChromeActivityTestCommon.ChromeTestCommonCallback;
+import org.chromium.chrome.test.util.ApplicationTestUtils;
+
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+//TODO(yolandyan): break this test rule down to smaller rules once the junit4 migration is over
+public class ChromeActivityTestRule<T extends ChromeActivity>
+        extends ActivityTestRule<T> implements ChromeTestCommonCallback<T> {
+    private final ChromeActivityTestCommon<T> mTestCommon;
+    private String mCurrentTestName;
+
+    public static final String DISABLE_NETWORK_PREDICTION_FLAG =
+            "--disable-features=NetworkPrediction";
+
+    // ChromeActivityTestRule
+    private T mSetActivity;
+
+    /**
+     * @param activityClass
+     */
+    public ChromeActivityTestRule(Class<T> activityClass) {
+        this(activityClass, false);
+    }
+
+    public ChromeActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
+        super(activityClass, initialTouchMode, false);
+        mTestCommon = new ChromeActivityTestCommon<T>(activityClass, this);
+    }
+
+    @Override
+    public Statement apply(final Statement base, Description description) {
+        mCurrentTestName = description.getMethodName();
+        final Statement superBase = super.apply(new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                mTestCommon.setUp();
+                base.evaluate();
+            }
+        }, description);
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                String perfTagAnalysisString = mTestCommon.setupPotentialPerfTest();
+                superBase.evaluate();
+                mTestCommon.endPerfTest(perfTagAnalysisString);
+            }
+        };
+    }
+
+    /**
+     * Return the timeout limit for Chrome activty start in tests
+     */
+    public static int getActivityStartTimeoutMs() {
+        return ChromeActivityTestCommon.ACTIVITY_START_TIMEOUT_MS;
+    }
+
+    @Override
+    protected void afterActivityFinished() {
+        try {
+            mTestCommon.tearDown();
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to tearDown", e);
+        }
+        super.afterActivityFinished();
+    }
+
+    // TODO(yolandyan): remove this once startActivityCompletely is refactored out of
+    // ChromeActivityTestRule
+    @Override
+    public T getActivity() {
+        if (mSetActivity != null) {
+            return mSetActivity;
+        }
+        return super.getActivity();
+    }
+
+    /**
+     * Matches testString against baseString.
+     * Returns 0 if there is no match, 1 if an exact match and 2 if a fuzzy match.
+     */
+    public static int matchUrl(String baseString, String testString) {
+        return ChromeActivityTestCommon.matchUrl(baseString, testString);
+    }
+
+    /**
+     * Invokes {@link Instrumentation#startActivitySync(Intent)} and sets the
+     * test case's activity to the result. See the documentation for
+     * {@link Instrumentation#startActivitySync(Intent)} on the timing of the
+     * return, but generally speaking the activity's "onCreate" has completed
+     * and the activity's main looper has become idle.
+     */
+    public void startActivityCompletely(Intent intent) {
+        mTestCommon.startActivityCompletely(intent);
+    }
+
+    /** Convenience function for {@link ApplicationTestUtils#clearAppData(Context)}. */
+    public void clearAppData() {
+        mTestCommon.clearAppData();
+    }
+
+    /**
+     * Enables or disables network predictions, i.e. prerendering, prefetching, DNS preresolution,
+     * etc. Network predictions are enabled by default.
+     */
+    public void setNetworkPredictionEnabled(final boolean enabled) {
+        mTestCommon.setNetworkPredictionEnabled(enabled);
+    }
+
+    /**
+     * Waits for {@link AsyncTask}'s that have been queued to finish. Note, this
+     * only waits for tasks that have been started using the default
+     * {@link java.util.concurrent.Executor}, which executes tasks serially.
+     *
+     * @param timeout how long to wait for tasks to complete
+     */
+    public void waitForAsyncTasks(long timeout) throws InterruptedException {
+        mTestCommon.waitForAsyncTasks(timeout);
+    }
+
+    /**
+     * Navigates to a URL directly without going through the UrlBar. This bypasses the page
+     * preloading mechanism of the UrlBar.
+     * @param url            The url to load in the current tab.
+     * @param secondsToWait  The number of seconds to wait for the page to be loaded.
+     * @return FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the page has been
+     *         prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    public int loadUrl(String url, long secondsToWait)
+            throws IllegalArgumentException, InterruptedException {
+        return mTestCommon.loadUrl(url, secondsToWait);
+    }
+
+    /**
+     * Navigates to a URL directly without going through the UrlBar. This bypasses the page
+     * preloading mechanism of the UrlBar.
+     * @param url The url to load in the current tab.
+     * @return FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the page has been
+     *         prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    public int loadUrl(String url) throws IllegalArgumentException, InterruptedException {
+        return mTestCommon.loadUrl(url);
+    }
+
+    /**
+     * @param url            The url of the page to load.
+     * @param pageTransition The type of transition. see
+     *                       {@link org.chromium.ui.base.PageTransition}
+     *                       for valid values.
+     * @param tab            The tab to load the url into.
+     * @param secondsToWait  The number of seconds to wait for the page to be loaded.
+     * @return               FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the
+     *                       page has been prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    public int loadUrlInTab(String url, int pageTransition, Tab tab, long secondsToWait)
+            throws InterruptedException {
+        return mTestCommon.loadUrlInTab(url, pageTransition, tab, secondsToWait);
+    }
+
+    /**
+     * @param url            The url of the page to load.
+     * @param pageTransition The type of transition. see
+     *                       {@link org.chromium.ui.base.PageTransition}
+     *                       for valid values.
+     * @param tab            The tab to load the url into.
+     * @return               FULL_PRERENDERED_PAGE_LOAD or PARTIAL_PRERENDERED_PAGE_LOAD if the
+     *                       page has been prerendered. DEFAULT_PAGE_LOAD if it had not.
+     */
+    public int loadUrlInTab(String url, int pageTransition, Tab tab) throws InterruptedException {
+        return mTestCommon.loadUrlInTab(url, pageTransition, tab);
+    }
+
+    /**
+     * Load a url in a new tab. The {@link Tab} will pretend to be created from a link.
+     * @param url The url of the page to load.
+     */
+    public Tab loadUrlInNewTab(String url) throws InterruptedException {
+        return mTestCommon.loadUrlInNewTab(url);
+    }
+
+    /**
+     * Load a url in a new tab. The {@link Tab} will pretend to be created from a link.
+     * @param url The url of the page to load.
+     * @param incognito Whether the new tab should be incognito.
+     */
+    public Tab loadUrlInNewTab(final String url, final boolean incognito)
+            throws InterruptedException {
+        return mTestCommon.loadUrlInNewTab(url, incognito);
+    }
+
+    /**
+     * Simulates starting Main Activity from launcher, blocks until it is started.
+     */
+    public void startMainActivityFromLauncher() throws InterruptedException {
+        startMainActivityWithURL(null);
+    }
+
+    /**
+     * Starts the Main activity on the specified URL. Passing a null URL ensures the default page is
+     * loaded, which is the NTP with a new profile .
+     */
+    public void startMainActivityWithURL(String url) throws InterruptedException {
+        // Only launch Chrome.
+        mTestCommon.startMainActivityWithURL(url);
+    }
+
+    /**
+     * Starts the Main activity and open a blank page.
+     * This is faster and less flakyness-prone than starting on the NTP.
+     */
+    public void startMainActivityOnBlankPage() throws InterruptedException {
+        mTestCommon.startMainActivityOnBlankPage();
+    }
+
+    /**
+     * Starts the Main activity as if it was started from an external application, on the specified
+     * URL.
+     */
+    public void startMainActivityFromExternalApp(String url, String appId)
+            throws InterruptedException {
+        mTestCommon.startMainActivityFromExternalApp(url, appId);
+    }
+
+    /**
+     * Starts the Main activity using the passed intent, and using the specified URL.
+     * This method waits for DEFERRED_STARTUP to fire as well as a subsequent
+     * idle-sync of the main looper thread, and the initial tab must either
+     * complete its load or it must crash before this method will return.
+     */
+    public void startMainActivityFromIntent(Intent intent, String url) throws InterruptedException {
+        mTestCommon.startMainActivityFromIntent(intent, url);
+    }
+
+    /**
+     * Prepares a URL intent to start the activity.
+     * @param intent the intent to be modified
+     * @param url the URL to be used (may be null)
+     */
+    public Intent prepareUrlIntent(Intent intent, String url) {
+        return mTestCommon.prepareUrlIntent(intent, url);
+    }
+
+    /**
+     * Open an incognito tab by invoking the 'new incognito' menu item.
+     * Returns when receiving the 'PAGE_LOAD_FINISHED' notification.
+     *
+     * TODO(yolandyan): split this into the seperate test rule, this only applies to tabbed mode
+     */
+    public void newIncognitoTabFromMenu() throws InterruptedException {
+        mTestCommon.newIncognitoTabFromMenu();
+    }
+
+    /**
+     * New multiple incognito tabs by invoking the 'new incognito' menu item n times.
+     * @param n The number of tabs you want to create.
+     *
+     * TODO(yolandyan): split this into the seperate test rule, this only applies to tabbed mode
+     */
+    public void newIncognitoTabsFromMenu(int n) throws InterruptedException {
+        mTestCommon.newIncognitoTabsFromMenu(n);
+    }
+
+    /**
+     * @return The number of incognito tabs currently open.
+     */
+    public int incognitoTabsCount() {
+        return mTestCommon.incognitoTabsCount();
+    }
+
+    /**
+     * Looks up the Omnibox in the view hierarchy and types the specified
+     * text into it, requesting focus and using an inter-character delay of
+     * 200ms.
+     *
+     * @param oneCharAtATime Whether to type text one character at a time or all at once.
+     *
+     * @throws InterruptedException
+     *
+     * TODO(yolandyan): split this into the seperate test rule, this only applies to tabbed mode
+     */
+    public void typeInOmnibox(String text, boolean oneCharAtATime) throws InterruptedException {
+        mTestCommon.typeInOmnibox(text, oneCharAtATime);
+    }
+
+    /**
+     * Searches for a given suggestion after typing given text in the Omnibox.
+     *
+     * @param inputText Input text to type into the Omnibox.
+     * @param displayText Suggestion text expected to be found. Passing in null ignores this field.
+     * @param url URL expected to be found. Passing in null ignores this field.
+     * @param type Type of suggestion expected to be found. Passing in null ignores this field.
+     *
+     * @throws InterruptedException
+     */
+    public OmniboxSuggestion findOmniboxSuggestion(String inputText, String displayText, String url,
+            int type) throws InterruptedException {
+        return mTestCommon.findOmniboxSuggestion(inputText, displayText, url, type);
+    }
+
+    /**
+     * Returns the infobars being displayed by the current tab, or null if they don't exist.
+     */
+    public List<InfoBar> getInfoBars() {
+        return mTestCommon.getInfoBars();
+    }
+
+    /**
+     * Launches the preferences menu and starts the preferences activity named fragmentName.
+     * Returns the activity that was started.
+     */
+    public Preferences startPreferences(String fragmentName) {
+        return mTestCommon.startPreferences(fragmentName);
+    }
+
+    /**
+     * Executes the given snippet of JavaScript code within the current tab. Returns the result of
+     * its execution in JSON format.
+     * @throws InterruptedException
+     */
+    public String runJavaScriptCodeInCurrentTab(String code)
+            throws InterruptedException, TimeoutException {
+        return mTestCommon.runJavaScriptCodeInCurrentTab(code);
+    }
+
+    /**
+     * Waits till the ContentViewCore receives the expected page scale factor
+     * from the compositor and asserts that this happens.
+     */
+    public void assertWaitForPageScaleFactorMatch(float expectedScale) {
+        mTestCommon.assertWaitForPageScaleFactorMatch(expectedScale);
+    }
+
+    public String getName() {
+        return mCurrentTestName;
+    }
+
+    @Override
+    public String getTestName() {
+        return mCurrentTestName;
+    }
+
+    @Override
+    public Instrumentation getInstrumentation() {
+        return InstrumentationRegistry.getInstrumentation();
+    }
+
+    /**
+     * ActitivityTestRule already set initial touch mode in constructor.
+     */
+    @Override
+    public void setActivityInitialTouchMode(boolean touchMode) {}
+
+    @Override
+    public void setActivity(T chromeActivity) {
+        mSetActivity = chromeActivity;
+    }
+}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
index e063ca25..94e6f21 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
@@ -8,12 +8,15 @@
 
 import org.junit.runners.model.InitializationError;
 
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.BaseTestResult.PreTestHook;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.SkipCheck;
 import org.chromium.chrome.test.ChromeInstrumentationTestRunner.ChromeDisableIfSkipCheck;
 import org.chromium.chrome.test.ChromeInstrumentationTestRunner.ChromeRestrictionSkipCheck;
+import org.chromium.content.browser.test.ChildProcessAllocatorSettingsHook;
 
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -26,12 +29,18 @@
      * @throws InitializationError if the test class malformed
      */
     public ChromeJUnit4ClassRunner(final Class<?> klass) throws InitializationError {
-        super(klass, defaultSkipChecks(), null);
+        super(klass, defaultSkipChecks(), defaultPreTestHooks());
     }
 
     private static List<SkipCheck> defaultSkipChecks() {
-        return Arrays.asList(new SkipCheck[] {
+        return CollectionUtil.newArrayList(
                 new ChromeRestrictionSkipCheck(InstrumentationRegistry.getTargetContext()),
-                new ChromeDisableIfSkipCheck(InstrumentationRegistry.getTargetContext())});
+                new ChromeDisableIfSkipCheck(InstrumentationRegistry.getTargetContext()));
     }
+
+    private static List<PreTestHook> defaultPreTestHooks() {
+        return CollectionUtil.newArrayList(CommandLineFlags.getRegistrationHook(),
+            new ChildProcessAllocatorSettingsHook());
+    }
+
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
index 7329685..b7402e37 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
@@ -39,8 +39,7 @@
 
     // TODO(jbudorick): fix deprecation warning crbug.com/537347
     @SuppressWarnings("deprecation")
-    public static void setUp(Context context, boolean clearAppData)
-            throws Exception {
+    public static void setUp(Context context, boolean clearAppData) {
         if (clearAppData) {
             // Clear data and remove any tasks listed in Android's Overview menu between test runs.
             clearAppData(context);
@@ -158,7 +157,7 @@
 
     /** Finishes all tasks Chrome has listed in Android's Overview. */
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    public static void finishAllChromeTasks(final Context context) throws Exception {
+    public static void finishAllChromeTasks(final Context context) {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
diff --git a/chrome/test/base/extension_js_browser_test.cc b/chrome/test/base/extension_js_browser_test.cc
index 403b48c7..f1d3030 100644
--- a/chrome/test/base/extension_js_browser_test.cc
+++ b/chrome/test/base/extension_js_browser_test.cc
@@ -32,15 +32,16 @@
   EXPECT_TRUE(load_waiter_->browser_context());
   if (!load_waiter_->browser_context())
     return false;
-  ConstValueVector args;
-  args.push_back(new base::Value(test_fixture));
-  args.push_back(new base::Value(test_name));
+  std::vector<base::Value> args;
+  args.push_back(base::Value(test_fixture));
+  args.push_back(base::Value(test_name));
   std::vector<base::string16> scripts;
   if (!libs_loaded_) {
     BuildJavascriptLibraries(&scripts);
     libs_loaded_ = true;
   }
-  scripts.push_back(BuildRunTestJSCall(is_async, "RUN_TEST_F", args));
+  scripts.push_back(
+      BuildRunTestJSCall(is_async, "RUN_TEST_F", std::move(args)));
 
   base::string16 script_16 =
       base::JoinString(scripts, base::ASCIIToUTF16("\n"));
diff --git a/chrome/test/base/javascript_browser_test.cc b/chrome/test/base/javascript_browser_test.cc
index 3d762f2..c70778b 100644
--- a/chrome/test/base/javascript_browser_test.cc
+++ b/chrome/test/base/javascript_browser_test.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/test/base/javascript_browser_test.h"
 
+#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/chrome_paths.h"
@@ -104,17 +105,18 @@
 base::string16 JavaScriptBrowserTest::BuildRunTestJSCall(
     bool is_async,
     const std::string& function_name,
-    const ConstValueVector& test_func_args) {
-  ConstValueVector arguments;
-  base::Value* is_async_arg = new base::Value(is_async);
-  arguments.push_back(is_async_arg);
-  base::Value* function_name_arg = new base::Value(function_name);
-  arguments.push_back(function_name_arg);
-  base::ListValue* baked_argument_list = new base::ListValue();
-  ConstValueVector::const_iterator arguments_iterator;
-  for (auto* arg : test_func_args)
-    baked_argument_list->Append(arg->CreateDeepCopy());
-  arguments.push_back(baked_argument_list);
-  return content::WebUI::GetJavascriptCall(std::string("runTest"),
-                                           arguments.get());
+    std::vector<base::Value> test_func_args) {
+  std::vector<std::unique_ptr<base::Value>> arguments;
+  arguments.push_back(base::MakeUnique<base::Value>(is_async));
+  arguments.push_back(base::MakeUnique<base::Value>(function_name));
+  auto baked_argument_list = base::MakeUnique<base::ListValue>();
+  for (const auto& arg : test_func_args)
+    baked_argument_list->Append(arg.CreateDeepCopy());
+  arguments.push_back(std::move(baked_argument_list));
+
+  std::vector<const base::Value*> ptr_vector;
+  ptr_vector.reserve(arguments.size());
+  for (const auto& argument : arguments)
+    ptr_vector.push_back(argument.get());
+  return content::WebUI::GetJavascriptCall(std::string("runTest"), ptr_vector);
 }
diff --git a/chrome/test/base/javascript_browser_test.h b/chrome/test/base/javascript_browser_test.h
index 2299cff9..fead630 100644
--- a/chrome/test/base/javascript_browser_test.h
+++ b/chrome/test/base/javascript_browser_test.h
@@ -5,8 +5,9 @@
 #ifndef CHROME_TEST_BASE_JAVASCRIPT_BROWSER_TEST_H_
 #define CHROME_TEST_BASE_JAVASCRIPT_BROWSER_TEST_H_
 
+#include <vector>
+
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
 #include "base/strings/string16.h"
 #include "base/values.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -20,8 +21,6 @@
   static const base::FilePath::CharType kWebUILibraryJS[];
   static const base::FilePath::CharType kWebUITestFolder[];
 
-  typedef ScopedVector<const base::Value> ConstValueVector;
-
   // Add a custom helper JS library for your test.
   // If a relative path is specified, it'll be read
   // as relative to the test data dir.
@@ -45,7 +44,7 @@
   // |RunJavaScriptBrowserTestF| call.
   base::string16 BuildRunTestJSCall(bool is_async,
                                     const std::string& test_name,
-                                    const ConstValueVector& args);
+                                    std::vector<base::Value> args);
 
  private:
   // User added libraries.
diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc
index 01486f6..2313b2c 100644
--- a/chrome/test/base/web_ui_browser_test.cc
+++ b/chrome/test/base/web_ui_browser_test.cc
@@ -95,110 +95,111 @@
 }
 
 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) {
-  ConstValueVector empty_args;
-  return RunJavascriptFunction(function_name, empty_args);
+  std::vector<base::Value> empty_args;
+  return RunJavascriptFunction(function_name, std::move(empty_args));
 }
 
 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name,
-                                             base::Value* arg) {
-  ConstValueVector args;
-  args.push_back(arg);
-  return RunJavascriptFunction(function_name, args);
+                                             base::Value arg) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg));
+  return RunJavascriptFunction(function_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name,
-                                             base::Value* arg1,
-                                             base::Value* arg2) {
-  ConstValueVector args;
-  args.push_back(arg1);
-  args.push_back(arg2);
-  return RunJavascriptFunction(function_name, args);
+                                             base::Value arg1,
+                                             base::Value arg2) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg1));
+  args.push_back(std::move(arg2));
+  return RunJavascriptFunction(function_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptFunction(
     const std::string& function_name,
-    const ConstValueVector& function_arguments) {
-  return RunJavascriptUsingHandler(
-      function_name, function_arguments, false, false, NULL);
+    std::vector<base::Value> function_arguments) {
+  return RunJavascriptUsingHandler(function_name, std::move(function_arguments),
+                                   false, false, nullptr);
 }
 
 bool WebUIBrowserTest::RunJavascriptTestF(bool is_async,
                                           const std::string& test_fixture,
                                           const std::string& test_name) {
-  ConstValueVector args;
-  args.push_back(new base::Value(test_fixture));
-  args.push_back(new base::Value(test_name));
+  std::vector<base::Value> args;
+  args.push_back(base::Value(test_fixture));
+  args.push_back(base::Value(test_name));
 
   if (is_async)
-    return RunJavascriptAsyncTest("RUN_TEST_F", args);
+    return RunJavascriptAsyncTest("RUN_TEST_F", std::move(args));
   else
-    return RunJavascriptTest("RUN_TEST_F", args);
+    return RunJavascriptTest("RUN_TEST_F", std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptTest(const std::string& test_name) {
-  ConstValueVector empty_args;
-  return RunJavascriptTest(test_name, empty_args);
+  std::vector<base::Value> empty_args;
+  return RunJavascriptTest(test_name, std::move(empty_args));
 }
 
 bool WebUIBrowserTest::RunJavascriptTest(const std::string& test_name,
-                                         base::Value* arg) {
-  ConstValueVector args;
-  args.push_back(arg);
-  return RunJavascriptTest(test_name, args);
+                                         base::Value arg) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg));
+  return RunJavascriptTest(test_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptTest(const std::string& test_name,
-                                         base::Value* arg1,
-                                         base::Value* arg2) {
-  ConstValueVector args;
-  args.push_back(arg1);
-  args.push_back(arg2);
-  return RunJavascriptTest(test_name, args);
+                                         base::Value arg1,
+                                         base::Value arg2) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg1));
+  args.push_back(std::move(arg2));
+  return RunJavascriptTest(test_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptTest(
     const std::string& test_name,
-    const ConstValueVector& test_arguments) {
-  return RunJavascriptUsingHandler(
-      test_name, test_arguments, true, false, NULL);
+    std::vector<base::Value> test_arguments) {
+  return RunJavascriptUsingHandler(test_name, std::move(test_arguments), true,
+                                   false, nullptr);
 }
 
 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name) {
-  ConstValueVector empty_args;
-  return RunJavascriptAsyncTest(test_name, empty_args);
+  std::vector<base::Value> empty_args;
+  return RunJavascriptAsyncTest(test_name, std::move(empty_args));
 }
 
 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name,
-                                              base::Value* arg) {
-  ConstValueVector args;
-  args.push_back(arg);
-  return RunJavascriptAsyncTest(test_name, args);
+                                              base::Value arg) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg));
+  return RunJavascriptAsyncTest(test_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name,
-                                              base::Value* arg1,
-                                              base::Value* arg2) {
-  ConstValueVector args;
-  args.push_back(arg1);
-  args.push_back(arg2);
-  return RunJavascriptAsyncTest(test_name, args);
+                                              base::Value arg1,
+                                              base::Value arg2) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg1));
+  args.push_back(std::move(arg2));
+  return RunJavascriptAsyncTest(test_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name,
-                                              base::Value* arg1,
-                                              base::Value* arg2,
-                                              base::Value* arg3) {
-  ConstValueVector args;
-  args.push_back(arg1);
-  args.push_back(arg2);
-  args.push_back(arg3);
-  return RunJavascriptAsyncTest(test_name, args);
+                                              base::Value arg1,
+                                              base::Value arg2,
+                                              base::Value arg3) {
+  std::vector<base::Value> args;
+  args.push_back(std::move(arg1));
+  args.push_back(std::move(arg2));
+  args.push_back(std::move(arg3));
+  return RunJavascriptAsyncTest(test_name, std::move(args));
 }
 
 bool WebUIBrowserTest::RunJavascriptAsyncTest(
     const std::string& test_name,
-    const ConstValueVector& test_arguments) {
-  return RunJavascriptUsingHandler(test_name, test_arguments, true, true, NULL);
+    std::vector<base::Value> test_arguments) {
+  return RunJavascriptUsingHandler(test_name, std::move(test_arguments), true,
+                                   true, nullptr);
 }
 
 void WebUIBrowserTest::PreLoadJavascriptLibraries(
@@ -206,11 +207,11 @@
     const std::string& preload_test_name,
     RenderViewHost* preload_host) {
   ASSERT_FALSE(libraries_preloaded_);
-  ConstValueVector args;
-  args.push_back(new base::Value(preload_test_fixture));
-  args.push_back(new base::Value(preload_test_name));
-  RunJavascriptUsingHandler(
-      "preloadJavascriptLibraries", args, false, false, preload_host);
+  std::vector<base::Value> args;
+  args.push_back(base::Value(preload_test_fixture));
+  args.push_back(base::Value(preload_test_name));
+  RunJavascriptUsingHandler("preloadJavascriptLibraries", std::move(args),
+                            false, false, preload_host);
   libraries_preloaded_ = true;
 }
 
@@ -240,7 +241,7 @@
       : browser_test_(browser_test),
         preload_test_fixture_(preload_test_fixture),
         preload_test_name_(preload_test_name),
-        preview_dialog_(NULL),
+        preview_dialog_(nullptr),
         message_loop_runner_(new content::MessageLoopRunner) {}
 
   void Wait() {
@@ -258,7 +259,7 @@
                                                       preload_test_fixture_,
                                                       preload_test_name_));
     message_loop_runner_->Quit();
-    return NULL;
+    return nullptr;
   }
 
   WebUIBrowserTest* browser_test_;
@@ -301,8 +302,7 @@
 WebUIBrowserTest::WebUIBrowserTest()
     : test_handler_(new WebUITestHandler()),
       libraries_preloaded_(false),
-      override_selected_web_ui_(NULL) {
-}
+      override_selected_web_ui_(nullptr) {}
 
 void WebUIBrowserTest::set_preload_test_fixture(
     const std::string& preload_test_fixture) {
@@ -391,7 +391,7 @@
 }
 
 void WebUIBrowserTest::TearDownOnMainThread() {
-  logging::SetLogMessageHandler(NULL);
+  logging::SetLogMessageHandler(nullptr);
 
   test_factory_->RemoveFactoryOverride(GURL(kDummyURL).host());
   content::WebUIControllerFactory::UnregisterFactoryForTesting(
@@ -410,12 +410,12 @@
 }
 
 WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() {
-  return NULL;
+  return nullptr;
 }
 
 bool WebUIBrowserTest::RunJavascriptUsingHandler(
     const std::string& function_name,
-    const ConstValueVector& function_arguments,
+    std::vector<base::Value> function_arguments,
     bool is_test,
     bool is_async,
     RenderViewHost* preload_host) {
@@ -435,11 +435,14 @@
   if (!function_name.empty()) {
     base::string16 called_function;
     if (is_test) {
-      called_function =
-          BuildRunTestJSCall(is_async, function_name, function_arguments);
+      called_function = BuildRunTestJSCall(is_async, function_name,
+                                           std::move(function_arguments));
     } else {
-      called_function = content::WebUI::GetJavascriptCall(
-          function_name, function_arguments.get());
+      std::vector<const base::Value*> ptr_vector(function_arguments.size());
+      for (size_t i = 0; i < function_arguments.size(); ++i)
+        ptr_vector[i] = &function_arguments[i];
+      called_function =
+          content::WebUI::GetJavascriptCall(function_name, ptr_vector);
     }
     content.append(called_function);
   }
@@ -477,7 +480,7 @@
       override_selected_web_ui_
           ? override_selected_web_ui_
           : browser()->tab_strip_model()->GetActiveWebContents()->GetWebUI();
-  ASSERT_TRUE(web_ui_instance != NULL);
+  ASSERT_TRUE(web_ui_instance != nullptr);
 
   test_handler_->set_web_ui(web_ui_instance);
   test_handler_->RegisterMessages();
diff --git a/chrome/test/base/web_ui_browser_test.h b/chrome/test/base/web_ui_browser_test.h
index b642fd0..d3524e0 100644
--- a/chrome/test/base/web_ui_browser_test.h
+++ b/chrome/test/base/web_ui_browser_test.h
@@ -39,13 +39,12 @@
   // Note that calls to functions in test_api.js are not supported.
   // Takes ownership of Value* arguments.
   bool RunJavascriptFunction(const std::string& function_name);
+  bool RunJavascriptFunction(const std::string& function_name, base::Value arg);
   bool RunJavascriptFunction(const std::string& function_name,
-                             base::Value* arg);
+                             base::Value arg1,
+                             base::Value arg2);
   bool RunJavascriptFunction(const std::string& function_name,
-                             base::Value* arg1,
-                             base::Value* arg2);
-  bool RunJavascriptFunction(const std::string& function_name,
-                             const ConstValueVector& function_arguments);
+                             std::vector<base::Value> function_arguments);
 
   // Runs a test fixture that may include calls to functions in test_api.js.
   bool RunJavascriptTestF(bool is_async,
@@ -55,26 +54,26 @@
   // Runs a test that may include calls to functions in test_api.js.
   // Takes ownership of Value* arguments.
   bool RunJavascriptTest(const std::string& test_name);
-  bool RunJavascriptTest(const std::string& test_name, base::Value* arg);
+  bool RunJavascriptTest(const std::string& test_name, base::Value arg);
   bool RunJavascriptTest(const std::string& test_name,
-                         base::Value* arg1,
-                         base::Value* arg2);
+                         base::Value arg1,
+                         base::Value arg2);
   bool RunJavascriptTest(const std::string& test_name,
-                         const ConstValueVector& test_arguments);
+                         std::vector<base::Value> test_arguments);
 
   // Runs a test that may include calls to functions in test_api.js, and waits
   // for call to testDone().  Takes ownership of Value* arguments.
   bool RunJavascriptAsyncTest(const std::string& test_name);
-  bool RunJavascriptAsyncTest(const std::string& test_name, base::Value* arg);
+  bool RunJavascriptAsyncTest(const std::string& test_name, base::Value arg);
   bool RunJavascriptAsyncTest(const std::string& test_name,
-                              base::Value* arg1,
-                              base::Value* arg2);
+                              base::Value arg1,
+                              base::Value arg2);
   bool RunJavascriptAsyncTest(const std::string& test_name,
-                              base::Value* arg1,
-                              base::Value* arg2,
-                              base::Value* arg3);
+                              base::Value arg1,
+                              base::Value arg2,
+                              base::Value arg3);
   bool RunJavascriptAsyncTest(const std::string& test_name,
-                              const ConstValueVector& test_arguments);
+                              std::vector<base::Value> test_arguments);
 
   // Sends message through |preload_host| to preload javascript libraries and
   // sets the |libraries_preloaded| flag to prevent re-loading at next
@@ -128,7 +127,7 @@
   // the RenderView for evaluation at the appropriate time before the onload
   // call is made. Passes |is_async| along to runTest wrapper.
   bool RunJavascriptUsingHandler(const std::string& function_name,
-                                 const ConstValueVector& function_arguments,
+                                 std::vector<base::Value> function_arguments,
                                  bool is_test,
                                  bool is_async,
                                  content::RenderViewHost* preload_host);
diff --git a/chrome/test/base/web_ui_browser_test_browsertest.cc b/chrome/test/base/web_ui_browser_test_browsertest.cc
index 0f8906e..a1b3728 100644
--- a/chrome/test/base/web_ui_browser_test_browsertest.cc
+++ b/chrome/test/base/web_ui_browser_test_browsertest.cc
@@ -90,12 +90,12 @@
 
   // Starts a failing test.
   void RunTestFailsAssert() {
-    RunJavascriptFunction("runAsync", new base::Value("testFailsAssert"));
+    RunJavascriptFunction("runAsync", base::Value("testFailsAssert"));
   }
 
   // Starts a passing test.
   void RunTestPasses() {
-    RunJavascriptFunction("runAsync", new base::Value("testPasses"));
+    RunJavascriptFunction("runAsync", base::Value("testPasses"));
   }
 
  protected:
@@ -165,8 +165,8 @@
 // message). (Async version).
 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncFailsAssert) {
   EXPECT_CALL(message_handler_, HandleTestFails(::testing::_));
-  ASSERT_FALSE(RunJavascriptAsyncTest("startAsyncTest",
-                                      new base::Value("testFailsAssert")));
+  ASSERT_FALSE(
+      RunJavascriptAsyncTest("startAsyncTest", base::Value("testFailsAssert")));
 }
 
 // Test that expectations continue the function, but fail the test.
@@ -174,8 +174,8 @@
   ::testing::InSequence s;
   EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_));
   EXPECT_CALL(message_handler_, HandleTestFails(::testing::_));
-  ASSERT_FALSE(RunJavascriptAsyncTest("startAsyncTest",
-                                      new base::Value("testFailsExpect")));
+  ASSERT_FALSE(
+      RunJavascriptAsyncTest("startAsyncTest", base::Value("testFailsExpect")));
 }
 
 // Test that test continues and passes. (Sync version).
@@ -192,7 +192,7 @@
       .WillOnce(::testing::InvokeWithoutArgs(
           this, &WebUIBrowserAsyncTest::TestDone));
   ASSERT_TRUE(
-      RunJavascriptAsyncTest("startAsyncTest", new base::Value("testPasses")));
+      RunJavascriptAsyncTest("startAsyncTest", base::Value("testPasses")));
 }
 
 // Test that two tests pass.
@@ -207,7 +207,7 @@
       .WillOnce(::testing::InvokeWithoutArgs(
           this, &WebUIBrowserAsyncTest::TestDone));
   ASSERT_TRUE(
-      RunJavascriptAsyncTest("startAsyncTest", new base::Value("testPasses")));
+      RunJavascriptAsyncTest("startAsyncTest", base::Value("testPasses")));
 }
 
 // Test that first test passes; second fails.
@@ -219,7 +219,7 @@
           this, &WebUIBrowserAsyncTest::RunTestFailsAssert));
   EXPECT_CALL(message_handler_, HandleTestFails(::testing::_));
   ASSERT_FALSE(
-      RunJavascriptAsyncTest("startAsyncTest", new base::Value("testPasses")));
+      RunJavascriptAsyncTest("startAsyncTest", base::Value("testPasses")));
 }
 
 // Test that testDone() with failure first then sync pass still fails.
@@ -231,7 +231,7 @@
   // Call runAsync directly instead of deferring through startAsyncTest. It will
   // call testDone() on failure, then return.
   ASSERT_FALSE(RunJavascriptAsyncTest(
-      "runAsync", new base::Value("testAsyncDoneFailFirstSyncPass")));
+      "runAsync", base::Value("testAsyncDoneFailFirstSyncPass")));
 }
 
 // Test that calling testDone during RunJavascriptAsyncTest still completes
diff --git a/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.html b/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.html
deleted file mode 100644
index cc4539f..0000000
--- a/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!--
- * 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.
--->
-<script src="common.js"></script>
-<script src="hit_test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js b/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js
deleted file mode 100644
index 9e7f7a69..0000000
--- a/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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.
-
-var allTests = [
-  function testHitTestInDesktop() {
-    var url = 'data:text/html,<!doctype html>' +
-        encodeURI('<button>Click Me</button>');
-    chrome.automation.getDesktop(function(desktop) {
-      chrome.tabs.create({url: url});
-
-      desktop.addEventListener('loadComplete', function(event) {
-        if (event.target.url.indexOf('data:') >= 0) {
-          var button = desktop.find({ attributes: { name: 'Click Me' } });
-          if (button) {
-            button.addEventListener(EventType.ALERT, function() {
-              chrome.test.succeed();
-            }, true);
-            var cx = Math.floor(
-                button.location.left + button.location.width / 2);
-            var cy = Math.floor(
-                button.location.top + button.location.height / 2);
-            desktop.hitTest(cx, cy, EventType.ALERT);
-          }
-        }
-      }, false);
-    });
-  },
-];
-
-chrome.test.runTests(allTests);
diff --git a/chrome/test/data/webui/bluetooth_internals_browsertest.js b/chrome/test/data/webui/bluetooth_internals_browsertest.js
index cef7a06..a7ab6ad 100644
--- a/chrome/test/data/webui/bluetooth_internals_browsertest.js
+++ b/chrome/test/data/webui/bluetooth_internals_browsertest.js
@@ -307,15 +307,7 @@
   },
 };
 
-// Flaky on Debug and ASAN. See crbug.com/707530
-GEN('#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER)');
-GEN('#define MAYBE_Startup_BluetoothInternals ' +
-    'DISABLED_Startup_BluetoothInternals');
-GEN('#else');
-GEN('#define MAYBE_Startup_BluetoothInternals Startup_BluetoothInternals');
-GEN('#endif');
-
-TEST_F('BluetoothInternalsTest', 'MAYBE_Startup_BluetoothInternals',
+TEST_F('BluetoothInternalsTest', 'Startup_BluetoothInternals',
     function() {
   /** @const */ var PageManager = cr.ui.pageManager.PageManager;
 
@@ -677,7 +669,7 @@
       whenSnackbarShows(snackbar3).then(next);
       snackbar3.addEventListener('dismissed', next);
 
-      whenSnackbarShows(snackbar1).then(function() {
+      return whenSnackbarShows(snackbar1).then(function() {
         return snackbar.Snackbar.dismiss(true);
       }).then(function() {
         expectEquals(0, snackbar.Snackbar.queue_.length);
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 092b6b9..bd9d622 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1090,12 +1090,13 @@
     'test_browser_proxy.js',
     'fake_language_settings_private.js',
     'fake_settings_private.js',
+    'fake_input_method_private.js',
     'languages_tests.js',
   ]),
 };
 
 // Flaky on Win and Linux, see http://crbug/692356.
-TEST_F('CrSettingsLanguagesTest', 'DISABLED_Languages', function() {
+TEST_F('CrSettingsLanguagesTest', 'Languages', function() {
   mocha.run();
 });
 
diff --git a/chrome/test/data/webui/settings/fake_input_method_private.js b/chrome/test/data/webui/settings/fake_input_method_private.js
new file mode 100644
index 0000000..98ba91e
--- /dev/null
+++ b/chrome/test/data/webui/settings/fake_input_method_private.js
@@ -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.
+
+/**
+ * @fileoverview Fake implementation of chrome.inputMethodPrivate
+ * for testing.
+ */
+cr.define('settings', function() {
+  /**
+   * Fake of the chrome.inputMethodsPrivate API. Only methods that are called
+   * during testing have been implemented.
+   *
+   * @constructor
+   * @implements {InputMethodPrivate}
+   */
+  function FakeInputMethodPrivate() {}
+
+  FakeInputMethodPrivate.prototype = {
+    getCurrentInputMethod: function(callback) {
+      callback(null);
+    },
+
+    get onChanged() {
+      return {
+        addListener: function() {
+          // Nothing to do here.
+        },
+        removeListener: function() {
+          // Nothing to do here.
+        },
+      };
+    },
+  };
+
+  return {FakeInputMethodPrivate: FakeInputMethodPrivate};
+});
diff --git a/chrome/test/data/webui/settings/languages_tests.js b/chrome/test/data/webui/settings/languages_tests.js
index 7d6f583..fcdd0e9 100644
--- a/chrome/test/data/webui/settings/languages_tests.js
+++ b/chrome/test/data/webui/settings/languages_tests.js
@@ -4,6 +4,48 @@
 
 cr.define('settings-languages', function() {
   /**
+   * @constructor
+   * @implements {settings.LanguagesBrowserProxy}
+   * @extends {settings.TestBrowserProxy}
+   */
+  var TestLanguagesBrowserProxy = function() {
+    var methodNames = [];
+    if (cr.isChromeOS || cr.isWindows)
+      methodNames.push('getProspectiveUILanguage');
+
+    settings.TestBrowserProxy.call(this, methodNames);
+
+    /** @private {!LanguageSettingsPrivate} */
+    this.languageSettingsPrivate_ = new settings.FakeLanguageSettingsPrivate();
+
+    /** @private {!InputMethodPrivate} */
+    this.inputMethodPrivate_ = new settings.FakeInputMethodPrivate();
+  };
+
+  TestLanguagesBrowserProxy.prototype = {
+    __proto__: settings.TestBrowserProxy.prototype,
+
+    /** @override */
+    getLanguageSettingsPrivate: function() {
+      return this.languageSettingsPrivate_;
+    },
+
+    /** @override */
+    getInputMethodPrivate: function() {
+      return this.inputMethodPrivate_;
+    },
+  };
+
+  if (cr.isChromeOS || cr.isWindows) {
+    /** @override */
+    TestLanguagesBrowserProxy.prototype.getProspectiveUILanguage =
+        function() {
+      this.methodCalled('getProspectiveUILanguage');
+      return Promise.resolve('en-US');
+    };
+  }
+
+  /**
    * Data-binds two Polymer properties using the property-changed events and
    * set/notifyPath API. Useful for testing components which would normally be
    * used together.
@@ -74,8 +116,10 @@
       }
     }
 
+    /** @type {?settings.LanguagesBrowserProxy} */
+    var browserProxy = null;
+
     var languageHelper;
-    var languageSettingsPrivate;
 
     suiteSetup(function() {
       CrSettingsPrefs.deferInitialization = true;
@@ -88,17 +132,13 @@
       settingsPrefs.initialize(settingsPrivate);
       document.body.appendChild(settingsPrefs);
 
-      languageSettingsPrivate = new settings.FakeLanguageSettingsPrivate();
-      languageSettingsPrivate.setSettingsPrefs(settingsPrefs);
-      settings.languageSettingsPrivateApiForTest = languageSettingsPrivate;
+      // Setup test browser proxy.
+      browserProxy = new TestLanguagesBrowserProxy();
+      settings.LanguagesBrowserProxyImpl.instance_ = browserProxy;
 
-      var getProspectiveUILanguageCalled = false;
-      registerMessageCallback('getProspectiveUILanguage', null,
-          function(callbackId) {
-            assertFalse(getProspectiveUILanguageCalled);
-            getProspectiveUILanguageCalled = true;
-            cr.webUIResponse(callbackId, true, 'en-US');
-          });
+      // Setup fake languageSettingsPrivate API.
+      var languageSettingsPrivate = browserProxy.getLanguageSettingsPrivate();
+      languageSettingsPrivate.setSettingsPrefs(settingsPrefs);
 
       languageHelper = document.createElement('settings-languages');
 
@@ -107,12 +147,13 @@
 
       document.body.appendChild(languageHelper);
       return languageHelper.whenReady().then(function() {
-        assertEquals(
-            cr.isChromeOS || cr.isWindows, getProspectiveUILanguageCalled);
+        if (cr.isChromeOS || cr.isWindows)
+          return browserProxy.whenCalled('getProspectiveUILanguage');
       });
     });
 
     test('languages model', function() {
+      var languageSettingsPrivate = browserProxy.getLanguageSettingsPrivate();
       for (var i = 0; i < languageSettingsPrivate.languages.length;
            i++) {
         assertEquals(languageSettingsPrivate.languages[i].code,
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 100c026a..5e40627db 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -1304,10 +1304,12 @@
   for (size_t i = 0; i < nodes.size(); ++i) {
     AudioDevice device(nodes[i]);
     audio_devices_[device.id] = device;
-    if (!has_alternative_input_ &&
-        device.is_input &&
+    if (!has_alternative_input_ && device.is_input &&
         device.type != AUDIO_TYPE_INTERNAL_MIC &&
-        device.type != AUDIO_TYPE_KEYBOARD_MIC) {
+        device.type != AUDIO_TYPE_KEYBOARD_MIC &&
+        device.type != AUDIO_TYPE_HOTWORD &&
+        device.type != AUDIO_TYPE_POST_MIX_LOOPBACK &&
+        device.type != AUDIO_TYPE_POST_DSP_LOOPBACK) {
       has_alternative_input_ = true;
     } else if (!has_alternative_output_ &&
                !device.is_input &&
diff --git a/chromeos/components/tether/initializer.cc b/chromeos/components/tether/initializer.cc
index 9d12a93..809231fe 100644
--- a/chromeos/components/tether/initializer.cc
+++ b/chromeos/components/tether/initializer.cc
@@ -51,8 +51,8 @@
     ProfileOAuth2TokenService* token_service,
     NetworkStateHandler* network_state_handler,
     NetworkConnect* network_connect) {
-  if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
-    PA_LOG(WARNING) << "Bluetooth is unavailable on this device; cannot "
+  if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
+    PA_LOG(WARNING) << "Bluetooth is not supported on this device; cannot "
                     << "initialize tether feature.";
     return;
   }
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.cc b/components/arc/bluetooth/arc_bluetooth_bridge.cc
index 97bca58..b63042df 100644
--- a/components/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -251,12 +251,12 @@
 
 ArcBluetoothBridge::ArcBluetoothBridge(ArcBridgeService* bridge_service)
     : ArcService(bridge_service), binding_(this), weak_factory_(this) {
-  if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (BluetoothAdapterFactory::IsBluetoothSupported()) {
     VLOG(1) << "Registering bluetooth adapter.";
     BluetoothAdapterFactory::GetAdapter(base::Bind(
         &ArcBluetoothBridge::OnAdapterInitialized, weak_factory_.GetWeakPtr()));
   } else {
-    VLOG(1) << "No bluetooth adapter available.";
+    VLOG(1) << "Bluetooth not supported.";
   }
   arc_bridge_service()->bluetooth()->AddObserver(this);
 }
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index f746de2..ca0aba2 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -158,6 +158,10 @@
 // associated with window.
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasBlendingKey, false);
 
+// A property key containing a boolean set to true whether the current
+// OnWindowActivated invocation should be ignored.
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIgnoreWindowActivated, false);
+
 wl_resource* GetSurfaceResource(Surface* surface) {
   return surface->GetProperty(kSurfaceResourceKey);
 }
@@ -1926,7 +1930,14 @@
 void remote_surface_activate(wl_client* client,
                              wl_resource* resource,
                              uint32_t serial) {
+  ShellSurface* shell_surface = GetUserDataAs<ShellSurface>(resource);
+  aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+
+  // Activation on Aura is synchronous, so activation callbacks will be called
+  // before the flag is reset.
+  window->SetProperty(kIgnoreWindowActivated, true);
   GetUserDataAs<ShellSurface>(resource)->Activate();
+  window->ClearProperty(kIgnoreWindowActivated);
 }
 
 void remote_surface_maximize(wl_client* client, wl_resource* resource) {
@@ -2121,6 +2132,13 @@
   // Overridden from WMHelper::ActivationObserver:
   void OnWindowActivated(aura::Window* gained_active,
                          aura::Window* lost_active) override {
+    // If the origin of activation is Wayland client, then assume it's been
+    // already activated on the client side, so do not notify about the
+    // activation. It means that zcr_remote_shell_v1_send_activated is used
+    // only to notify about activations originating in Aura.
+    if (gained_active && gained_active->GetProperty(kIgnoreWindowActivated))
+      return;
+
     SendActivated(gained_active, lost_active);
   }
 
diff --git a/components/pairing/bluetooth_controller_pairing_controller.cc b/components/pairing/bluetooth_controller_pairing_controller.cc
index 5ef30c9c..b8c9d0a 100644
--- a/components/pairing/bluetooth_controller_pairing_controller.cc
+++ b/components/pairing/bluetooth_controller_pairing_controller.cc
@@ -241,7 +241,7 @@
          current_stage_ == STAGE_DEVICE_NOT_FOUND ||
          current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
          current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
-  if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     ChangeStage(STAGE_INITIALIZATION_ERROR);
     return;
   }
diff --git a/components/pairing/bluetooth_host_pairing_controller.cc b/components/pairing/bluetooth_host_pairing_controller.cc
index c8c534f..8b0b201 100644
--- a/components/pairing/bluetooth_host_pairing_controller.cc
+++ b/components/pairing/bluetooth_host_pairing_controller.cc
@@ -471,9 +471,9 @@
 
 void BluetoothHostPairingController::StartPairing() {
   DCHECK_EQ(current_stage_, STAGE_NONE);
-  bool bluetooth_available =
-      device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
-  if (!bluetooth_available) {
+  const bool bluetooth_supported =
+      device::BluetoothAdapterFactory::IsBluetoothSupported();
+  if (!bluetooth_supported) {
     ChangeStage(STAGE_INITIALIZATION_ERROR);
     return;
   }
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
index 3ea4363..efa17fd 100644
--- a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
@@ -73,7 +73,7 @@
 void BluetoothLowEnergyConnectionFinder::Find(
     const cryptauth::ConnectionFinder::ConnectionCallback&
         connection_callback) {
-  if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     PA_LOG(WARNING) << "Bluetooth is unsupported on this platform. Aborting.";
     return;
   }
diff --git a/components/proximity_auth/bluetooth_connection.cc b/components/proximity_auth/bluetooth_connection.cc
index 563446d..d3798d8 100644
--- a/components/proximity_auth/bluetooth_connection.cc
+++ b/components/proximity_auth/bluetooth_connection.cc
@@ -42,7 +42,7 @@
     return;
   }
 
-  if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     PA_LOG(WARNING)
         << "Connection failed: Bluetooth is unsupported on this platform.";
     return;
diff --git a/components/proximity_auth/bluetooth_connection_finder.cc b/components/proximity_auth/bluetooth_connection_finder.cc
index fd48587..e0a0e84c 100644
--- a/components/proximity_auth/bluetooth_connection_finder.cc
+++ b/components/proximity_auth/bluetooth_connection_finder.cc
@@ -37,7 +37,7 @@
 void BluetoothConnectionFinder::Find(
     const cryptauth::ConnectionFinder::ConnectionCallback&
         connection_callback) {
-  if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     PA_LOG(WARNING) << "Bluetooth is unsupported on this platform. Aborting.";
     return;
   }
diff --git a/components/proximity_auth/bluetooth_connection_finder_unittest.cc b/components/proximity_auth/bluetooth_connection_finder_unittest.cc
index 56488bd..1283ccad 100644
--- a/components/proximity_auth/bluetooth_connection_finder_unittest.cc
+++ b/components/proximity_auth/bluetooth_connection_finder_unittest.cc
@@ -201,7 +201,7 @@
   // Some platforms do not support Bluetooth. This test is only meaningful on
   // those platforms.
   adapter_ = NULL;
-  if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
+  if (device::BluetoothAdapterFactory::IsBluetoothSupported())
     return;
 
   // The StrictMock will verify that no connection is created.
diff --git a/components/proximity_auth/bluetooth_connection_unittest.cc b/components/proximity_auth/bluetooth_connection_unittest.cc
index dd57691..56a7ea0 100644
--- a/components/proximity_auth/bluetooth_connection_unittest.cc
+++ b/components/proximity_auth/bluetooth_connection_unittest.cc
@@ -205,7 +205,7 @@
   // Some platforms do not support Bluetooth. This test is only meaningful on
   // those platforms.
   adapter_ = NULL;
-  if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
+  if (device::BluetoothAdapterFactory::IsBluetoothSupported())
     return;
 
   StrictMock<MockBluetoothConnection> connection;
diff --git a/components/proximity_auth/proximity_monitor_impl.cc b/components/proximity_auth/proximity_monitor_impl.cc
index dce7cb0..02422ca 100644
--- a/components/proximity_auth/proximity_monitor_impl.cc
+++ b/components/proximity_auth/proximity_monitor_impl.cc
@@ -42,7 +42,7 @@
       clock_(std::move(clock)),
       polling_weak_ptr_factory_(this),
       weak_ptr_factory_(this) {
-  if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     device::BluetoothAdapterFactory::GetAdapter(
         base::Bind(&ProximityMonitorImpl::OnAdapterInitialized,
                    weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/proximity_auth/unlock_manager_impl.cc b/components/proximity_auth/unlock_manager_impl.cc
index ba01d4c..19babab 100644
--- a/components/proximity_auth/unlock_manager_impl.cc
+++ b/components/proximity_auth/unlock_manager_impl.cc
@@ -102,7 +102,7 @@
 #endif  // defined(OS_CHROMEOS)
   SetWakingUpState(true);
 
-  if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     device::BluetoothAdapterFactory::GetAdapter(
         base::Bind(&UnlockManagerImpl::OnBluetoothAdapterInitialized,
                    weak_ptr_factory_.GetWeakPtr()));
diff --git a/content/browser/android/content_startup_flags.cc b/content/browser/android/content_startup_flags.cc
index b7bc16df..4d4d4e7 100644
--- a/content/browser/android/content_startup_flags.cc
+++ b/content/browser/android/content_startup_flags.cc
@@ -14,7 +14,6 @@
 #include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "ui/base/ui_base_switches.h"
-#include "ui/native_theme/native_theme_switches.h"
 
 namespace content {
 
@@ -38,7 +37,6 @@
 
   parsed_command_line->AppendSwitch(switches::kEnablePinch);
   parsed_command_line->AppendSwitch(switches::kEnableViewport);
-  parsed_command_line->AppendSwitch(switches::kEnableOverlayScrollbar);
   parsed_command_line->AppendSwitch(switches::kValidateInputEventStream);
 
   if (base::android::BuildInfo::GetInstance()->sdk_int() >=
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index d0271781..7d5481d 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -295,7 +295,7 @@
   RecordRequestDeviceOptions(options);
 
   if (!GetAdapter()) {
-    if (BluetoothAdapterFactoryWrapper::Get().IsLowEnergyAvailable()) {
+    if (BluetoothAdapterFactoryWrapper::Get().IsLowEnergySupported()) {
       BluetoothAdapterFactoryWrapper::Get().AcquireAdapter(
           this, base::Bind(&WebBluetoothServiceImpl::RequestDeviceImpl,
                            weak_ptr_factory_.GetWeakPtr(),
diff --git a/content/browser/devtools/protocol/schema_handler.cc b/content/browser/devtools/protocol/schema_handler.cc
index f4f862c..6cf5b21d 100644
--- a/content/browser/devtools/protocol/schema_handler.cc
+++ b/content/browser/devtools/protocol/schema_handler.cc
@@ -22,37 +22,14 @@
     std::unique_ptr<protocol::Array<Schema::Domain>>* domains) {
   // TODO(kozyatisnkiy): get this from the target instead of hardcoding a list.
   static const char kVersion[] = "1.2";
-  static const char* kDomains[] = {"Inspector",
-                                   "Memory",
-                                   "Page",
-                                   "Emulation",
-                                   "Security",
-                                   "Network",
-                                   "Database",
-                                   "IndexedDB",
-                                   "CacheStorage",
-                                   "DOMStorage",
-                                   "CSS",
-                                   "ApplicationCache",
-                                   "DOM",
-                                   "IO",
-                                   "DOMDebugger",
-                                   "ServiceWorker",
-                                   "Input",
-                                   "LayerTree",
-                                   "DeviceOrientation",
-                                   "Tracing",
-                                   "Animation",
-                                   "Accessibility",
-                                   "Storage",
-                                   "Log",
-                                   "Runtime",
-                                   "Debugger",
-                                   "Profiler",
-                                   "HeapProfiler",
-                                   "Schema",
-                                   "Target",
-                                   "Overlay"};
+  static const char* kDomains[] = {
+    "Inspector", "Memory", "Page", "Rendering", "Emulation", "Security",
+    "Network", "Database", "IndexedDB", "CacheStorage", "DOMStorage", "CSS",
+    "ApplicationCache", "DOM", "IO", "DOMDebugger", "ServiceWorker",
+    "Input", "LayerTree", "DeviceOrientation", "Tracing", "Animation",
+    "Accessibility", "Storage", "Log", "Runtime", "Debugger",
+    "Profiler", "HeapProfiler", "Schema", "Target"
+  };
   *domains = protocol::Array<Schema::Domain>::create();
   for (size_t i = 0; i < arraysize(kDomains); ++i) {
     (*domains)->addItem(Schema::Domain::Create()
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index e779da3..8bb4f2f 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -198,7 +198,7 @@
 #include "ui/gfx/switches.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gpu_switching_manager.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 #if defined(OS_ANDROID)
 #include "content/public/browser/android/java_interfaces.h"
@@ -1714,7 +1714,6 @@
     switches::kDisableLogging,
     switches::kDisableMediaSuspend,
     switches::kDisableNotifications,
-    switches::kDisableOverlayScrollbar,
     switches::kDisablePepper3DImageChromium,
     switches::kDisablePermissionsAPI,
     switches::kDisablePresentationAPI,
@@ -1753,7 +1752,6 @@
     switches::kEnableLogging,
     switches::kEnableNetworkInformation,
     switches::kEnableNetworkService,
-    switches::kEnableOverlayScrollbar,
     switches::kEnableNewVp9CodecString,
     switches::kEnablePinch,
     switches::kEnablePluginPlaceholderTesting,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 53a28b21..ba2cd466 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -91,7 +91,7 @@
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 #include "url/url_constants.h"
 
 #if defined(OS_WIN)
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 372a996..7e7f4d21 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
@@ -87,7 +88,7 @@
 #include "ui/events/event_utils.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/latency/latency_info.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 #if defined(USE_AURA)
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
@@ -619,14 +620,15 @@
 void SitePerProcessBrowserTest::SetUpCommandLine(
     base::CommandLine* command_line) {
   IsolateAllSitesForTesting(command_line);
+}
+
+void SitePerProcessBrowserTest::SetUpOnMainThread() {
 #if !defined(OS_ANDROID)
   // TODO(bokan): Needed for scrollability check in
   // FrameOwnerPropertiesPropagationScrolling. crbug.com/662196.
-  command_line->AppendSwitch(switches::kDisableOverlayScrollbar);
+  feature_list_.InitAndDisableFeature(features::kOverlayScrollbar);
 #endif
-};
 
-void SitePerProcessBrowserTest::SetUpOnMainThread() {
   host_resolver()->AddRule("*", "127.0.0.1");
   SetupCrossSiteRedirector(embedded_test_server());
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/content/browser/site_per_process_browsertest.h b/content/browser/site_per_process_browsertest.h
index fe8b84b0..b37d7341 100644
--- a/content/browser/site_per_process_browsertest.h
+++ b/content/browser/site_per_process_browsertest.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/shell/browser/shell.h"
@@ -34,6 +35,7 @@
 
  private:
   FrameTreeVisualizer visualizer_;
+  base::test::ScopedFeatureList feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(SitePerProcessBrowserTest);
 };
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index d0a3c95..6bb73b4 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -18,7 +18,7 @@
 #include "services/device/public/cpp/device_features.h"
 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
 #include "ui/gl/gl_switches.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 using blink::WebRuntimeFeatures;
 
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 9ada1963..6b637c3 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -67,7 +67,7 @@
 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
 #include "third_party/WebKit/public/web/WebSelection.h"
 #include "ui/gl/gl_switches.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 #include "ui/native_theme/overlay_scrollbar_constants_aura.h"
 
 namespace base {
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 6f4c28cc..8b2ded4 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -86,7 +86,7 @@
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/range/range.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index e18a62f..c809245 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -459,21 +459,6 @@
         ['mac', ('nvidia', 0xfe9)], bug=635081)
 
     # Linux failures
-    self.Flaky('conformance/textures/video/' +
-               'tex-2d-rgba-rgba-unsigned_byte.html',
-               ['linux', 'no_passthrough'], bug=627525)
-    self.Flaky('conformance/textures/video/' +
-               'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html',
-               ['linux', 'no_passthrough'], bug=627525)
-    self.Flaky('conformance/textures/video/' +
-               'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html',
-               ['linux', 'no_passthrough'], bug=627525)
-    self.Flaky('conformance/textures/video/' +
-               'tex-2d-rgb-rgb-unsigned_byte.html',
-               ['linux', 'no_passthrough'], bug=627525)
-    self.Flaky('conformance/textures/video/' +
-               'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
-               ['linux', 'no_passthrough'], bug=627525)
     self.Fail('conformance/extensions/webgl-compressed-texture-astc.html',
         ['linux', 'intel'], bug=680675)
 
diff --git a/device/bluetooth/adapter_factory.cc b/device/bluetooth/adapter_factory.cc
index 9eabd2d..b214d21 100644
--- a/device/bluetooth/adapter_factory.cc
+++ b/device/bluetooth/adapter_factory.cc
@@ -22,7 +22,7 @@
 }
 
 void AdapterFactory::GetAdapter(const GetAdapterCallback& callback) {
-  if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+  if (device::BluetoothAdapterFactory::IsBluetoothSupported()) {
     device::BluetoothAdapterFactory::GetAdapter(
         base::Bind(&AdapterFactory::OnGetAdapter,
                    weak_ptr_factory_.GetWeakPtr(), callback));
diff --git a/device/bluetooth/bluetooth_adapter_factory.cc b/device/bluetooth/bluetooth_adapter_factory.cc
index ed64ecd..8cf0128 100644
--- a/device/bluetooth/bluetooth_adapter_factory.cc
+++ b/device/bluetooth/bluetooth_adapter_factory.cc
@@ -16,6 +16,9 @@
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
 #endif
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
 
 namespace device {
 
@@ -54,7 +57,7 @@
 }  // namespace
 
 // static
-bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
+bool BluetoothAdapterFactory::IsBluetoothSupported() {
   // SetAdapterForTesting() may be used to provide a test or mock adapter
   // instance even on platforms that would otherwise not support it.
   if (default_adapter.Get())
@@ -68,27 +71,31 @@
 }
 
 // static
-bool BluetoothAdapterFactory::IsLowEnergyAvailable() {
-  DCHECK(IsBluetoothAdapterAvailable());
-
+bool BluetoothAdapterFactory::IsLowEnergySupported() {
   // SetAdapterForTesting() may be used to provide a test or mock adapter
   // instance even on platforms that would otherwise not support it.
   if (default_adapter.Get())
     return true;
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_WIN) || \
-    defined(OS_LINUX)
+
+#if defined(OS_ANDROID) && __ANDROID_API__ >= 23
   return true;
+#elif defined(OS_WIN)
+  // Windows 8 supports Low Energy GATT operations but it does not support
+  // scanning, initiating connections and GATT Server. To keep the API
+  // consistent we consider Windows 8 as lacking Low Energy support.
+  return base::win::GetVersion() >= base::win::VERSION_WIN10;
 #elif defined(OS_MACOSX)
   return base::mac::IsAtLeastOS10_10();
+#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
+  return true;
 #else
   return false;
-#endif  // defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_WIN) ||
-        // defined(OS_LINUX)
+#endif
 }
 
 // static
 void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
-  DCHECK(IsBluetoothAdapterAvailable());
+  DCHECK(IsBluetoothSupported());
 
 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
   if (!default_adapter.Get()) {
diff --git a/device/bluetooth/bluetooth_adapter_factory.h b/device/bluetooth/bluetooth_adapter_factory.h
index ab800db..4dbdbf3 100644
--- a/device/bluetooth/bluetooth_adapter_factory.h
+++ b/device/bluetooth/bluetooth_adapter_factory.h
@@ -20,13 +20,17 @@
   typedef base::Callback<void(scoped_refptr<BluetoothAdapter> adapter)>
       AdapterCallback;
 
-  // Returns true if the Bluetooth adapter is available for the current
-  // platform.
-  static bool IsBluetoothAdapterAvailable();
+  // Returns true if the platform supports Bluetooth. It does not imply that
+  // there is a Bluetooth radio. Use BluetoothAdapter::IsPresent to know
+  // if there is a Bluetooth radio present.
+  static bool IsBluetoothSupported();
 
-  // Returns true if Bluetooth Low Energy is available for the current
-  // platform.
-  static bool IsLowEnergyAvailable();
+  // Returns true if the platform supports Bluetooth Low Energy. This is
+  // independent of whether or not there is a Bluetooth radio present e.g.
+  // Windows 7 does not support BLE so IsLowEnergySupported would return
+  // false. Windows 10, on the other hand, supports BLE so this function
+  // returns true even if there is no Bluetooth radio on the system.
+  static bool IsLowEnergySupported();
 
   // Returns the shared instance of the default adapter, creating and
   // initializing it if necessary. |callback| is called with the adapter
diff --git a/device/bluetooth/bluetooth_adapter_factory_wrapper.cc b/device/bluetooth/bluetooth_adapter_factory_wrapper.cc
index 722fb24..0f6734e 100644
--- a/device/bluetooth/bluetooth_adapter_factory_wrapper.cc
+++ b/device/bluetooth/bluetooth_adapter_factory_wrapper.cc
@@ -35,12 +35,12 @@
   return g_singleton.Get();
 }
 
-bool BluetoothAdapterFactoryWrapper::IsLowEnergyAvailable() {
+bool BluetoothAdapterFactoryWrapper::IsLowEnergySupported() {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (adapter_ != nullptr) {
     return true;
   }
-  return BluetoothAdapterFactory::IsLowEnergyAvailable();
+  return BluetoothAdapterFactory::IsLowEnergySupported();
 }
 
 void BluetoothAdapterFactoryWrapper::AcquireAdapter(
@@ -56,7 +56,7 @@
     return;
   }
 
-  DCHECK(BluetoothAdapterFactory::IsLowEnergyAvailable());
+  DCHECK(BluetoothAdapterFactory::IsLowEnergySupported());
   BluetoothAdapterFactory::GetAdapter(
       base::Bind(&BluetoothAdapterFactoryWrapper::OnGetAdapter,
                  weak_ptr_factory_.GetWeakPtr(), callback));
diff --git a/device/bluetooth/bluetooth_adapter_factory_wrapper.h b/device/bluetooth/bluetooth_adapter_factory_wrapper.h
index e7fd70e..3731e3ca 100644
--- a/device/bluetooth/bluetooth_adapter_factory_wrapper.h
+++ b/device/bluetooth/bluetooth_adapter_factory_wrapper.h
@@ -31,7 +31,7 @@
 
   // Returns true if the platform supports Bluetooth Low Energy or if
   // SetBluetoothAdapterForTesting has been called.
-  bool IsLowEnergyAvailable();
+  bool IsLowEnergySupported();
 
   // Adds |observer| to the set of adapter observers. If another observer has
   // acquired the adapter in the past it adds |observer| as an observer to that
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router.cc b/extensions/browser/api/bluetooth/bluetooth_event_router.cc
index dbb2385..5524f5a 100644
--- a/extensions/browser/api/bluetooth/bluetooth_event_router.cc
+++ b/extensions/browser/api/bluetooth/bluetooth_event_router.cc
@@ -79,8 +79,7 @@
 }
 
 bool BluetoothEventRouter::IsBluetoothSupported() const {
-  return adapter_.get() ||
-         device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
+  return device::BluetoothAdapterFactory::IsBluetoothSupported();
 }
 
 void BluetoothEventRouter::GetAdapter(
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
index 2c1e1f2..5ed0354 100644
--- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
+++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -278,8 +278,7 @@
 
 bool BluetoothLowEnergyEventRouter::IsBluetoothSupported() const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  return adapter_.get() ||
-         BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
+  return BluetoothAdapterFactory::IsBluetoothSupported();
 }
 
 bool BluetoothLowEnergyEventRouter::InitializeAdapterAndInvokeCallback(
diff --git a/extensions/renderer/api_last_error.cc b/extensions/renderer/api_last_error.cc
index ece0de1..fbf516b5 100644
--- a/extensions/renderer/api_last_error.cc
+++ b/extensions/renderer/api_last_error.cc
@@ -14,7 +14,12 @@
 namespace {
 
 const char kLastErrorProperty[] = "lastError";
+const char kScriptSuppliedValueKey[] = "script_supplied_value";
 
+// The object corresponding to the lastError property, containing a single
+// property ('message') with the last error. This object is stored on the parent
+// (chrome.runtime in production) as a private property, and is returned via an
+// accessor which marks the error as accessed.
 class LastErrorObject final : public gin::Wrappable<LastErrorObject> {
  public:
   explicit LastErrorObject(const std::string& error) : error_(error) {}
@@ -26,7 +31,7 @@
       v8::Isolate* isolate) override {
     DCHECK(isolate);
     return Wrappable<LastErrorObject>::GetObjectTemplateBuilder(isolate)
-        .SetProperty("message", &LastErrorObject::GetLastError);
+        .SetProperty("message", &LastErrorObject::error);
   }
 
   void Reset(const std::string& error) {
@@ -36,13 +41,9 @@
 
   const std::string& error() const { return error_; }
   bool accessed() const { return accessed_; }
+  void set_accessed() { accessed_ = true; }
 
  private:
-  std::string GetLastError() {
-    accessed_ = true;
-    return error_;
-  }
-
   std::string error_;
   bool accessed_ = false;
 
@@ -51,6 +52,63 @@
 
 gin::WrapperInfo LastErrorObject::kWrapperInfo = {gin::kEmbedderNativeGin};
 
+// An accessor to retrieve the last error property (curried in through data),
+// and mark it as accessed.
+void LastErrorGetter(v8::Local<v8::Name> property,
+                     const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Object> holder = info.Holder();
+  v8::Local<v8::Context> context = holder->CreationContext();
+
+  v8::Local<v8::Value> last_error;
+  v8::Local<v8::Private> last_error_key = v8::Private::ForApi(
+      isolate, gin::StringToSymbol(isolate, kLastErrorProperty));
+  if (!holder->GetPrivate(context, last_error_key).ToLocal(&last_error) ||
+      last_error != info.Data()) {
+    // Something funny happened - our private properties aren't set right.
+    NOTREACHED();
+    return;
+  }
+
+  v8::Local<v8::Value> return_value;
+
+  // It's possible that some script has set their own value for the last error
+  // property. If so, return that. Otherwise, return the real last error.
+  v8::Local<v8::Private> script_value_key = v8::Private::ForApi(
+      isolate, gin::StringToSymbol(isolate, kScriptSuppliedValueKey));
+  v8::Local<v8::Value> script_value;
+  if (holder->GetPrivate(context, script_value_key).ToLocal(&script_value) &&
+      !script_value->IsUndefined()) {
+    return_value = script_value;
+  } else {
+    LastErrorObject* last_error_obj = nullptr;
+    CHECK(gin::Converter<LastErrorObject*>::FromV8(isolate, last_error,
+                                                   &last_error_obj));
+    last_error_obj->set_accessed();
+    return_value = last_error;
+  }
+
+  info.GetReturnValue().Set(return_value);
+}
+
+// Allow script to set the last error property.
+void LastErrorSetter(v8::Local<v8::Name> property,
+                     v8::Local<v8::Value> value,
+                     const v8::PropertyCallbackInfo<void>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Object> holder = info.Holder();
+  v8::Local<v8::Context> context = holder->CreationContext();
+
+  v8::Local<v8::Private> script_value_key = v8::Private::ForApi(
+      isolate, gin::StringToSymbol(isolate, kScriptSuppliedValueKey));
+  v8::Maybe<bool> set_private =
+      holder->SetPrivate(context, script_value_key, value);
+  if (!set_private.IsJust() || !set_private.FromJust())
+    NOTREACHED();
+}
+
 }  // namespace
 
 APILastError::APILastError(const GetParent& get_parent,
@@ -79,14 +137,20 @@
     return;
   v8::Local<v8::String> key = gin::StringToSymbol(isolate, kLastErrorProperty);
   v8::Local<v8::Value> v8_error;
+  // Two notes: this Get() is visible to external script, and this will actually
+  // mark the lastError as accessed, if one exists. These shouldn't be a
+  // problem (lastError is meant to be helpful, but isn't designed to handle
+  // crazy chaining, etc). However, if we decide we needed to be fancier, we
+  // could detect the presence of a current error through a GetPrivate(), and
+  // optionally throw it if one exists.
   if (!parent->Get(context, key).ToLocal(&v8_error))
     return;
 
   if (!v8_error->IsUndefined()) {
     // There may be an existing last error to overwrite.
     LastErrorObject* last_error = nullptr;
-    if (!gin::Converter<LastErrorObject*>::FromV8(context->GetIsolate(),
-                                                  v8_error, &last_error)) {
+    if (!gin::Converter<LastErrorObject*>::FromV8(isolate, v8_error,
+                                                  &last_error)) {
       // If it's not a real lastError (e.g. if a script manually set it), don't
       // do anything. We shouldn't mangle a property set by other script.
       // TODO(devlin): Or should we? If someone sets chrome.runtime.lastError,
@@ -95,15 +159,19 @@
     }
     last_error->Reset(error);
   } else {
-    DCHECK(context->GetIsolate());
     v8::Local<v8::Value> last_error =
-        gin::CreateHandle(context->GetIsolate(), new LastErrorObject(error))
-            .ToV8();
+        gin::CreateHandle(isolate, new LastErrorObject(error)).ToV8();
+    v8::Maybe<bool> set_private = parent->SetPrivate(
+        context, v8::Private::ForApi(isolate, key), last_error);
+    if (!set_private.IsJust() || !set_private.FromJust()) {
+      NOTREACHED();
+      return;
+    }
     DCHECK(!last_error.IsEmpty());
     // This Set() can fail, but there's nothing to do if it does (the exception
     // will be caught by the TryCatch above).
-    ignore_result(parent->Set(
-        context, gin::StringToSymbol(isolate, kLastErrorProperty), last_error));
+    ignore_result(parent->SetAccessor(context, key, &LastErrorGetter,
+                                      &LastErrorSetter, last_error));
   }
 }
 
@@ -115,6 +183,7 @@
   v8::Local<v8::Object> parent;
   LastErrorObject* last_error = nullptr;
   v8::Local<v8::String> key;
+  v8::Local<v8::Private> private_key;
   {
     // See comment in SetError().
     v8::TryCatch try_catch(isolate);
@@ -124,8 +193,10 @@
     if (parent.IsEmpty())
       return;
     key = gin::StringToSymbol(isolate, kLastErrorProperty);
+    private_key = v8::Private::ForApi(isolate, key);
     v8::Local<v8::Value> error;
-    if (!parent->Get(context, key).ToLocal(&error))
+    // Access through GetPrivate() so that we don't trigger accessed().
+    if (!parent->GetPrivate(context, private_key).ToLocal(&error))
       return;
     if (!gin::Converter<LastErrorObject*>::FromV8(context->GetIsolate(), error,
                                                   &last_error)) {
@@ -142,9 +213,14 @@
   v8::TryCatch try_catch(isolate);
   try_catch.SetVerbose(true);
 
+  v8::Maybe<bool> delete_private = parent->DeletePrivate(context, private_key);
+  if (!delete_private.IsJust() || !delete_private.FromJust()) {
+    NOTREACHED();
+    return;
+  }
   // This Delete() can fail, but there's nothing to do if it does (the exception
   // will be caught by the TryCatch above).
-  parent->Delete(context, key).ToChecked();
+  ignore_result(parent->Delete(context, key));
 }
 
 bool APILastError::HasError(v8::Local<v8::Context> context) {
@@ -159,10 +235,11 @@
   if (parent.IsEmpty())
     return false;
   v8::Local<v8::Value> error;
-  if (!parent->Get(context, gin::StringToSymbol(isolate, kLastErrorProperty))
-           .ToLocal(&error)) {
+  v8::Local<v8::Private> key = v8::Private::ForApi(
+      isolate, gin::StringToSymbol(isolate, kLastErrorProperty));
+  // Access through GetPrivate() so we don't trigger accessed().
+  if (!parent->GetPrivate(context, key).ToLocal(&error))
     return false;
-  }
 
   LastErrorObject* last_error = nullptr;
   return gin::Converter<LastErrorObject*>::FromV8(context->GetIsolate(), error,
diff --git a/extensions/renderer/api_last_error_unittest.cc b/extensions/renderer/api_last_error_unittest.cc
index 0ec57e8..dbe8ff2c 100644
--- a/extensions/renderer/api_last_error_unittest.cc
+++ b/extensions/renderer/api_last_error_unittest.cc
@@ -19,10 +19,18 @@
 void DoNothingWithError(v8::Local<v8::Context> context,
                         const std::string& error) {}
 
-std::string GetLastError(v8::Local<v8::Object> parent,
-                         v8::Local<v8::Context> context) {
-  v8::Local<v8::Value> last_error =
-      GetPropertyFromObject(parent, context, "lastError");
+// Returns the v8 object for the lastError.
+v8::Local<v8::Value> GetLastError(v8::Local<v8::Object> parent,
+                                  v8::Local<v8::Context> context) {
+  return GetPropertyFromObject(parent, context, "lastError");
+}
+
+// Returns a stringified version of the lastError message, if one exists, and
+// otherwise a stringified version of whatever the lastError property is (e.g.
+// undefined).
+std::string GetLastErrorMessage(v8::Local<v8::Object> parent,
+                                v8::Local<v8::Context> context) {
+  v8::Local<v8::Value> last_error = GetLastError(parent, context);
   if (last_error.IsEmpty() || !last_error->IsObject())
     return V8ToString(last_error, context);
   v8::Local<v8::Value> message =
@@ -57,7 +65,8 @@
   APILastError last_error(base::Bind(&GetParent, parents),
                           base::Bind(&DoNothingWithError));
 
-  EXPECT_EQ("undefined", GetLastError(parent_object, context));
+  EXPECT_FALSE(last_error.HasError(context));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_object, context));
   // Check that the key isn't present on the object (as opposed to simply being
   // undefined).
   EXPECT_FALSE(
@@ -65,10 +74,12 @@
           .ToChecked());
 
   last_error.SetError(context, "Some last error");
-  EXPECT_EQ("\"Some last error\"", GetLastError(parent_object, context));
+  EXPECT_TRUE(last_error.HasError(context));
+  EXPECT_EQ("\"Some last error\"", GetLastErrorMessage(parent_object, context));
 
   last_error.ClearError(context, false);
-  EXPECT_EQ("undefined", GetLastError(parent_object, context));
+  EXPECT_FALSE(last_error.HasError(context));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_object, context));
   EXPECT_FALSE(
       parent_object->Has(context, gin::StringToV8(isolate(), "lastError"))
           .ToChecked());
@@ -92,9 +103,24 @@
   {
     v8::TryCatch try_catch(isolate());
     last_error.SetError(context, "foo");
-    // GetLastError() will count as accessing the error property, so we
-    // shouldn't log an error.
-    EXPECT_EQ("\"foo\"", GetLastError(parent_object, context));
+    // GetLastErrorMessage() will count as accessing the error property, so we
+    // shouldn't throw an exception.
+    EXPECT_EQ("\"foo\"", GetLastErrorMessage(parent_object, context));
+    last_error.ClearError(context, true);
+    EXPECT_FALSE(console_error);
+    EXPECT_FALSE(try_catch.HasCaught());
+  }
+
+  {
+    v8::TryCatch try_catch(isolate());
+    last_error.SetError(context, "foo");
+    // GetLastError() only accesses the error object, and not the message
+    // directly (e.g. chrome.runtime.lastError vs
+    // chrome.runtime.lastError.message), but should still count as access and
+    // shouldn't throw an exception.
+    v8::Local<v8::Value> v8_error = GetLastError(parent_object, context);
+    ASSERT_FALSE(v8_error.IsEmpty());
+    EXPECT_TRUE(v8_error->IsObject());
     last_error.ClearError(context, true);
     EXPECT_FALSE(console_error);
     EXPECT_FALSE(try_catch.HasCaught());
@@ -111,6 +137,17 @@
     // JS execution.
     EXPECT_FALSE(try_catch.HasCaught());
   }
+
+  {
+    v8::TryCatch try_catch(isolate());
+    last_error.SetError(context, "A last error");
+    // Access through the internal HasError() should not count as access.
+    EXPECT_TRUE(last_error.HasError(context));
+    last_error.ClearError(context, true);
+    ASSERT_TRUE(console_error);
+    EXPECT_EQ("Unchecked runtime.lastError: A last error", *console_error);
+    EXPECT_FALSE(try_catch.HasCaught());
+  }
 }
 
 // Test behavior when something else sets a lastError property on the parent
@@ -139,14 +176,21 @@
               gin::StringToV8(isolate(), "fake error"));
   checked_set(parent_object, "lastError", fake_last_error);
 
-  EXPECT_EQ("\"fake error\"", GetLastError(parent_object, context));
+  EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
 
   // The bindings shouldn't mangle an existing property (or maybe we should -
   // see the TODO in api_last_error.cc).
   last_error.SetError(context, "Real last error");
-  EXPECT_EQ("\"fake error\"", GetLastError(parent_object, context));
+  EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
   last_error.ClearError(context, false);
-  EXPECT_EQ("\"fake error\"", GetLastError(parent_object, context));
+  EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
+
+  checked_set(parent_object, "lastError", v8::Undefined(isolate()));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_object, context));
+  last_error.SetError(context, "a last error");
+  EXPECT_EQ("\"a last error\"", GetLastErrorMessage(parent_object, context));
+  checked_set(parent_object, "lastError", fake_last_error);
+  EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
 }
 
 // Test lastError in multiple different contexts.
@@ -162,20 +206,20 @@
                           base::Bind(&DoNothingWithError));
 
   last_error.SetError(context_a, "Last error a");
-  EXPECT_EQ("\"Last error a\"", GetLastError(parent_a, context_a));
-  EXPECT_EQ("undefined", GetLastError(parent_b, context_b));
+  EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b));
 
   last_error.SetError(context_b, "Last error b");
-  EXPECT_EQ("\"Last error a\"", GetLastError(parent_a, context_a));
-  EXPECT_EQ("\"Last error b\"", GetLastError(parent_b, context_b));
+  EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a));
+  EXPECT_EQ("\"Last error b\"", GetLastErrorMessage(parent_b, context_b));
 
   last_error.ClearError(context_b, false);
-  EXPECT_EQ("\"Last error a\"", GetLastError(parent_a, context_a));
-  EXPECT_EQ("undefined", GetLastError(parent_b, context_b));
+  EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b));
 
   last_error.ClearError(context_a, false);
-  EXPECT_EQ("undefined", GetLastError(parent_a, context_a));
-  EXPECT_EQ("undefined", GetLastError(parent_b, context_b));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_a, context_a));
+  EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b));
 }
 
 }  // namespace extensions
diff --git a/gpu/ipc/service/image_transport_surface_android.cc b/gpu/ipc/service/image_transport_surface_android.cc
index 7c0e9334..d5be8e4 100644
--- a/gpu/ipc/service/image_transport_surface_android.cc
+++ b/gpu/ipc/service/image_transport_surface_android.cc
@@ -37,8 +37,8 @@
   if (!initialize_success)
     return scoped_refptr<gl::GLSurface>();
 
-  return scoped_refptr<gl::GLSurface>(
-      new PassThroughImageTransportSurface(delegate, surface.get()));
+  return scoped_refptr<gl::GLSurface>(new PassThroughImageTransportSurface(
+      delegate, surface.get(), kMultiWindowSwapIntervalDefault));
 }
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/image_transport_surface_linux.cc b/gpu/ipc/service/image_transport_surface_linux.cc
index 54cf4b2..6453e17 100644
--- a/gpu/ipc/service/image_transport_surface_linux.cc
+++ b/gpu/ipc/service/image_transport_surface_linux.cc
@@ -5,6 +5,7 @@
 #include "gpu/ipc/service/image_transport_surface.h"
 
 #include "gpu/ipc/service/pass_through_image_transport_surface.h"
+#include "ui/gl/gl_surface_glx.h"
 #include "ui/gl/init/gl_factory.h"
 
 namespace gpu {
@@ -16,15 +17,20 @@
     gl::GLSurfaceFormat format) {
   DCHECK_NE(surface_handle, kNullSurfaceHandle);
   scoped_refptr<gl::GLSurface> surface;
+  MultiWindowSwapInterval multi_window_swap_interval =
+      kMultiWindowSwapIntervalDefault;
 #if defined(USE_OZONE)
   surface = gl::init::CreateSurfacelessViewGLSurface(surface_handle);
 #endif
-  if (!surface)
+  if (!surface) {
     surface = gl::init::CreateViewGLSurface(surface_handle);
+    if (gl::GetGLImplementation() == gl::kGLImplementationDesktopGL)
+      multi_window_swap_interval = kMultiWindowSwapIntervalForceZero;
+  }
   if (!surface)
     return surface;
-  return scoped_refptr<gl::GLSurface>(
-      new PassThroughImageTransportSurface(delegate, surface.get()));
+  return scoped_refptr<gl::GLSurface>(new PassThroughImageTransportSurface(
+      delegate, surface.get(), multi_window_swap_interval));
 }
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/image_transport_surface_mac.mm b/gpu/ipc/service/image_transport_surface_mac.mm
index 2dd88d5..288e6eb 100644
--- a/gpu/ipc/service/image_transport_surface_mac.mm
+++ b/gpu/ipc/service/image_transport_surface_mac.mm
@@ -69,7 +69,8 @@
       if (!surface.get() || !surface->Initialize(format))
         return surface;
       return make_scoped_refptr<gl::GLSurface>(
-          new PassThroughImageTransportSurface(delegate, surface.get()));
+          new PassThroughImageTransportSurface(
+              delegate, surface.get(), kMultiWindowSwapIntervalDefault));
   }
 }
 
diff --git a/gpu/ipc/service/image_transport_surface_win.cc b/gpu/ipc/service/image_transport_surface_win.cc
index 495a583..a13a2d5 100644
--- a/gpu/ipc/service/image_transport_surface_win.cc
+++ b/gpu/ipc/service/image_transport_surface_win.cc
@@ -41,6 +41,8 @@
   DCHECK_NE(surface_handle, kNullSurfaceHandle);
 
   scoped_refptr<gl::GLSurface> surface;
+  MultiWindowSwapInterval multi_window_swap_interval =
+      kMultiWindowSwapIntervalDefault;
   if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) {
     std::unique_ptr<gfx::VSyncProvider> vsync_provider;
 
@@ -72,6 +74,10 @@
     } else {
       surface = gl::init::CreateNativeViewGLSurfaceEGL(
           surface_handle, std::move(vsync_provider));
+      // This is unnecessary with DirectComposition because that doesn't block
+      // swaps, but instead blocks the first draw into a surface during the next
+      // frame.
+      multi_window_swap_interval = kMultiWindowSwapIntervalForceZero;
       if (!surface)
         return nullptr;
     }
@@ -81,8 +87,8 @@
       return nullptr;
   }
 
-  return scoped_refptr<gl::GLSurface>(
-      new PassThroughImageTransportSurface(delegate, surface.get()));
+  return scoped_refptr<gl::GLSurface>(new PassThroughImageTransportSurface(
+      delegate, surface.get(), multi_window_swap_interval));
 }
 
 }  // namespace gpu
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.cc b/gpu/ipc/service/pass_through_image_transport_surface.cc
index 4f0c406f..a35c9ee 100644
--- a/gpu/ipc/service/pass_through_image_transport_surface.cc
+++ b/gpu/ipc/service/pass_through_image_transport_surface.cc
@@ -14,12 +14,23 @@
 
 namespace gpu {
 
+namespace {
+// Number of swap generations before vsync is reenabled after we've stopped
+// doing multiple swaps per frame.
+const int kMultiWindowSwapEnableVSyncDelay = 60;
+
+int g_current_swap_generation_ = 0;
+int g_num_swaps_in_current_swap_generation_ = 0;
+int g_last_multi_window_swap_generation_ = 0;
+}  // anonymous namespace
+
 PassThroughImageTransportSurface::PassThroughImageTransportSurface(
     base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
-    gl::GLSurface* surface)
+    gl::GLSurface* surface,
+    MultiWindowSwapInterval multi_window_swap_interval)
     : GLSurfaceAdapter(surface),
       delegate_(delegate),
-      did_set_swap_interval_(false),
+      multi_window_swap_interval_(multi_window_swap_interval),
       weak_ptr_factory_(this) {}
 
 bool PassThroughImageTransportSurface::Initialize(
@@ -110,18 +121,6 @@
       weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
 }
 
-bool PassThroughImageTransportSurface::OnMakeCurrent(gl::GLContext* context) {
-  if (!did_set_swap_interval_) {
-    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kDisableGpuVsync))
-      context->ForceSwapIntervalZero(true);
-    else
-      context->SetSwapInterval(1);
-    did_set_swap_interval_ = true;
-  }
-  return true;
-}
-
 PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {
   if (delegate_) {
     delegate_->SetLatencyInfoCallback(
@@ -143,12 +142,49 @@
   }
 }
 
+void PassThroughImageTransportSurface::UpdateSwapInterval() {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableGpuVsync)) {
+    gl::GLContext::GetCurrent()->ForceSwapIntervalZero(true);
+    return;
+  }
+
+  gl::GLContext::GetCurrent()->SetSwapInterval(1);
+
+  if (multi_window_swap_interval_ == kMultiWindowSwapIntervalForceZero) {
+    // This code is a simple way of enforcing that we only vsync if one surface
+    // is swapping per frame. This provides single window cases a stable refresh
+    // while allowing multi-window cases to not slow down due to multiple syncs
+    // on a single thread. A better way to fix this problem would be to have
+    // each surface present on its own thread.
+
+    if (g_current_swap_generation_ == swap_generation_) {
+      // No other surface has swapped since we swapped last time.
+      if (g_num_swaps_in_current_swap_generation_ > 1)
+        g_last_multi_window_swap_generation_ = g_current_swap_generation_;
+      g_num_swaps_in_current_swap_generation_ = 0;
+      g_current_swap_generation_++;
+    }
+
+    swap_generation_ = g_current_swap_generation_;
+    g_num_swaps_in_current_swap_generation_++;
+
+    bool should_override_vsync =
+        (g_num_swaps_in_current_swap_generation_ > 1) &&
+        (g_current_swap_generation_ - g_last_multi_window_swap_generation_ <
+         kMultiWindowSwapEnableVSyncDelay);
+    gl::GLContext::GetCurrent()->ForceSwapIntervalZero(should_override_vsync);
+  }
+}
+
 std::unique_ptr<std::vector<ui::LatencyInfo>>
 PassThroughImageTransportSurface::StartSwapBuffers() {
   // GetVsyncValues before SwapBuffers to work around Mali driver bug:
   // crbug.com/223558.
   SendVSyncUpdateIfAvailable();
 
+  UpdateSwapInterval();
+
   base::TimeTicks swap_time = base::TimeTicks::Now();
   for (auto& latency : latency_info_) {
     latency.AddLatencyNumberWithTimestamp(
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.h b/gpu/ipc/service/pass_through_image_transport_surface.h
index cf7331c..44ea243 100644
--- a/gpu/ipc/service/pass_through_image_transport_surface.h
+++ b/gpu/ipc/service/pass_through_image_transport_surface.h
@@ -19,13 +19,22 @@
 
 namespace gpu {
 
+enum MultiWindowSwapInterval {
+  // Use the default swap interval of 1 even if multiple windows are swapping.
+  // This can reduce frame rate if the swap buffers calls block.
+  kMultiWindowSwapIntervalDefault,
+  // Force swap interval to 0 when multiple windows are swapping.
+  kMultiWindowSwapIntervalForceZero
+};
+
 // An implementation of ImageTransportSurface that implements GLSurface through
 // GLSurfaceAdapter, thereby forwarding GLSurface methods through to it.
 class PassThroughImageTransportSurface : public gl::GLSurfaceAdapter {
  public:
   PassThroughImageTransportSurface(
       base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
-      gl::GLSurface* surface);
+      gl::GLSurface* surface,
+      MultiWindowSwapInterval multi_window_swap_interval);
 
   // GLSurface implementation.
   bool Initialize(gl::GLSurfaceFormat format) override;
@@ -43,7 +52,6 @@
   gfx::SwapResult CommitOverlayPlanes() override;
   void CommitOverlayPlanesAsync(
       const SwapCompletionCallback& callback) override;
-  bool OnMakeCurrent(gl::GLContext* context) override;
 
  private:
   ~PassThroughImageTransportSurface() override;
@@ -52,6 +60,8 @@
   // the browser.
   void SendVSyncUpdateIfAvailable();
 
+  void UpdateSwapInterval();
+
   // Add |latency_info| to be reported and augumented with GPU latency
   // components next time there is a GPU buffer swap.
   void AddLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
@@ -65,8 +75,11 @@
       gfx::SwapResult result);
 
   base::WeakPtr<ImageTransportSurfaceDelegate> delegate_;
-  bool did_set_swap_interval_;
   std::vector<ui::LatencyInfo> latency_info_;
+  MultiWindowSwapInterval multi_window_swap_interval_ =
+      kMultiWindowSwapIntervalDefault;
+  int swap_generation_ = 0;
+
   base::WeakPtrFactory<PassThroughImageTransportSurface> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PassThroughImageTransportSurface);
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index ec030d5c..d40ba6a8 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -146,6 +146,7 @@
   "network",
   "page",
   "profiler",
+  "rendering",
   "runtime",
   "security",
   "service_worker",
@@ -341,7 +342,9 @@
     "//url",
   ]
 
-  if (!is_mac) {
+  if (is_mac) {
+    deps += [ ":mac_helpers" ]
+  } else {
     deps += [ "//ui/aura" ]
   }
 
@@ -431,6 +434,22 @@
   ]
 }
 
+if (is_mac) {
+  copy("mac_helpers") {
+    sources = [
+      "$root_out_dir/crashpad_handler",
+    ]
+
+    deps = [
+      "//third_party/crashpad/crashpad/handler:crashpad_handler",
+    ]
+
+    outputs = [
+      "$root_out_dir/Helpers/{{source_file_part}}",
+    ]
+  }
+}
+
 test("headless_browsertests") {
   sources = [
     "lib/embedder_mojo_browsertest.cc",
diff --git a/headless/lib/browser/headless_devtools_client_impl.cc b/headless/lib/browser/headless_devtools_client_impl.cc
index 0b6cc969..9cb9de77 100644
--- a/headless/lib/browser/headless_devtools_client_impl.cc
+++ b/headless/lib/browser/headless_devtools_client_impl.cc
@@ -59,6 +59,7 @@
       network_domain_(this),
       page_domain_(this),
       profiler_domain_(this),
+      rendering_domain_(this),
       runtime_domain_(this),
       security_domain_(this),
       service_worker_domain_(this),
@@ -328,6 +329,10 @@
   return &profiler_domain_;
 }
 
+rendering::Domain* HeadlessDevToolsClientImpl::GetRendering() {
+  return &rendering_domain_;
+}
+
 runtime::Domain* HeadlessDevToolsClientImpl::GetRuntime() {
   return &runtime_domain_;
 }
diff --git a/headless/lib/browser/headless_devtools_client_impl.h b/headless/lib/browser/headless_devtools_client_impl.h
index 3accb438..1b17967 100644
--- a/headless/lib/browser/headless_devtools_client_impl.h
+++ b/headless/lib/browser/headless_devtools_client_impl.h
@@ -34,6 +34,7 @@
 #include "headless/public/devtools/domains/network.h"
 #include "headless/public/devtools/domains/page.h"
 #include "headless/public/devtools/domains/profiler.h"
+#include "headless/public/devtools/domains/rendering.h"
 #include "headless/public/devtools/domains/runtime.h"
 #include "headless/public/devtools/domains/security.h"
 #include "headless/public/devtools/domains/service_worker.h"
@@ -86,6 +87,7 @@
   network::Domain* GetNetwork() override;
   page::Domain* GetPage() override;
   profiler::Domain* GetProfiler() override;
+  rendering::Domain* GetRendering() override;
   runtime::Domain* GetRuntime() override;
   security::Domain* GetSecurity() override;
   service_worker::Domain* GetServiceWorker() override;
@@ -188,6 +190,7 @@
   network::ExperimentalDomain network_domain_;
   page::ExperimentalDomain page_domain_;
   profiler::ExperimentalDomain profiler_domain_;
+  rendering::ExperimentalDomain rendering_domain_;
   runtime::ExperimentalDomain runtime_domain_;
   security::ExperimentalDomain security_domain_;
   service_worker::ExperimentalDomain service_worker_domain_;
diff --git a/headless/lib/headless_browser_browsertest.cc b/headless/lib/headless_browser_browsertest.cc
index 52931af4..8b6e20c7 100644
--- a/headless/lib/headless_browser_browsertest.cc
+++ b/headless/lib/headless_browser_browsertest.cc
@@ -717,12 +717,13 @@
   base::FilePath crash_dumps_dir_;
 };
 
-// TODO(skyostil): Minidump generation currently is only supported on Linux.
-#if defined(HEADLESS_USE_BREAKPAD)
+// TODO(skyostil): Minidump generation currently is only supported on Linux and
+// Mac.
+#if defined(HEADLESS_USE_BREAKPAD) || defined(OS_MACOSX)
 #define MAYBE_GenerateMinidump GenerateMinidump
 #else
 #define MAYBE_GenerateMinidump DISABLED_GenerateMinidump
-#endif  // defined(HEADLESS_USE_BREAKPAD)
+#endif  // defined(HEADLESS_USE_BREAKPAD) || defined(OS_MACOSX)
 IN_PROC_BROWSER_TEST_F(CrashReporterTest, MAYBE_GenerateMinidump) {
   // Navigates a tab to chrome://crash and checks that a minidump is generated.
   // Note that we only test renderer crashes here -- browser crashes need to be
@@ -744,6 +745,10 @@
 
   // Check that one minidump got created.
   {
+#if defined(OS_MACOSX)
+    // Mac outputs dumps in the 'completed' directory.
+    crash_dumps_dir_ = crash_dumps_dir_.Append("completed");
+#endif
     base::ThreadRestrictions::SetIOAllowed(true);
     base::FileEnumerator it(crash_dumps_dir_, /* recursive */ false,
                             base::FileEnumerator::FILES);
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc
index 067ef27..9428908 100644
--- a/headless/lib/headless_content_main_delegate.cc
+++ b/headless/lib/headless_content_main_delegate.cc
@@ -33,6 +33,10 @@
 #include "headless/embedded_resource_pak.h"
 #endif
 
+#if defined(OS_MACOSX)
+#include "components/crash/content/app/crashpad.h"
+#endif
+
 namespace headless {
 namespace {
 // Keep in sync with content/common/content_constants_internal.h.
@@ -159,16 +163,17 @@
   g_headless_crash_client.Pointer()->set_crash_dumps_dir(
       browser_->options()->crash_dumps_dir);
 
-#if !defined(OS_MACOSX)
+#if defined(HEADLESS_USE_BREAKPAD)
   if (!browser_->options()->enable_crash_reporter) {
     DCHECK(!breakpad::IsCrashReporterEnabled());
     return;
   }
-#if defined(HEADLESS_USE_BREAKPAD)
   if (process_type != switches::kZygoteProcess)
     breakpad::InitCrashReporter(process_type);
+#elif defined(OS_MACOSX)
+  const bool browser_process = process_type.empty();
+  crash_reporter::InitializeCrashpad(browser_process, process_type);
 #endif  // defined(HEADLESS_USE_BREAKPAD)
-#endif  // !defined(OS_MACOSX)
 }
 
 void HeadlessContentMainDelegate::PreSandboxStartup() {
@@ -181,10 +186,8 @@
 #else
   if (command_line.HasSwitch(switches::kEnableLogging))
     InitLogging(command_line);
-#endif
-#if !defined(OS_MACOSX)
+#endif  // defined(OS_WIN)
   InitCrashReporter(command_line);
-#endif
   InitializeResourceBundle();
 }
 
diff --git a/headless/public/headless_devtools_client.h b/headless/public/headless_devtools_client.h
index b3cea9482..7e7d979 100644
--- a/headless/public/headless_devtools_client.h
+++ b/headless/public/headless_devtools_client.h
@@ -84,6 +84,9 @@
 namespace profiler {
 class Domain;
 }
+namespace rendering {
+class Domain;
+}
 namespace runtime {
 class Domain;
 }
@@ -136,6 +139,7 @@
   virtual network::Domain* GetNetwork() = 0;
   virtual page::Domain* GetPage() = 0;
   virtual profiler::Domain* GetProfiler() = 0;
+  virtual rendering::Domain* GetRendering() = 0;
   virtual runtime::Domain* GetRuntime() = 0;
   virtual security::Domain* GetSecurity() = 0;
   virtual service_worker::Domain* GetServiceWorker() = 0;
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd
index fbd2bb8..554dbeb 100644
--- a/ios/chrome/app/strings/ios_chromium_strings.grd
+++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -189,12 +189,6 @@
       <message name="IDS_IOS_MANAGED_SWITCH_SUBTITLE" desc="The subtitle of the Switch from a managed account dialog. [300em]">
         You are switching sync accounts from <ph name="USER_EMAIL1">$1<ex>john@doe.com</ex></ph> to <ph name="USER_EMAIL2">$2<ex>johndoe@gmail.com</ex></ph>. Your existing Chromium data is managed by <ph name="DOMAIN">$3<ex>doe.com</ex></ph>. This will delete your data from this device, but your data will remain in <ph name="USER_EMAIL1">$1<ex>john@doe.com</ex></ph>.
       </message>
-      <message name="IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS" desc="Text displayed on the New Tab Page for the move Chromium to the dock promo. [iOS only]">
-        For faster access, <ph name="BEGIN_LINK"><ex>BEGIN_LINK</ex>BEGIN_LINK</ph>move Chromium to your dock<ph name="END_LINK"><ex>END_LINK</ex>END_LINK</ph>
-      </message>
-      <message name="IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME" desc="Text displayed on the New Tab Page for the move Chromium to the dock promo. [iOS only]">
-        Love Chromium? <ph name="BEGIN_LINK"><ex>BEGIN_LINK</ex>BEGIN_LINK</ph>Move it to your dock<ph name="END_LINK"><ex>END_LINK</ex>END_LINK</ph>
-      </message>
       <message name="IDS_IOS_MOVE_TO_DOCK_TIP" desc="Text displayed on the New Tab Page for the move Chromium to the dock promo. [iOS only]">
         Tip: <ph name="BEGIN_LINK"><ex>BEGIN_LINK</ex>BEGIN_LINK</ph>Move Chromium to your dock<ph name="END_LINK"><ex>END_LINK</ex>END_LINK</ph>
       </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd
index edc1c2c..8aeee5de 100644
--- a/ios/chrome/app/strings/ios_google_chrome_strings.grd
+++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -189,12 +189,6 @@
       <message name="IDS_IOS_MANAGED_SWITCH_SUBTITLE" desc="The subtitle of the Switch from a managed account dialog. [300em]">
         You are switching sync accounts from <ph name="USER_EMAIL1">$1<ex>john@doe.com</ex></ph> to <ph name="USER_EMAIL2">$2<ex>johndoe@gmail.com</ex></ph>. Your existing Chrome data is managed by <ph name="DOMAIN">$3<ex>doe.com</ex></ph>. This will delete your data from this device, but your data will remain in <ph name="USER_EMAIL1">$1<ex>john@doe.com</ex></ph>.
       </message>
-      <message name="IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS" desc="Text displayed on the New Tab Page for the move Chrome to the dock promo. [iOS only]">
-        For faster access, <ph name="BEGIN_LINK"><ex>BEGIN_LINK</ex>BEGIN_LINK</ph>move Chrome to your dock<ph name="END_LINK"><ex>END_LINK</ex>END_LINK</ph>
-      </message>
-      <message name="IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME" desc="Text displayed on the New Tab Page for the move Chrome to the dock promo. [iOS only]">
-        Love Chrome? <ph name="BEGIN_LINK"><ex>BEGIN_LINK</ex>BEGIN_LINK</ph>Move it to your dock<ph name="END_LINK"><ex>END_LINK</ex>END_LINK</ph>
-      </message>
       <message name="IDS_IOS_MOVE_TO_DOCK_TIP" desc="Text displayed on the New Tab Page for the move Chrome to the dock promo. [iOS only]">
         Tip: <ph name="BEGIN_LINK"><ex>BEGIN_LINK</ex>BEGIN_LINK</ph>Move Chrome to your dock<ph name="END_LINK"><ex>END_LINK</ex>END_LINK</ph>
       </message>
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h
index 3ab4110..ee8f11e 100644
--- a/ios/chrome/browser/experimental_flags.h
+++ b/ios/chrome/browser/experimental_flags.h
@@ -19,11 +19,10 @@
 };
 
 enum WhatsNewPromoStatus {
-  WHATS_NEW_DEFAULT = 0,          // Not forced to enable a promo.
-  WHATS_NEW_APP_RATING,           // Force enable App Rating Promo.
-  WHATS_NEW_MOVE_TO_DOCK_FASTER,  // Force enable Move To Dock Faster Access
-  WHATS_NEW_MOVE_TO_DOCK_LOVE,    // Force enable Move To Dock Love Chrome
-  WHATS_NEW_MOVE_TO_DOCK_TIP,     // Force enable Move To Dock Tip promo.
+  WHATS_NEW_DEFAULT = 0,         // Not forced to enable a promo.
+  WHATS_NEW_APP_RATING,          // Force enable App Rating Promo.
+  WHATS_NEW_MOVE_TO_DOCK_TIP,    // Force enable Move To Dock Tip promo.
+  WHATS_NEW_PROMO_STATUS_COUNT,  // Count of Whats New Promo Statuses.
 };
 
 // Whether the First Run UI will be always be displayed.
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index 1ae41b0d..320efade 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -70,8 +70,16 @@
 }
 
 WhatsNewPromoStatus GetWhatsNewPromoStatus() {
-  NSInteger status = [[NSUserDefaults standardUserDefaults]
-      integerForKey:kWhatsNewPromoStatus];
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+  NSInteger status = [defaults integerForKey:kWhatsNewPromoStatus];
+  // If |status| is set to a value greater than or equal to the count of items
+  // defined in WhatsNewPromoStatus, set it to |WHATS_NEW_DEFAULT| and correct
+  // the value in NSUserDefaults. This error case can happen when a user
+  // upgrades to a version with fewer Whats New Promo settings.
+  if (status >= static_cast<NSInteger>(WHATS_NEW_PROMO_STATUS_COUNT)) {
+    status = static_cast<NSInteger>(WHATS_NEW_DEFAULT);
+    [defaults setInteger:status forKey:kWhatsNewPromoStatus];
+  }
   return static_cast<WhatsNewPromoStatus>(status);
 }
 
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index a931c238..8b0c43f6 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -344,15 +344,11 @@
 				<integer>0</integer>
 				<integer>1</integer>
 				<integer>2</integer>
-				<integer>3</integer>
-				<integer>4</integer>
 			</array>
 			<key>Titles</key>
 			<array>
 				<string>Default</string>
 				<string>App Rating Promo</string>
-				<string>Faster Access Move to Dock Promo</string>
-				<string>Love Chrome Move to Dock Promo</string>
 				<string>Tip Move to Dock Promo</string>
 			</array>
 		</dict>
diff --git a/ios/chrome/browser/ui/ntp/notification_promo_whats_new.mm b/ios/chrome/browser/ui/ntp/notification_promo_whats_new.mm
index c30a2fa..9e15d27 100644
--- a/ios/chrome/browser/ui/ntp/notification_promo_whats_new.mm
+++ b/ios/chrome/browser/ui/ntp/notification_promo_whats_new.mm
@@ -35,10 +35,8 @@
 
 // A mapping from a string to a l10n message id.
 const PromoStringToIdsMapEntry kPromoStringToIdsMap[] = {
-    {"IDS_IOS_APP_RATING_PROMO_STRING", IDS_IOS_APP_RATING_PROMO_STRING},
-    {"IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS", IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS},
-    {"IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME", IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME},
-    {"IDS_IOS_MOVE_TO_DOCK_TIP", IDS_IOS_MOVE_TO_DOCK_TIP},
+    {"appRatingPromo", IDS_IOS_APP_RATING_PROMO_STRING},
+    {"moveToDockTip", IDS_IOS_MOVE_TO_DOCK_TIP},
 };
 
 // Returns a localized version of |promo_text| if it has an entry in the
@@ -69,23 +67,11 @@
   if (forceEnabled != experimental_flags::WHATS_NEW_DEFAULT) {
     switch (forceEnabled) {
       case experimental_flags::WHATS_NEW_APP_RATING:
-        InjectFakePromo("1", "IDS_IOS_APP_RATING_PROMO_STRING",
-                        "chrome_command", "ratethisapp", "", "RateThisAppPromo",
-                        "logo");
-        break;
-      case experimental_flags::WHATS_NEW_MOVE_TO_DOCK_FASTER:
-        InjectFakePromo("2", "IDS_IOS_MOVE_TO_DOCK_FASTER_ACCESS", "url", "",
-                        "https://support.google.com/chrome/?p=iphone_dock",
-                        "MoveToDockFasterAccessPromo",
-                        "logoWithRoundedRectangle");
-        break;
-      case experimental_flags::WHATS_NEW_MOVE_TO_DOCK_LOVE:
-        InjectFakePromo("3", "IDS_IOS_MOVE_TO_DOCK_LOVE_CHROME", "url", "",
-                        "https://support.google.com/chrome/?p=iphone_dock",
-                        "MoveToDockLovePromo", "logoWithRoundedRectangle");
+        InjectFakePromo("1", "appRatingPromo", "chrome_command", "ratethisapp",
+                        "", "RateThisAppPromo", "logo");
         break;
       case experimental_flags::WHATS_NEW_MOVE_TO_DOCK_TIP:
-        InjectFakePromo("4", "IDS_IOS_MOVE_TO_DOCK_TIP", "url", "",
+        InjectFakePromo("2", "moveToDockTip", "url", "",
                         "https://support.google.com/chrome/?p=iphone_dock",
                         "MoveToDockTipPromo", "logoWithRoundedRectangle");
         break;
diff --git a/ios/chrome/browser/ui/ntp/notification_promo_whats_new_unittest.mm b/ios/chrome/browser/ui/ntp/notification_promo_whats_new_unittest.mm
index 1ed5ebe..47a4a2f 100644
--- a/ios/chrome/browser/ui/ntp/notification_promo_whats_new_unittest.mm
+++ b/ios/chrome/browser/ui/ntp/notification_promo_whats_new_unittest.mm
@@ -128,59 +128,55 @@
 
 // Test that a command-based, valid promo is shown with the correct text.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoCommandTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "ratethisapp", "RateThisAppPromo", "logo", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "ratethisapp", "RateThisAppPromo", "logo",
+       "0", "0");
   RunTests(l10n_util::GetStringUTF8(IDS_IOS_APP_RATING_PROMO_STRING),
            "chrome_command", "", IDC_RATE_THIS_APP, WHATS_NEW_LOGO, true);
 }
 
 // Test that a url-based, valid promo is shown with the correct text and icon.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoURLTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_MOVE_TO_DOCK_TIP", "0", "url", "http://blog.chromium.org", "",
-       "TestURLPromo", "", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "moveToDockTip", "0",
+       "url", "http://blog.chromium.org", "", "TestURLPromo", "", "0", "0");
   RunTests(l10n_util::GetStringUTF8(IDS_IOS_MOVE_TO_DOCK_TIP), "url",
            "http://blog.chromium.org/", 0, WHATS_NEW_INFO, true);
 }
 
 // Test that a promo without a valid promo type is not shown.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoNoTypeTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_MOVE_TO_DOCK_TIP", "0", "invalid type",
-       "http://blog.chromium.org", "", "TestPromo", "", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "moveToDockTip", "0",
+       "invalid type", "http://blog.chromium.org", "", "TestPromo", "", "0",
+       "0");
   EXPECT_FALSE(promo_.CanShow());
 }
 
 // Test that a url promo with an empty url is not shown.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoEmptyURLTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_MOVE_TO_DOCK_TIP", "0", "url", "", "", "TestURLPromo", "", "0",
-       "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "moveToDockTip", "0",
+       "url", "", "", "TestURLPromo", "", "0", "0");
   EXPECT_FALSE(promo_.CanShow());
 }
 
 // Test that a url promo with an invalid url is not shown.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoInvalidURLTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_MOVE_TO_DOCK_TIP", "0", "url", "INVALID URL", "",
-       "TestURLPromo", "", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "moveToDockTip", "0",
+       "url", "INVALID URL", "", "TestURLPromo", "", "0", "0");
   EXPECT_FALSE(promo_.CanShow());
 }
 
 // Test that a command-based promo with an invalid command is not shown.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoInvalidCommandTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "INVALID COMMAND", "CommandPromo", "logo", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "INVALID COMMAND", "CommandPromo", "logo",
+       "0", "0");
   EXPECT_FALSE(promo_.CanShow());
 }
 
 // Test that a promo without a metric name is not shown.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoNoMetricTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_MOVE_TO_DOCK_TIP", "0", "url", "http://blog.chromium.org", "",
-       "", "", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "moveToDockTip", "0",
+       "url", "http://blog.chromium.org", "", "", "", "0", "0");
   EXPECT_FALSE(promo_.CanShow());
 }
 
@@ -196,9 +192,9 @@
 // the cut off, the promo still shows.
 TEST_F(NotificationPromoWhatsNewTest, MaxSecondsSinceInstallSuccessTest) {
   //  Init with max_seconds_since_install set to 2 days.
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "ratethisapp", "RateThisAppPromo", "logo", "0", "172800");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "ratethisapp", "RateThisAppPromo", "logo",
+       "0", "172800");
   // Set install date to one day before now.
   base::Time one_day_before_now_time =
       base::Time::Now() - base::TimeDelta::FromDays(1);
@@ -213,9 +209,9 @@
 // the cut off, the promo does not show.
 TEST_F(NotificationPromoWhatsNewTest, MaxSecondsSinceInstallFailureTest) {
   //  Init with max_seconds_since_install set to 2 days.
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "ratethisapp", "RateThisAppPromo", "logo", "0", "172800");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "ratethisapp", "RateThisAppPromo", "logo",
+       "0", "172800");
   // Set install date to three days before now.
   base::Time three_days_before_now_time =
       base::Time::Now() - base::TimeDelta::FromDays(3);
@@ -229,9 +225,9 @@
 // install_date + seconds_since_install, the promo still shows.
 TEST_F(NotificationPromoWhatsNewTest, SecondsSinceInstallSuccessTest) {
   //  Init with seconds_since_install set to 2 days.
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "ratethisapp", "RateThisAppPromo", "logo", "172800", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "ratethisapp", "RateThisAppPromo", "logo",
+       "172800", "0");
   // Set install date to three days before now.
   base::Time three_days_before_now_time =
       base::Time::Now() - base::TimeDelta::FromDays(3);
@@ -246,9 +242,9 @@
 // install_date + seconds_since_install, the promo does not show.
 TEST_F(NotificationPromoWhatsNewTest, SecondsSinceInstallFailureTest) {
   //  Init with seconds_since_install set to 2 days.
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "ratethisapp", "RateThisAppPromo", "logo", "172800", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "ratethisapp", "RateThisAppPromo", "logo",
+       "172800", "0");
   // Set install date to one day before now.
   base::Time one_day_before_now_time =
       base::Time::Now() - base::TimeDelta::FromDays(1);
@@ -261,9 +257,9 @@
 
 // Test that user actions are recorded when promo is viewed and closed.
 TEST_F(NotificationPromoWhatsNewTest, NotificationPromoMetricTest) {
-  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT",
-       "IDS_IOS_APP_RATING_PROMO_STRING", "0", "chrome_command", "",
-       "ratethisapp", "RateThisAppPromo", "logo", "0", "0");
+  Init("3 Aug 1999 9:26:06 GMT", "3 Aug 2199 9:26:06 GMT", "appRatingPromo",
+       "0", "chrome_command", "", "ratethisapp", "RateThisAppPromo", "logo",
+       "0", "0");
 
   // Assert that promo is appropriately set up to be viewed.
   ASSERT_TRUE(promo_.CanShow());
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index 60d371b..1471774 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -76,6 +76,7 @@
 ios_web_view_sources += ios_web_view_public_headers
 
 ios_web_view_deps = [
+  ":generate_license",
   ":packed_resources",
   "//base",
   "//components/infobars/core",
@@ -170,3 +171,23 @@
     "{{bundle_resources_dir}}/{{source_file_part}}",
   ]
 }
+
+action("generate_license") {
+  _license_path = "$target_out_dir/LICENSE"
+
+  script = "//tools/licenses.py"
+  inputs = [
+    "//buildtools/$host_os/gn",
+  ]
+  outputs = [
+    _license_path,
+  ]
+  args = [
+    "license_file",
+    rebase_path(_license_path, root_build_dir),
+    "--gn-target",
+    "//ios/web_view",
+    "--gn-out-dir",
+    ".",
+  ]
+}
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index 4ae5b9c..7c79934 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -4675,11 +4675,23 @@
   ChunkDemuxerStream* audio_stream =
       static_cast<ChunkDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
   EXPECT_NE(nullptr, audio_stream);
-  CheckStreamStatusNotifications(demuxer_.get(), audio_stream);
   ChunkDemuxerStream* video_stream =
       static_cast<ChunkDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
   EXPECT_NE(nullptr, video_stream);
+
+  // Verify stream status changes without pending read.
+  CheckStreamStatusNotifications(demuxer_.get(), audio_stream);
   CheckStreamStatusNotifications(demuxer_.get(), video_stream);
+
+  // Verify stream status changes with pending read.
+  bool read_done = false;
+  audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &read_done));
+  CheckStreamStatusNotifications(demuxer_.get(), audio_stream);
+  EXPECT_TRUE(read_done);
+  read_done = false;
+  video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &read_done));
+  CheckStreamStatusNotifications(demuxer_.get(), video_stream);
+  EXPECT_TRUE(read_done);
 }
 
 TEST_F(ChunkDemuxerTest, MultipleIds) {
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 0541b52d..6a5aa09 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -747,7 +747,6 @@
   if (!is_enabled_ && !read_cb_.is_null()) {
     DVLOG(1) << "Read from disabled stream, returning EOS";
     base::ResetAndReturn(&read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer());
-    return;
   }
   if (!stream_status_change_cb_.is_null())
     stream_status_change_cb_.Run(this, is_enabled_, timestamp);
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index c828cfa..5e9bc04 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -54,6 +54,40 @@
   return arg->end_of_stream();
 }
 
+namespace {
+void OnStreamStatusChanged(base::WaitableEvent* event,
+                           DemuxerStream* stream,
+                           bool enabled,
+                           base::TimeDelta) {
+  event->Signal();
+}
+
+void CheckStreamStatusNotifications(MediaResource* media_resource,
+                                    FFmpegDemuxerStream* stream) {
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+  ASSERT_TRUE(stream->IsEnabled());
+  media_resource->SetStreamStatusChangeCB(
+      base::Bind(&OnStreamStatusChanged, base::Unretained(&event)));
+
+  stream->SetEnabled(false, base::TimeDelta());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(event.IsSignaled());
+
+  event.Reset();
+  stream->SetEnabled(true, base::TimeDelta());
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(event.IsSignaled());
+}
+
+void OnReadDone_ExpectEos(DemuxerStream::Status status,
+                          const scoped_refptr<DecoderBuffer>& buffer) {
+  EXPECT_EQ(status, DemuxerStream::kOk);
+  EXPECT_TRUE(buffer->end_of_stream());
+}
+}
+
 const uint8_t kEncryptedMediaInitData[] = {
     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
     0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
@@ -1599,4 +1633,30 @@
   EXPECT_EQ(astream, preferred_seeking_stream(base::TimeDelta()));
 }
 
+TEST_F(FFmpegDemuxerTest, StreamStatusNotifications) {
+  CreateDemuxer("bear-320x240.webm");
+  InitializeDemuxer();
+  FFmpegDemuxerStream* audio_stream =
+      static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::AUDIO));
+  EXPECT_NE(nullptr, audio_stream);
+  FFmpegDemuxerStream* video_stream =
+      static_cast<FFmpegDemuxerStream*>(GetStream(DemuxerStream::VIDEO));
+  EXPECT_NE(nullptr, video_stream);
+
+  // Verify stream status notifications delivery without pending read first.
+  CheckStreamStatusNotifications(demuxer_.get(), audio_stream);
+  CheckStreamStatusNotifications(demuxer_.get(), video_stream);
+
+  // Verify that stream notifications are delivered properly when stream status
+  // changes with a pending read. Call FlushBuffers before reading, to ensure
+  // there is no buffers ready to be returned by the Read right away, thus
+  // ensuring that status changes occur while an async read is pending.
+  audio_stream->FlushBuffers();
+  audio_stream->Read(base::Bind(&media::OnReadDone_ExpectEos));
+  CheckStreamStatusNotifications(demuxer_.get(), audio_stream);
+  video_stream->FlushBuffers();
+  video_stream->Read(base::Bind(&media::OnReadDone_ExpectEos));
+  CheckStreamStatusNotifications(demuxer_.get(), video_stream);
+}
+
 }  // namespace media
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 52e7463..23379f5 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -115,21 +115,21 @@
       testing_fixed_http_port(0),
       testing_fixed_https_port(0),
       enable_tcp_fast_open_for_ssl(false),
+      enable_user_alternate_protocol_ports(false),
       enable_spdy_ping_based_connection_checking(true),
       enable_http2(true),
       spdy_session_max_recv_window_size(kSpdySessionMaxRecvWindowSize),
       time_func(&base::TimeTicks::Now),
       enable_http2_alternative_service(false),
       enable_quic(false),
-      mark_quic_broken_when_network_blackholes(false),
-      retry_without_alt_svc_on_quic_errors(false),
-      quic_max_server_configs_stored_in_properties(0u),
+      quic_max_packet_length(kDefaultMaxPacketSize),
       quic_clock(nullptr),
       quic_random(nullptr),
-      quic_max_packet_length(kDefaultMaxPacketSize),
-      enable_user_alternate_protocol_ports(false),
       quic_crypto_client_stream_factory(
           QuicCryptoClientStreamFactory::GetDefaultFactory()),
+      quic_max_server_configs_stored_in_properties(0u),
+      mark_quic_broken_when_network_blackholes(false),
+      retry_without_alt_svc_on_quic_errors(false),
       quic_close_sessions_on_ip_change(false),
       quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
       quic_reduced_ping_timeout_seconds(kPingTimeoutSecs),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 27725eec..f78ac60 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -101,6 +101,7 @@
     uint16_t testing_fixed_http_port;
     uint16_t testing_fixed_https_port;
     bool enable_tcp_fast_open_for_ssl;
+    bool enable_user_alternate_protocol_ports;
 
     // Use SPDY ping frames to test for connection health after idle.
     bool enable_spdy_ping_based_connection_checking;
@@ -116,33 +117,37 @@
 
     // Enables QUIC support.
     bool enable_quic;
+
+    // QUIC runtime configuration options.
+
+    // Versions of QUIC which may be used.
+    QuicVersionVector quic_supported_versions;
+    // User agent description to send in the QUIC handshake.
+    std::string quic_user_agent_id;
+    // Limit on the size of QUIC packets.
+    size_t quic_max_packet_length;
+    // Source of time for QUIC connections.
+    QuicClock* quic_clock;
+    // Source of entropy for QUIC connections.
+    QuicRandom* quic_random;
+    // Optional factory to use for creating QuicCryptoClientStreams.
+    QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
+    // Maximum number of server configs that are to be stored in
+    // HttpServerProperties, instead of the disk cache.
+    size_t quic_max_server_configs_stored_in_properties;
+    // QUIC will be used for all connections in this set.
+    std::set<HostPortPair> origins_to_force_quic_on;
+    // Set of QUIC tags to send in the handshake's connection options.
+    QuicTagVector quic_connection_options;
+
+    // Active QUIC experiments
+
     // Marks a QUIC server broken when a connection blackholes after the
     // handshake is confirmed.
     bool mark_quic_broken_when_network_blackholes;
     // Retry requests which fail with QUIC_PROTOCOL_ERROR, and mark QUIC
     // broken if the retry succeeds.
     bool retry_without_alt_svc_on_quic_errors;
-    // Maximum number of server configs that are to be stored in
-    // HttpServerProperties, instead of the disk cache.
-    size_t quic_max_server_configs_stored_in_properties;
-    // If not empty, QUIC will be used for all connections to the set of
-    // origins in |origins_to_force_quic_on|.
-    std::set<HostPortPair> origins_to_force_quic_on;
-    // Source of time for QUIC connections.
-    QuicClock* quic_clock;
-    // Source of entropy for QUIC connections.
-    QuicRandom* quic_random;
-    // Limit on the size of QUIC packets.
-    size_t quic_max_packet_length;
-    // User agent description to send in the QUIC handshake.
-    std::string quic_user_agent_id;
-    bool enable_user_alternate_protocol_ports;
-    // Optional factory to use for creating QuicCryptoClientStreams.
-    QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
-    // Versions of QUIC which may be used.
-    QuicVersionVector quic_supported_versions;
-    // Set of QUIC tags to send in the handshake's connection options.
-    QuicTagVector quic_connection_options;
     // If true, all QUIC sessions are closed when any local IP address changes.
     bool quic_close_sessions_on_ip_change;
     // Specifies QUIC idle connection state lifetime.
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 464e920..050ba28 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -200,7 +200,6 @@
 // at URLRequestJobSourceStream::Read, which calls back into
 // URLRequestJob::ReadRawData.
 int URLRequestJob::Read(IOBuffer* buf, int buf_size) {
-  DCHECK_LT(buf_size, 1000000);  // Sanity check.
   DCHECK(buf);
 
   pending_read_buffer_ = buf;
diff --git a/testing/buildbot/filters/ash_mus_unittests.filter b/testing/buildbot/filters/ash_mus_unittests.filter
index 2fe9763c..1417b01 100644
--- a/testing/buildbot/filters/ash_mus_unittests.filter
+++ b/testing/buildbot/filters/ash_mus_unittests.filter
@@ -21,7 +21,7 @@
 -CursorWindowControllerTest.MoveToDifferentDisplay
 -CursorWindowControllerTest.VisibilityTest
 -DIPTest.WorkArea
--DisplayConfigurationControllerTest.ErasesAnimatorOnAnimationEnded
+-DisplayConfigurationControllerTest.OnlyHasOneAnimator
 -DisplayManagerFontTest.TextSubpixelPositioningWithDsf125External
 -DisplayManagerFontTest.TextSubpixelPositioningWithDsf125Internal
 -DisplayManagerFontTest.TextSubpixelPositioningWithDsf125InternalWithScaling
@@ -252,14 +252,17 @@
 -ScreenPositionControllerTest.ConvertHostPointToScreenRotate
 -ScreenPositionControllerTest.ConvertHostPointToScreenUIScale
 -ScreenPositionControllerTest.ConvertToScreenWhileRemovingSecondaryDisplay
--ScreenRotationAnimatorTest.RemoveSecondaryDisplayAfterCopyCallback
--ScreenRotationAnimatorTest.RotatesDuringRotation
--ScreenRotationAnimatorTest.RotatesToDifferentRotation
--ScreenRotationAnimatorTest.RotatesToDifferentRotationWithCopyCallback
--ScreenRotationAnimatorTest.ShouldCompleteAnimations
--ScreenRotationAnimatorTest.ShouldNotifyObserver
--ScreenRotationAnimatorTest.ShouldNotifyObserverOnce
--ScreenRotationAnimatorTest.ShouldNotRotateTheSameRotation
+-ScreenRotationAnimatorSlowAnimationTest.RotatesDuringRotation
+-ScreenRotationAnimatorSlowAnimationTest.RotatesToDifferentRotation
+-ScreenRotationAnimatorSlowAnimationTest.ShouldCompleteAnimations
+-ScreenRotationAnimatorSlowAnimationTest.ShouldNotifyObserver
+-ScreenRotationAnimatorSlowAnimationTest.ShouldNotifyObserverOnce
+-ScreenRotationAnimatorSlowAnimationTest.ShouldNotRotateTheSameRotation
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayBeforeFirstCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayBeforeSecondCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeFirstCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeSecondCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RotatesToDifferentRotationWithCopyCallback
 -ScreenshotControllerTest.BreaksCapture
 -ScreenshotControllerTest.MultipleDisplays
 -ScreenUtilTest.ShelfDisplayBoundsInUnifiedDesktop
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 963eeca..584f799 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -1251,6 +1251,7 @@
 Bug(none) fast/scrolling/scrollbar-prevent-default.html [ Failure ]
 Bug(none) compositing/lots-of-img-layers-with-opacity.html [ Failure ]
 Bug(none) compositing/lots-of-img-layers.html [ Failure ]
+Bug(none) compositing/opacity-with-mask.html [ Failure ]
 
 crbug.com/462142 fast/css3-text/css3-text-decoration/text-decoration-style-inherit.html [ Failure ]
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 229c108..391a03c 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -3260,6 +3260,10 @@
 # Sheriff failures 2017-04-19
 crbug.com/713094 [ Win ] virtual/sharedarraybuffer/fast/css/fontfaceset-check-platform-fonts.html [ Failure Pass ]
 
+# Fails when run in isolation. Passes when run as part of the directory
+# depending on test order.
+crbug.com/713419 virtual/gpu/fast/canvas/painting-on-bad-canvas.html [ Crash Pass ]
+
 # Tests to be run only under virtual/experimental-canvas-features/
 crbug.com/682753 fast/canvas-experimental [ Skip ]
 
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 9260384..81e8dc63 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -126,10 +126,10 @@
   {
     "prefix": "android",
     "base": "fullscreen",
-    "args": ["--enable-threaded-compositing",
+    "args": ["--enable-features=OverlayScrollbar", "--enable-threaded-compositing",
              "--enable-fixed-position-compositing", "--enable-prefer-compositing-to-lcd-text",
              "--enable-composited-scrolling-for-frames", "--enable-gesture-tap-highlight", "--enable-pinch",
-             "--force-overlay-fullscreen-video", "--enable-overlay-scrollbars", "--enable-overscroll-notifications",
+             "--force-overlay-fullscreen-video", "--enable-overscroll-notifications",
              "--enable-fixed-layout", "--enable-viewport", "--disable-canvas-aa",
              "--disable-composited-antialiasing"]
   },
diff --git a/third_party/WebKit/LayoutTests/ambient-light/rounded-lux-value-expected.txt b/third_party/WebKit/LayoutTests/ambient-light/rounded-lux-value-expected.txt
new file mode 100644
index 0000000..06ae4333
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/ambient-light/rounded-lux-value-expected.txt
@@ -0,0 +1,10 @@
+Tests that the lux value is rounded to avoid fingerprinting risk.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS deviceLightEvent.value is mockLightRounded
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/ambient-light/rounded-lux-value.html b/third_party/WebKit/LayoutTests/ambient-light/rounded-lux-value.html
new file mode 100644
index 0000000..39b221753
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/ambient-light/rounded-lux-value.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/js-test.js"></script>
+<script>
+description('Tests that the lux value is rounded to avoid fingerprinting risk.');
+
+var mockLightFullPrecision = 10.123456789;
+var mockLightRounded = 10;
+
+if (window.testRunner)
+    testRunner.setMockDeviceLight(mockLightFullPrecision);
+else
+    debug('This test can not be run without the TestRunner');
+
+var deviceLightEvent;
+function checkLight(event) {
+    deviceLightEvent = event;
+    shouldBe('deviceLightEvent.value', 'mockLightRounded');
+}
+
+function listener(event) {
+    checkLight(event);
+    finishJSTest();
+}
+
+window.addEventListener('devicelight', listener);
+window.jsTestIsAsync = true;
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-timing-1/step-timing-functions-output-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css-timing-1/step-timing-functions-output-expected.txt
deleted file mode 100644
index 24f63f7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css-timing-1/step-timing-functions-output-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-FAIL step-start easing with input progress greater than 1 assert_equals: expected "200px" but got "100px"
-PASS step-end easing with input progress greater than 1 
-FAIL step-end easing with input progress greater than 2 assert_equals: expected "200px" but got "100px"
-PASS step-start easing with input progress less than 0 
-FAIL step-start easing with input progress less than -1 assert_equals: expected "-100px" but got "0px"
-FAIL step-end easing with input progress less than 0 assert_equals: expected "-100px" but got "0px"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-expected.txt
index 4fa88d53..09b0bad 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-expected.txt
@@ -5,10 +5,10 @@
 
 PASS Rejected as expected: undefined
 PASS reason instanceof Error is true
-TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
+TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
 PASS Rejected as expected: null
 PASS reason instanceof Error is true
-TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
+TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
 PASS Rejected as expected: empty image
 PASS reason instanceof Error is true
 InvalidStateError: Failed to execute 'createImageBitmap' on 'Window': No image can be retrieved from the provided element.
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-in-workers-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-in-workers-expected.txt
index eddad15..dcf97bd7 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-in-workers-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-invalid-args-in-workers-expected.txt
@@ -6,7 +6,7 @@
 Starting worker: ./resources/canvas-createImageBitmap-invalid-args-in-workers.js
 PASS [Worker] Rejected as expected: null
 PASS [Worker] reason instanceof Error is true
-[Worker] TypeError: Failed to execute 'createImageBitmap' on 'WorkerGlobalScope': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
+[Worker] TypeError: Failed to execute 'createImageBitmap' on 'WorkerGlobalScope': The provided value is not of type '(HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
 PASS [Worker] Rejected as expected: invalid area
 PASS [Worker] reason instanceof Error is true
 [Worker] IndexSizeError: Failed to execute 'createImageBitmap' on 'WorkerGlobalScope': The source height provided is 0.
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-svg-image-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-svg-image-expected.html
new file mode 100644
index 0000000..a18476a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-svg-image-expected.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<style>
+svg {
+  border: 1px solid black;
+}
+#img4 {
+  display: none;
+}
+</style>
+<svg id="s1" width="20px" height="20px">
+  <image id="img1" href="resources/pattern.png" x="0" y="0" width="20px" height="20px" />
+</svg>
+<svg id="s2" width="20px" height="20px">
+  <image id="img1" href="resources/pattern.png" x="10" y="10" width="20px" height="20px" />
+</svg>
+<svg id="s3" width="20px" height="20px">
+  <image id="img3" href="resources/pattern.png" x="0" y="0" width="20px" height="20px" />
+</svg>
+<svg id="s4" width="20px" height="20px">
+  <image id="img4" href="invalid" x="0" y="0" width="20px" height="20px" />
+</svg>
+<svg id="s5" width="20px" height="20px">
+</svg>
+<svg id="s6" width="20px" height="20px">
+  <image id="img1" href="resources/pattern.png" x="0" y="0" width="10px" height="10px" />
+</svg>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-svg-image.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-svg-image.html
new file mode 100644
index 0000000..6780ef2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-svg-image.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<style>
+svg {
+  display: none;
+}
+canvas {
+  border: 1px solid black;
+}
+</style>
+
+<svg id="s1" width="200px" height="20px">
+  <image id="img1" href="resources/pattern.png" x="0" y="0" width="20px" height="20px" />
+  <image id="img2" href="resources/pattern.png" x="20" y="0" width="40px" height="40px" />
+  <image id="img3" href="resources/pattern.png" x="40" y="0" width="40px" height="40px" />
+  <image id="img4" href="invalid" x="60" y="0" width="20px" height="20px" />
+  <image id="img5" href="resources/pattern.png" x="80" y="0" width="20px" height="20px" />
+</svg>
+
+<canvas id="c1" width="20" height="20"></canvas>
+<canvas id="c2" width="20" height="20"></canvas>
+<canvas id="c3" width="20" height="20"></canvas>
+<canvas id="c4" width="20" height="20"></canvas>
+<canvas id="c5" width="20" height="20"></canvas>
+<canvas id="c6" width="20" height="20"></canvas>
+
+<script>
+var draw = function(target, img, x, y, opts) {
+  document.getElementById(img).addEventListener("load", function() {
+    createImageBitmap(this, opts).then((ib) => {
+      document.getElementById(target).getContext("2d").drawImage(
+        ib, x || 0, y || 0);
+    });
+  });
+}
+
+draw("c1", "img1");
+draw("c2", "img2", 10, 10);
+draw("c3", "img3");
+draw("c4", "img4");
+document.getElementById("c5").getContext("2d").drawImage(
+  document.getElementById("img5"), 0, 0);
+draw("c6", "img2", 0, 0, {resizeWidth: 10, resizeHeight: 10});
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
index d965cc1..495b94a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
@@ -967,7 +967,7 @@
 
     function nodeResolved(node)
     {
-        InspectorTest.OverlayAgent.getHighlightObjectForTest(node.id, report);
+        InspectorTest.DOMAgent.getHighlightObjectForTest(node.id, report);
     }
 
     function report(error, result)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
index bee51ac1..27539da 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -978,7 +978,6 @@
         InspectorTest.HeapProfilerAgent = target.heapProfilerAgent();
         InspectorTest.InspectorAgent = target.inspectorAgent();
         InspectorTest.NetworkAgent = target.networkAgent();
-        InspectorTest.OverlayAgent = target.overlayAgent();
         InspectorTest.PageAgent = target.pageAgent();
         InspectorTest.ProfilerAgent = target.profilerAgent();
         InspectorTest.RuntimeAgent = target.runtimeAgent();
@@ -993,7 +992,6 @@
         InspectorTest.domDebuggerModel = target.model(SDK.DOMDebuggerModel);
         InspectorTest.cssModel = target.model(SDK.CSSModel);
         InspectorTest.cpuProfilerModel = target.model(SDK.CPUProfilerModel);
-        InspectorTest.overlayModel = target.model(SDK.OverlayModel);
         InspectorTest.serviceWorkerManager = target.model(SDK.ServiceWorkerManager);
         InspectorTest.tracingManager = target.model(SDK.TracingManager);
         InspectorTest.mainTarget = target;
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-setInspectModeEnabled.html b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-setInspectModeEnabled.html
index f10e98e..24432f9 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-setInspectModeEnabled.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-setInspectModeEnabled.html
@@ -7,10 +7,9 @@
 {
     var nodeInfo = {};
     InspectorTest.eventHandler["DOM.setChildNodes"] = setChildNodes;
-    InspectorTest.eventHandler["Overlay.inspectNodeRequested"] = inspectNodeRequested;
+    InspectorTest.eventHandler["DOM.inspectNodeRequested"] = inspectNodeRequested;
     InspectorTest.sendCommand("DOM.enable", {});
-    InspectorTest.sendCommand("Overlay.enable", {});
-    InspectorTest.sendCommand("Overlay.setInspectMode", { "mode": "searchForNode", highlightConfig: {} }, onSetModeEnabled);
+    InspectorTest.sendCommand("DOM.setInspectMode", { "mode": "searchForNode", highlightConfig: {} }, onSetModeEnabled);
 
     function onSetModeEnabled(message)
     {
diff --git a/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt b/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt
index c9fe4a65..e9cbe18 100644
--- a/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/agents-enable-disable-expected.txt
@@ -11,7 +11,6 @@
 LayerTree.disable finished successfully
 Log.disable finished successfully
 Network.disable finished successfully
-Overlay.disable finished successfully
 Page.disable finished successfully
 Profiler.disable finished successfully
 Runtime.disable finished successfully
@@ -49,9 +48,6 @@
 Network.enable finished successfully
 Network.disable finished successfully
 
-Overlay.enable finished with error DOM should be enabled first
-Overlay.disable finished successfully
-
 Page.enable finished successfully
 Page.disable finished successfully
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path-expected.txt
index f49e351..2533582 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path-expected.txt
@@ -41,9 +41,11 @@
         #classes > div.\2d
         #classes > div.-a
         #classes > div.\2d 0
+        #classes > div.--a
+        #classes > div.\2d --a
         #classes > div.\37
         #classes > div.класс
-        #classes > div:nth-child(10)
+        #classes > div:nth-child(12)
         #classes > div.__proto__.foo
         #classes > span
         #id-with-class
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path.html b/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path.html
index ed646f8..8811bcb 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-css-path.html
@@ -103,6 +103,8 @@
     <div class="-"></div>
     <div class="-a"></div>
     <div class="-0"></div>
+    <div class="--a"></div>
+    <div class="---a"></div>
     <div class="7"></div>
     <div class="класс">класс</div>
     <div class="__proto__"></div>
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-after-profiling.html b/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-after-profiling.html
index cba03b6..8d40576 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-after-profiling.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-after-profiling.html
@@ -18,7 +18,7 @@
 {
     InspectorTest.cpuProfilerModel.startRecording();
     InspectorTest.cpuProfilerModel.stopRecording();
-    InspectorTest.overlayModel.setInspectMode(Protocol.Overlay.InspectMode.SearchForNode).then(clickAtInspected);
+    InspectorTest.domModel.setInspectMode(Protocol.DOM.InspectMode.SearchForNode, clickAtInspected);
 
     function clickAtInspected()
     {
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-shadow-text.html b/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-shadow-text.html
index fb1e8d04..694383e 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-shadow-text.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/inspect-mode-shadow-text.html
@@ -19,7 +19,7 @@
 
 function test()
 {
-    InspectorTest.overlayModel.setInspectMode(Protocol.Overlay.InspectMode.SearchForNode).then(step2);
+    InspectorTest.domModel.setInspectMode(Protocol.DOM.InspectMode.SearchForNode, step2);
 
     function step2()
     {
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/inspect-pointer-events-none.html b/third_party/WebKit/LayoutTests/inspector/elements/inspect-pointer-events-none.html
index ab0ee74..71505d93f 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/inspect-pointer-events-none.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/inspect-pointer-events-none.html
@@ -59,7 +59,7 @@
 
     function step1()
     {
-        InspectorTest.overlayModel.setInspectMode(Protocol.Overlay.InspectMode.SearchForNode).then(step2);
+        InspectorTest.domModel.setInspectMode(Protocol.DOM.InspectMode.SearchForNode, step2);
     }
 
     function step2()
@@ -72,7 +72,7 @@
     {
         InspectorTest.firstElementsTreeOutline().removeEventListener(Elements.ElementsTreeOutline.Events.SelectedNodeChanged, step3);
         expectSelectedNode("inner");
-        InspectorTest.overlayModel.setInspectMode(Protocol.Overlay.InspectMode.SearchForNode).then(step4);
+        InspectorTest.domModel.setInspectMode(Protocol.DOM.InspectMode.SearchForNode, step4);
     }
 
     function step4()
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/inspect-pseudo-element.html b/third_party/WebKit/LayoutTests/inspector/elements/inspect-pseudo-element.html
index 2598996..5f34553 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/inspect-pseudo-element.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/inspect-pseudo-element.html
@@ -16,7 +16,7 @@
 
 function test()
 {
-    InspectorTest.overlayModel.setInspectMode(Protocol.Overlay.InspectMode.SearchForNode).then(inspectModeEnabled);
+    InspectorTest.domModel.setInspectMode(Protocol.DOM.InspectMode.SearchForNode, inspectModeEnabled);
 
     function inspectModeEnabled()
     {
diff --git a/third_party/WebKit/LayoutTests/inspector/layers/no-overlay-layers.html b/third_party/WebKit/LayoutTests/inspector/layers/no-overlay-layers.html
index 8300cdb..0a82d716 100644
--- a/third_party/WebKit/LayoutTests/inspector/layers/no-overlay-layers.html
+++ b/third_party/WebKit/LayoutTests/inspector/layers/no-overlay-layers.html
@@ -25,7 +25,7 @@
     {
         // Assure layer objects are not re-created during updates.
         InspectorTest.layerTreeModel().layerTree().forEachLayer(function(layer) { layersBeforeHighlight.push(layer.id()); });
-        InspectorTest.OverlayAgent.highlightRect(0, 0, 200, 200, {r:255, g:0, b:0});
+        InspectorTest.DOMAgent.highlightRect(0, 0, 200, 200, {r:255, g:0, b:0});
         InspectorTest.evaluateAndRunWhenTreeChanges("requestAnimationFrame(updateGeometry)", step2);
     }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
index accaa67..0d62404 100644
--- a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
@@ -1,22 +1,22 @@
 Test that if a profiler is working all the agents are disabled.
 
 --> SDK.targetManager.suspendAllTargets();
+frontend: {"id":<number>,"method":"Page.configureOverlay","params":{"suspended":true}}
 frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":false}}
 frontend: {"id":<number>,"method":"Debugger.disable"}
 frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":0}}
-frontend: {"id":<number>,"method":"Overlay.setPausedInDebuggerMessage"}
+frontend: {"id":<number>,"method":"Page.configureOverlay","params":{"suspended":true}}
 frontend: {"id":<number>,"method":"DOM.disable"}
 frontend: {"id":<number>,"method":"CSS.disable"}
-frontend: {"id":<number>,"method":"Overlay.setSuspended","params":{"suspended":true}}
 
 --> SDK.targetManager.resumeAllTargets();
+frontend: {"id":<number>,"method":"Page.configureOverlay","params":{"suspended":false}}
 frontend: {"id":<number>,"method":"Target.setAutoAttach","params":{"autoAttach":true,"waitForDebuggerOnStart":true}}
 frontend: {"id":<number>,"method":"Debugger.enable"}
 frontend: {"id":<number>,"method":"Debugger.setPauseOnExceptions","params":{"state":"none"}}
 frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":8}}
 frontend: {"id":<number>,"method":"DOM.enable"}
 frontend: {"id":<number>,"method":"CSS.enable"}
-frontend: {"id":<number>,"method":"Overlay.setSuspended","params":{"suspended":false}}
 
 --> done
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/pretty-print-javascript-9-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/pretty-print-javascript-9-expected.txt
new file mode 100644
index 0000000..83a5cca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/pretty-print-javascript-9-expected.txt
@@ -0,0 +1,17 @@
+Verifies JavaScript pretty-printing functionality.
+
+
+Running: parenthesizedExpressions
+====== 8< ------
+if ((a))
+    ((b));
+else
+    (c);
+
+------ >8 ======
+Correct mapping for <if>
+Correct mapping for <((a))>
+Correct mapping for <((b));>
+Correct mapping for <else>
+Correct mapping for <(c)>
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/pretty-print-javascript-9.html b/third_party/WebKit/LayoutTests/inspector/sources/pretty-print-javascript-9.html
new file mode 100644
index 0000000..ca398acf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/pretty-print-javascript-9.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/sources-test.js"></script>
+
+<script>
+
+function test()
+{
+    var testJSFormatter = InspectorTest.testPrettyPrint.bind(InspectorTest, "text/javascript");
+
+    InspectorTest.runTestSuite([
+        function parenthesizedExpressions(next)
+        {
+            var mappingQueries = ["if", "((a))", "((b));", "else", "(c)"];
+            testJSFormatter("if((a))((b));else (c);", mappingQueries, next);
+        },
+    ]);
+}
+
+</script>
+
+</head>
+
+<body onload="runTest()">
+<p>Verifies JavaScript pretty-printing functionality.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index 87fce0f..0e0d7d40 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -204,8 +204,8 @@
   "$bindings_core_v8_output_dir/FloatOrStringElementRecord.h",
   "$bindings_core_v8_output_dir/HTMLElementOrLong.cpp",
   "$bindings_core_v8_output_dir/HTMLElementOrLong.h",
-  "$bindings_core_v8_output_dir/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas.cpp",
-  "$bindings_core_v8_output_dir/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas.h",
+  "$bindings_core_v8_output_dir/ImageBitmapSource.cpp",
+  "$bindings_core_v8_output_dir/ImageBitmapSource.h",
   "$bindings_core_v8_output_dir/HTMLOptionElementOrHTMLOptGroupElement.cpp",
   "$bindings_core_v8_output_dir/HTMLOptionElementOrHTMLOptGroupElement.h",
   "$bindings_core_v8_output_dir/HTMLScriptElementOrSVGScriptElement.cpp",
diff --git a/third_party/WebKit/Source/bindings/scripts/utilities.py b/third_party/WebKit/Source/bindings/scripts/utilities.py
index a212453f..991f9db 100644
--- a/third_party/WebKit/Source/bindings/scripts/utilities.py
+++ b/third_party/WebKit/Source/bindings/scripts/utilities.py
@@ -412,9 +412,11 @@
 
 # Workaround for http://crbug.com/611437
 # TODO(bashi): Remove this hack once we resolve too-long generated file names.
+# pylint: disable=line-too-long
 def shorten_union_name(union_type):
     aliases = {
         'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContext': 'RenderingContext',
+        'HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas': 'ImageBitmapSource',
     }
 
     idl_type = union_type
diff --git a/third_party/WebKit/Source/build/scripts/json5_generator.py b/third_party/WebKit/Source/build/scripts/json5_generator.py
index 72a210f..f2e1f322 100644
--- a/third_party/WebKit/Source/build/scripts/json5_generator.py
+++ b/third_party/WebKit/Source/build/scripts/json5_generator.py
@@ -155,6 +155,7 @@
         if not self.parameters:
             entry.update(item)
             return entry
+        assert "name" not in self.parameters, "The parameter 'name' is reserved, use a different name."
         entry["name"] = item.pop("name")
         # Validate parameters if it's specified.
         for key, value in item.items():
diff --git a/third_party/WebKit/Source/build/scripts/templates/fields/base.tmpl b/third_party/WebKit/Source/build/scripts/templates/fields/base.tmpl
index 2a0bc8e..b3c23ae 100644
--- a/third_party/WebKit/Source/build/scripts/templates/fields/base.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/fields/base.tmpl
@@ -1,6 +1,6 @@
 {% from 'fields/field.tmpl' import encode, decode, return_type %}
 {% macro decl_methods(field) -%}
-inline static {{return_type(field)}} {{field.initial_method_name}}() {
+inline static {{field.type_name}} {{field.initial_method_name}}() {
   return {{field.default_value}};
 }
 {{return_type(field)}} {{field.getter_method_name}}() const {
diff --git a/third_party/WebKit/Source/build/scripts/templates/fields/external.tmpl b/third_party/WebKit/Source/build/scripts/templates/fields/external.tmpl
index b5753c2..b530be7 100644
--- a/third_party/WebKit/Source/build/scripts/templates/fields/external.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/fields/external.tmpl
@@ -3,6 +3,6 @@
 {% macro decl_methods(field) %}
 {{base.decl_methods(field)}}
 void {{field.setter_method_name}}({{field.type_name}}&& v) {
-  {{field.name}} = std::move({{decode(field, "v")}});
+  {{field.name}} = std::move(v);
 }
 {% endmacro %}
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5 b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5
index 11355f8..f146476f 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5
@@ -2,13 +2,6 @@
   // This file specifies all the methods in CSSPropertyAPI.h and the necessary
   // information for code generation of the API and it's related classes.
   parameters: {
-    // - name
-    // The name of this method in camel case.
-    name: {
-      default: "",
-      valid_type: "str",
-    },
-
     // - return_type
     // Return type of this method.
     return_type: {
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
index b28309eb..41211b2 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
@@ -103,7 +103,8 @@
 }
 
 void IdleSpellCheckCallback::SetNeedsColdModeInvocation() {
-  if (!IsSpellCheckingEnabled()) {
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled() ||
+      !IsSpellCheckingEnabled()) {
     Deactivate();
     return;
   }
@@ -121,6 +122,7 @@
 }
 
 void IdleSpellCheckCallback::ColdModeTimerFired(TimerBase*) {
+  DCHECK(RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled());
   DCHECK_EQ(State::kColdModeTimerStarted, state_);
 
   if (!IsSpellCheckingEnabled()) {
@@ -174,6 +176,7 @@
     HotModeInvocation(deadline);
     SetNeedsColdModeInvocation();
   } else if (state_ == State::kColdModeRequested) {
+    DCHECK(RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled());
     state_ = State::kInColdModeInvocation;
     cold_mode_requester_->Invoke(deadline);
     if (cold_mode_requester_->FullDocumentChecked())
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallbackTest.cpp b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallbackTest.cpp
index 39907ad8..fc6e225 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallbackTest.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallbackTest.cpp
@@ -28,8 +28,10 @@
         IdleChecker().SetNeedsInvocation();
         break;
       case State::kColdModeTimerStarted:
+        DCHECK(RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled());
         break;
       case State::kColdModeRequested:
+        DCHECK(RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled());
         IdleChecker().SkipColdModeTimerForTesting();
         break;
       case State::kInHotModeInvocation:
@@ -41,13 +43,24 @@
 
 // Test cases for lifecycle state transitions.
 
-TEST_F(IdleSpellCheckCallbackTest, Initialization) {
+TEST_F(IdleSpellCheckCallbackTest, InitializationWithColdMode) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   EXPECT_EQ(State::kColdModeTimerStarted, IdleChecker().GetState());
 }
 
+TEST_F(IdleSpellCheckCallbackTest, InitializationWithoutColdMode) {
+  if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
+    return;
+  if (RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
+
+  EXPECT_EQ(State::kInactive, IdleChecker().GetState());
+}
+
 TEST_F(IdleSpellCheckCallbackTest, RequestWhenInactive) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
@@ -73,6 +86,8 @@
 TEST_F(IdleSpellCheckCallbackTest, RequestWhenColdModeTimerStarted) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeTimerStarted);
   IdleChecker().SetNeedsInvocation();
@@ -83,6 +98,8 @@
 TEST_F(IdleSpellCheckCallbackTest, RequestWhenColdModeRequested) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeRequested);
   int handle = IdleChecker().IdleCallbackHandle();
@@ -92,9 +109,22 @@
   EXPECT_NE(-1, IdleChecker().IdleCallbackHandle());
 }
 
+TEST_F(IdleSpellCheckCallbackTest, HotModeTransitToInactive) {
+  if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
+    return;
+  if (RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
+
+  TransitTo(State::kHotModeRequested);
+  IdleChecker().ForceInvocationForTesting();
+  EXPECT_EQ(State::kInactive, IdleChecker().GetState());
+}
+
 TEST_F(IdleSpellCheckCallbackTest, HotModeTransitToColdMode) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kHotModeRequested);
   IdleChecker().ForceInvocationForTesting();
@@ -104,6 +134,8 @@
 TEST_F(IdleSpellCheckCallbackTest, ColdModeTimerStartedToRequested) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeTimerStarted);
   IdleChecker().SkipColdModeTimerForTesting();
@@ -114,6 +146,8 @@
 TEST_F(IdleSpellCheckCallbackTest, ColdModeStayAtColdMode) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeRequested);
   IdleChecker().SetNeedsMoreColdModeInvocationForTesting();
@@ -124,6 +158,8 @@
 TEST_F(IdleSpellCheckCallbackTest, ColdModeToInactive) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeRequested);
   IdleChecker().ForceInvocationForTesting();
@@ -151,6 +187,8 @@
 TEST_F(IdleSpellCheckCallbackTest, DetachWhenColdModeTimerStarted) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeTimerStarted);
   GetDocument().Shutdown();
@@ -160,6 +198,8 @@
 TEST_F(IdleSpellCheckCallbackTest, DetachWhenColdModeRequested) {
   if (!RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
     return;
+  if (!RuntimeEnabledFeatures::idleTimeColdModeSpellCheckingEnabled())
+    return;
 
   TransitTo(State::kColdModeRequested);
   GetDocument().Shutdown();
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index 070d70a..952843b 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -554,7 +554,7 @@
   return StaticBitmapImage::Create(PremulSkImageToUnPremul(skia_image.get()));
 }
 
-ImageBitmap::ImageBitmap(HTMLImageElement* image,
+ImageBitmap::ImageBitmap(ImageElementBase* image,
                          Optional<IntRect> crop_rect,
                          Document* document,
                          const ImageBitmapOptions& options) {
@@ -1011,7 +1011,7 @@
 
 ImageBitmap::~ImageBitmap() {}
 
-ImageBitmap* ImageBitmap::Create(HTMLImageElement* image,
+ImageBitmap* ImageBitmap::Create(ImageElementBase* image,
                                  Optional<IntRect> crop_rect,
                                  Document* document,
                                  const ImageBitmapOptions& options) {
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h
index db57545..3684c0c3 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.h
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -8,8 +8,8 @@
 #include <memory>
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "core/CoreExport.h"
-#include "core/html/HTMLImageElement.h"
 #include "core/html/canvas/CanvasImageSource.h"
+#include "core/html/canvas/ImageElementBase.h"
 #include "core/imagebitmap/ImageBitmapOptions.h"
 #include "core/imagebitmap/ImageBitmapSource.h"
 #include "platform/geometry/IntRect.h"
@@ -21,6 +21,7 @@
 #include "third_party/skia/include/core/SkRefCnt.h"
 
 namespace blink {
+class Document;
 class HTMLCanvasElement;
 class HTMLVideoElement;
 class ImageData;
@@ -48,7 +49,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static ImageBitmap* Create(HTMLImageElement*,
+  static ImageBitmap* Create(ImageElementBase*,
                              Optional<IntRect>,
                              Document*,
                              const ImageBitmapOptions& = ImageBitmapOptions());
@@ -138,7 +139,7 @@
   DECLARE_VIRTUAL_TRACE();
 
  private:
-  ImageBitmap(HTMLImageElement*,
+  ImageBitmap(ImageElementBase*,
               Optional<IntRect>,
               Document*,
               const ImageBitmapOptions&);
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn
index 66703ff..975ff76 100644
--- a/third_party/WebKit/Source/core/html/BUILD.gn
+++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -263,12 +263,12 @@
     "canvas/CanvasDrawListener.h",
     "canvas/CanvasFontCache.cpp",
     "canvas/CanvasFontCache.h",
-    "canvas/CanvasImageElementSource.cpp",
-    "canvas/CanvasImageElementSource.h",
     "canvas/CanvasImageSource.h",
     "canvas/CanvasRenderingContext.cpp",
     "canvas/CanvasRenderingContext.h",
     "canvas/CanvasRenderingContextFactory.h",
+    "canvas/ImageElementBase.cpp",
+    "canvas/ImageElementBase.h",
     "forms/BaseButtonInputType.cpp",
     "forms/BaseButtonInputType.h",
     "forms/BaseCheckableInputType.cpp",
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index 54cb6398..9a72937 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -688,28 +688,6 @@
                                      referrer_policy_);
 }
 
-ScriptPromise HTMLImageElement::CreateImageBitmap(
-    ScriptState* script_state,
-    EventTarget& event_target,
-    Optional<IntRect> crop_rect,
-    const ImageBitmapOptions& options,
-    ExceptionState& exception_state) {
-  DCHECK(event_target.ToLocalDOMWindow());
-  if ((crop_rect &&
-       !ImageBitmap::IsSourceSizeValid(crop_rect->Width(), crop_rect->Height(),
-                                       exception_state)) ||
-      !ImageBitmap::IsSourceSizeValid(BitmapSourceSize().Width(),
-                                      BitmapSourceSize().Height(),
-                                      exception_state))
-    return ScriptPromise();
-  if (!ImageBitmap::IsResizeOptionValid(options, exception_state))
-    return ScriptPromise();
-  return ImageBitmapSource::FulfillImageBitmap(
-      script_state, ImageBitmap::Create(
-                        this, crop_rect,
-                        event_target.ToLocalDOMWindow()->document(), options));
-}
-
 void HTMLImageElement::SelectSourceURL(
     ImageLoader::UpdateFromElementBehavior behavior) {
   if (!GetDocument().IsActive())
@@ -833,16 +811,6 @@
   }
 }
 
-IntSize HTMLImageElement::BitmapSourceSize() const {
-  ImageResourceContent* image = CachedImage();
-  if (!image)
-    return IntSize();
-  LayoutSize l_size = image->ImageSize(
-      LayoutObject::ShouldRespectImageOrientation(GetLayoutObject()), 1.0f);
-  DCHECK(l_size.Fraction().IsZero());
-  return IntSize(l_size.Width().ToInt(), l_size.Height().ToInt());
-}
-
 void HTMLImageElement::AssociateWith(HTMLFormElement* form) {
   if (form && form->isConnected()) {
     form_ = form;
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.h b/third_party/WebKit/Source/core/html/HTMLImageElement.h
index a85704f6..195cee7f 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.h
@@ -29,8 +29,7 @@
 #include "core/html/FormAssociated.h"
 #include "core/html/HTMLElement.h"
 #include "core/html/HTMLImageLoader.h"
-#include "core/html/canvas/CanvasImageElementSource.h"
-#include "core/imagebitmap/ImageBitmapSource.h"
+#include "core/html/canvas/ImageElementBase.h"
 #include "platform/graphics/GraphicsTypes.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/ResourceResponse.h"
@@ -40,12 +39,10 @@
 class HTMLFormElement;
 class ImageCandidate;
 class ShadowRoot;
-class ImageBitmapOptions;
 
 class CORE_EXPORT HTMLImageElement final
     : public HTMLElement,
-      public CanvasImageElementSource,
-      public ImageBitmapSource,
+      public ImageElementBase,
       public ActiveScriptWrappable<HTMLImageElement>,
       public FormAssociated {
   DEFINE_WRAPPERTYPEINFO();
@@ -133,14 +130,6 @@
 
   void ForceReload() const;
 
-  // ImageBitmapSource implementation
-  IntSize BitmapSourceSize() const override;
-  ScriptPromise CreateImageBitmap(ScriptState*,
-                                  EventTarget&,
-                                  Optional<IntRect> crop_rect,
-                                  const ImageBitmapOptions&,
-                                  ExceptionState&) override;
-
   FormAssociated* ToFormAssociatedOrNull() override { return this; };
   void AssociateWith(HTMLFormElement*) override;
 
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasImageElementSource.cpp b/third_party/WebKit/Source/core/html/canvas/ImageElementBase.cpp
similarity index 62%
rename from third_party/WebKit/Source/core/html/canvas/CanvasImageElementSource.cpp
rename to third_party/WebKit/Source/core/html/canvas/ImageElementBase.cpp
index 64277260..e41aa983 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasImageElementSource.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/ImageElementBase.cpp
@@ -2,27 +2,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/html/canvas/CanvasImageElementSource.h"
+#include "core/html/canvas/ImageElementBase.h"
 
+#include "core/frame/ImageBitmap.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/layout/LayoutObject.h"
 #include "core/loader/ImageLoader.h"
 #include "core/svg/graphics/SVGImageForContainer.h"
 
 namespace blink {
 
-ImageResourceContent* CanvasImageElementSource::CachedImage() const {
+ImageResourceContent* ImageElementBase::CachedImage() const {
   return GetImageLoader().GetImage();
 }
 
-const Element& CanvasImageElementSource::GetElement() const {
+const Element& ImageElementBase::GetElement() const {
   return *GetImageLoader().GetElement();
 }
 
-bool CanvasImageElementSource::IsSVGSource() const {
+bool ImageElementBase::IsSVGSource() const {
   return CachedImage() && CachedImage()->GetImage()->IsSVGImage();
 }
 
-PassRefPtr<Image> CanvasImageElementSource::GetSourceImageForCanvas(
+PassRefPtr<Image> ImageElementBase::GetSourceImageForCanvas(
     SourceImageStatus* status,
     AccelerationHint,
     SnapshotReason,
@@ -54,13 +56,13 @@
   return source_image->ImageForDefaultFrame();
 }
 
-bool CanvasImageElementSource::WouldTaintOrigin(
+bool ImageElementBase::WouldTaintOrigin(
     SecurityOrigin* destination_security_origin) const {
   return CachedImage() &&
          !CachedImage()->IsAccessAllowed(destination_security_origin);
 }
 
-FloatSize CanvasImageElementSource::ElementSize(
+FloatSize ImageElementBase::ElementSize(
     const FloatSize& default_object_size) const {
   ImageResourceContent* image = CachedImage();
   if (!image)
@@ -76,7 +78,7 @@
                                     1.0f));
 }
 
-FloatSize CanvasImageElementSource::DefaultDestinationSize(
+FloatSize ImageElementBase::DefaultDestinationSize(
     const FloatSize& default_object_size) const {
   ImageResourceContent* image = CachedImage();
   if (!image)
@@ -94,15 +96,15 @@
   return FloatSize(size);
 }
 
-bool CanvasImageElementSource::IsAccelerated() const {
+bool ImageElementBase::IsAccelerated() const {
   return false;
 }
 
-const KURL& CanvasImageElementSource::SourceURL() const {
+const KURL& ImageElementBase::SourceURL() const {
   return CachedImage()->GetResponse().Url();
 }
 
-int CanvasImageElementSource::SourceWidth() {
+int ImageElementBase::SourceWidth() {
   SourceImageStatus status;
   RefPtr<Image> image = GetSourceImageForCanvas(&status, kPreferNoAcceleration,
                                                 kSnapshotReasonUnknown,
@@ -110,7 +112,7 @@
   return image->width();
 }
 
-int CanvasImageElementSource::SourceHeight() {
+int ImageElementBase::SourceHeight() {
   SourceImageStatus status;
   RefPtr<Image> image = GetSourceImageForCanvas(&status, kPreferNoAcceleration,
                                                 kSnapshotReasonUnknown,
@@ -118,9 +120,43 @@
   return image->height();
 }
 
-bool CanvasImageElementSource::IsOpaque() const {
+bool ImageElementBase::IsOpaque() const {
   Image* image = const_cast<Element&>(GetElement()).ImageContents();
   return image && image->CurrentFrameKnownToBeOpaque();
 }
 
+IntSize ImageElementBase::BitmapSourceSize() const {
+  ImageResourceContent* image = CachedImage();
+  if (!image)
+    return IntSize();
+  LayoutSize lSize =
+      image->ImageSize(LayoutObject::ShouldRespectImageOrientation(
+                           GetElement().GetLayoutObject()),
+                       1.0f);
+  DCHECK(lSize.Fraction().IsZero());
+  return IntSize(lSize.Width().ToInt(), lSize.Height().ToInt());
+}
+
+ScriptPromise ImageElementBase::CreateImageBitmap(
+    ScriptState* script_state,
+    EventTarget& event_target,
+    Optional<IntRect> crop_rect,
+    const ImageBitmapOptions& options,
+    ExceptionState& exception_state) {
+  DCHECK(event_target.ToLocalDOMWindow());
+  if ((crop_rect &&
+       !ImageBitmap::IsSourceSizeValid(crop_rect->Width(), crop_rect->Height(),
+                                       exception_state)) ||
+      !ImageBitmap::IsSourceSizeValid(BitmapSourceSize().Width(),
+                                      BitmapSourceSize().Height(),
+                                      exception_state))
+    return ScriptPromise();
+  if (!ImageBitmap::IsResizeOptionValid(options, exception_state))
+    return ScriptPromise();
+  return ImageBitmapSource::FulfillImageBitmap(
+      script_state, ImageBitmap::Create(
+                        this, crop_rect,
+                        event_target.ToLocalDOMWindow()->document(), options));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasImageElementSource.h b/third_party/WebKit/Source/core/html/canvas/ImageElementBase.h
similarity index 69%
rename from third_party/WebKit/Source/core/html/canvas/CanvasImageElementSource.h
rename to third_party/WebKit/Source/core/html/canvas/ImageElementBase.h
index 4497a79..d8060f49 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasImageElementSource.h
+++ b/third_party/WebKit/Source/core/html/canvas/ImageElementBase.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CanvasImageElementSource_h
-#define CanvasImageElementSource_h
+#ifndef ImageElementBase_h
+#define ImageElementBase_h
 
 #include "core/CoreExport.h"
 #include "core/html/canvas/CanvasImageSource.h"
+#include "core/imagebitmap/ImageBitmapSource.h"
 
 namespace blink {
 
@@ -14,11 +15,19 @@
 class ImageLoader;
 class ImageResourceContent;
 
-class CORE_EXPORT CanvasImageElementSource : public CanvasImageSource {
+class CORE_EXPORT ImageElementBase : public CanvasImageSource,
+                                     public ImageBitmapSource {
  public:
   virtual ImageLoader& GetImageLoader() const = 0;
   virtual FloatSize SourceDefaultObjectSize() = 0;
 
+  IntSize BitmapSourceSize() const override;
+  ScriptPromise CreateImageBitmap(ScriptState*,
+                                  EventTarget&,
+                                  Optional<IntRect>,
+                                  const ImageBitmapOptions&,
+                                  ExceptionState&) override;
+
   PassRefPtr<Image> GetSourceImageForCanvas(SourceImageStatus*,
                                             AccelerationHint,
                                             SnapshotReason,
@@ -42,11 +51,12 @@
 
   const KURL& SourceURL() const override;
 
- private:
   ImageResourceContent* CachedImage() const;
+
+ private:
   const Element& GetElement() const;
 };
 
 }  // namespace blink
 
-#endif  // CanvasImageElementSource_h
+#endif  // ImageElementBase_h
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
index f273bc8..a3c4e95 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -45,6 +45,7 @@
 #include "core/html/ImageData.h"
 #include "core/imagebitmap/ImageBitmapOptions.h"
 #include "core/offscreencanvas/OffscreenCanvas.h"
+#include "core/svg/SVGImageElement.h"
 #include "core/svg/graphics/SVGImage.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "platform/CrossThreadFunctional.h"
@@ -63,9 +64,16 @@
     ExceptionState& exception_state,
     const ImageBitmapOptions& options,
     bool has_crop_rect) {
+  ImageElementBase* image_element = nullptr;
   if (value.isHTMLImageElement()) {
-    HTMLImageElement* image_element = value.getAsHTMLImageElement();
-    if (!image_element || !image_element->CachedImage()) {
+    if (!(image_element = value.getAsHTMLImageElement()))
+      return nullptr;
+  } else if (value.isSVGImageElement()) {
+    if (!(image_element = value.getAsSVGImageElement()))
+      return nullptr;
+  }
+  if (image_element) {
+    if (!image_element->CachedImage()) {
       exception_state.ThrowDOMException(
           kInvalidStateError,
           "No image can be retrieved from the provided element.");
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
index 71124ca..45f9db0e 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
@@ -31,7 +31,8 @@
 #ifndef ImageBitmapFactories_h
 #define ImageBitmapFactories_h
 
-#include "bindings/core/v8/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas.h"
+#include <memory>
+#include "bindings/core/v8/ImageBitmapSource.h"
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptState.h"
@@ -43,7 +44,6 @@
 #include "platform/Supplementable.h"
 #include "platform/geometry/IntRect.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
-#include <memory>
 
 class SkImage;
 
@@ -57,7 +57,7 @@
 class ImageBitmapOptions;
 class WebTaskRunner;
 
-typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas
+typedef HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas
     ImageBitmapSourceUnion;
 
 class ImageBitmapFactories final
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.idl b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.idl
index 13ace66..8d64642 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.idl
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.idl
@@ -31,6 +31,7 @@
 // https://html.spec.whatwg.org/#imagebitmapfactories
 
 typedef (HTMLImageElement or
+         SVGImageElement or
          HTMLVideoElement or
          HTMLCanvasElement or
          Blob or
diff --git a/third_party/WebKit/Source/core/inspector/BUILD.gn b/third_party/WebKit/Source/core/inspector/BUILD.gn
index 66150a0..417c1c2 100644
--- a/third_party/WebKit/Source/core/inspector/BUILD.gn
+++ b/third_party/WebKit/Source/core/inspector/BUILD.gn
@@ -148,12 +148,12 @@
     "inspector/protocol/Memory.h",
     "inspector/protocol/Network.cpp",
     "inspector/protocol/Network.h",
-    "inspector/protocol/Overlay.cpp",
-    "inspector/protocol/Overlay.h",
     "inspector/protocol/Page.cpp",
     "inspector/protocol/Page.h",
     "inspector/protocol/Protocol.cpp",
     "inspector/protocol/Protocol.h",
+    "inspector/protocol/Rendering.cpp",
+    "inspector/protocol/Rendering.h",
     "inspector/protocol/Runtime.h",
     "inspector/protocol/Security.cpp",
     "inspector/protocol/Security.h",
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
index 9a66426..a9a2e62 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -77,7 +77,6 @@
 #include "core/page/Page.h"
 #include "core/xml/DocumentXPathEvaluator.h"
 #include "core/xml/XPathResult.h"
-#include "platform/graphics/Color.h"
 #include "platform/wtf/ListHashSet.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/text/CString.h"
@@ -98,6 +97,38 @@
 const size_t kMaxTextSize = 10000;
 const UChar kEllipsisUChar[] = {0x2026, 0};
 
+Color ParseColor(protocol::DOM::RGBA* rgba) {
+  if (!rgba)
+    return Color::kTransparent;
+
+  int r = rgba->getR();
+  int g = rgba->getG();
+  int b = rgba->getB();
+  if (!rgba->hasA())
+    return Color(r, g, b);
+
+  double a = rgba->getA(1);
+  // Clamp alpha to the [0..1] range.
+  if (a < 0)
+    a = 0;
+  else if (a > 1)
+    a = 1;
+
+  return Color(r, g, b, static_cast<int>(a * 255));
+}
+
+bool ParseQuad(std::unique_ptr<protocol::Array<double>> quad_array,
+               FloatQuad* quad) {
+  const size_t kCoordinatesInQuad = 8;
+  if (!quad_array || quad_array->length() != kCoordinatesInQuad)
+    return false;
+  quad->SetP1(FloatPoint(quad_array->get(0), quad_array->get(1)));
+  quad->SetP2(FloatPoint(quad_array->get(2), quad_array->get(3)));
+  quad->SetP3(FloatPoint(quad_array->get(4), quad_array->get(5)));
+  quad->SetP4(FloatPoint(quad_array->get(6), quad_array->get(7)));
+  return true;
+}
+
 }  // namespace
 
 class InspectorRevalidateDOMTask final
@@ -203,38 +234,20 @@
   }
 }
 
-// static
-Color InspectorDOMAgent::ParseColor(protocol::DOM::RGBA* rgba) {
-  if (!rgba)
-    return Color::kTransparent;
-
-  int r = rgba->getR();
-  int g = rgba->getG();
-  int b = rgba->getB();
-  if (!rgba->hasA())
-    return Color(r, g, b);
-
-  double a = rgba->getA(1);
-  // Clamp alpha to the [0..1] range.
-  if (a < 0)
-    a = 0;
-  else if (a > 1)
-    a = 1;
-
-  return Color(r, g, b, static_cast<int>(a * 255));
-}
-
 InspectorDOMAgent::InspectorDOMAgent(
     v8::Isolate* isolate,
     InspectedFrames* inspected_frames,
-    v8_inspector::V8InspectorSession* v8_session)
+    v8_inspector::V8InspectorSession* v8_session,
+    Client* client)
     : isolate_(isolate),
       inspected_frames_(inspected_frames),
       v8_session_(v8_session),
+      client_(client),
       dom_listener_(nullptr),
       document_node_to_id_map_(new NodeToIdMap()),
       last_node_id_(1),
-      suppress_attribute_modified_event_(false) {}
+      suppress_attribute_modified_event_(false),
+      backend_node_id_to_inspect_(0) {}
 
 InspectorDOMAgent::~InspectorDOMAgent() {}
 
@@ -425,6 +438,9 @@
   dom_editor_ = new DOMEditor(history_.Get());
   document_ = inspected_frames_->Root()->GetDocument();
   instrumenting_agents_->addInspectorDOMAgent(this);
+  if (backend_node_id_to_inspect_)
+    GetFrontend()->inspectNodeRequested(backend_node_id_to_inspect_);
+  backend_node_id_to_inspect_ = 0;
 }
 
 Response InspectorDOMAgent::enable() {
@@ -441,6 +457,7 @@
   if (!Enabled())
     return Response::Error("DOM agent hasn't been enabled");
   state_->setBoolean(DOMAgentState::kDomAgentEnabled, false);
+  SetSearchingForNode(kNotSearching, Maybe<protocol::DOM::HighlightConfig>());
   instrumenting_agents_->removeInspectorDOMAgent(this);
   history_.Clear();
   dom_editor_.Clear();
@@ -1107,8 +1124,155 @@
   return Response::OK();
 }
 
-Response InspectorDOMAgent::NodeForRemoteObjectId(const String& object_id,
-                                                  Node*& node) {
+void InspectorDOMAgent::Inspect(Node* inspected_node) {
+  if (!inspected_node)
+    return;
+
+  Node* node = inspected_node;
+  while (node && !node->IsElementNode() && !node->IsDocumentNode() &&
+         !node->IsDocumentFragment())
+    node = node->ParentOrShadowHostNode();
+  if (!node)
+    return;
+
+  int backend_node_id = DOMNodeIds::IdForNode(node);
+  if (!GetFrontend() || !Enabled()) {
+    backend_node_id_to_inspect_ = backend_node_id;
+    return;
+  }
+
+  GetFrontend()->inspectNodeRequested(backend_node_id);
+}
+
+void InspectorDOMAgent::NodeHighlightedInOverlay(Node* node) {
+  if (!GetFrontend() || !Enabled())
+    return;
+
+  while (node && !node->IsElementNode() && !node->IsDocumentNode() &&
+         !node->IsDocumentFragment())
+    node = node->ParentOrShadowHostNode();
+
+  if (!node)
+    return;
+
+  int node_id = PushNodePathToFrontend(node);
+  GetFrontend()->nodeHighlightRequested(node_id);
+}
+
+Response InspectorDOMAgent::SetSearchingForNode(
+    SearchMode search_mode,
+    Maybe<protocol::DOM::HighlightConfig> highlight_inspector_object) {
+  if (!client_)
+    return Response::OK();
+  if (search_mode == kNotSearching) {
+    client_->SetInspectMode(kNotSearching, nullptr);
+    return Response::OK();
+  }
+  std::unique_ptr<InspectorHighlightConfig> config;
+  Response response = HighlightConfigFromInspectorObject(
+      std::move(highlight_inspector_object), &config);
+  if (!response.isSuccess())
+    return response;
+  client_->SetInspectMode(search_mode, std::move(config));
+  return Response::OK();
+}
+
+Response InspectorDOMAgent::HighlightConfigFromInspectorObject(
+    Maybe<protocol::DOM::HighlightConfig> highlight_inspector_object,
+    std::unique_ptr<InspectorHighlightConfig>* out_config) {
+  if (!highlight_inspector_object.isJust()) {
+    return Response::Error(
+        "Internal error: highlight configuration parameter is missing");
+  }
+
+  protocol::DOM::HighlightConfig* config =
+      highlight_inspector_object.fromJust();
+  std::unique_ptr<InspectorHighlightConfig> highlight_config =
+      WTF::MakeUnique<InspectorHighlightConfig>();
+  highlight_config->show_info = config->getShowInfo(false);
+  highlight_config->show_rulers = config->getShowRulers(false);
+  highlight_config->show_extension_lines = config->getShowExtensionLines(false);
+  highlight_config->display_as_material = config->getDisplayAsMaterial(false);
+  highlight_config->content = ParseColor(config->getContentColor(nullptr));
+  highlight_config->padding = ParseColor(config->getPaddingColor(nullptr));
+  highlight_config->border = ParseColor(config->getBorderColor(nullptr));
+  highlight_config->margin = ParseColor(config->getMarginColor(nullptr));
+  highlight_config->event_target =
+      ParseColor(config->getEventTargetColor(nullptr));
+  highlight_config->shape = ParseColor(config->getShapeColor(nullptr));
+  highlight_config->shape_margin =
+      ParseColor(config->getShapeMarginColor(nullptr));
+  highlight_config->selector_list = config->getSelectorList("");
+
+  *out_config = std::move(highlight_config);
+  return Response::OK();
+}
+
+Response InspectorDOMAgent::setInspectMode(
+    const String& mode,
+    Maybe<protocol::DOM::HighlightConfig> highlight_config) {
+  SearchMode search_mode;
+  if (mode == protocol::DOM::InspectModeEnum::SearchForNode) {
+    search_mode = kSearchingForNormal;
+  } else if (mode == protocol::DOM::InspectModeEnum::SearchForUAShadowDOM) {
+    search_mode = kSearchingForUAShadow;
+  } else if (mode == protocol::DOM::InspectModeEnum::None) {
+    search_mode = kNotSearching;
+  } else {
+    return Response::Error(
+        String("Unknown mode \"" + mode + "\" was provided."));
+  }
+
+  if (search_mode != kNotSearching) {
+    Response response = PushDocumentUponHandlelessOperation();
+    if (!response.isSuccess())
+      return response;
+  }
+
+  return SetSearchingForNode(search_mode, std::move(highlight_config));
+}
+
+Response InspectorDOMAgent::highlightRect(
+    int x,
+    int y,
+    int width,
+    int height,
+    Maybe<protocol::DOM::RGBA> color,
+    Maybe<protocol::DOM::RGBA> outline_color) {
+  std::unique_ptr<FloatQuad> quad =
+      WTF::WrapUnique(new FloatQuad(FloatRect(x, y, width, height)));
+  InnerHighlightQuad(std::move(quad), std::move(color),
+                     std::move(outline_color));
+  return Response::OK();
+}
+
+Response InspectorDOMAgent::highlightQuad(
+    std::unique_ptr<protocol::Array<double>> quad_array,
+    Maybe<protocol::DOM::RGBA> color,
+    Maybe<protocol::DOM::RGBA> outline_color) {
+  std::unique_ptr<FloatQuad> quad = WTF::MakeUnique<FloatQuad>();
+  if (!ParseQuad(std::move(quad_array), quad.get()))
+    return Response::Error("Invalid Quad format");
+  InnerHighlightQuad(std::move(quad), std::move(color),
+                     std::move(outline_color));
+  return Response::OK();
+}
+
+void InspectorDOMAgent::InnerHighlightQuad(
+    std::unique_ptr<FloatQuad> quad,
+    Maybe<protocol::DOM::RGBA> color,
+    Maybe<protocol::DOM::RGBA> outline_color) {
+  std::unique_ptr<InspectorHighlightConfig> highlight_config =
+      WTF::MakeUnique<InspectorHighlightConfig>();
+  highlight_config->content = ParseColor(color.fromMaybe(nullptr));
+  highlight_config->content_outline =
+      ParseColor(outline_color.fromMaybe(nullptr));
+  if (client_)
+    client_->HighlightQuad(std::move(quad), *highlight_config);
+}
+
+Response InspectorDOMAgent::NodeForRemoteId(const String& object_id,
+                                            Node*& node) {
   v8::HandleScope handles(isolate_);
   v8::Local<v8::Value> value;
   v8::Local<v8::Context> context;
@@ -1126,6 +1290,66 @@
   return Response::OK();
 }
 
+Response InspectorDOMAgent::highlightNode(
+    std::unique_ptr<protocol::DOM::HighlightConfig> highlight_inspector_object,
+    Maybe<int> node_id,
+    Maybe<int> backend_node_id,
+    Maybe<String> object_id) {
+  Node* node = nullptr;
+  Response response;
+  if (node_id.isJust()) {
+    response = AssertNode(node_id.fromJust(), node);
+  } else if (backend_node_id.isJust()) {
+    node = DOMNodeIds::NodeForId(backend_node_id.fromJust());
+    response = !node ? Response::Error("No node found for given backend id")
+                     : Response::OK();
+  } else if (object_id.isJust()) {
+    response = NodeForRemoteId(object_id.fromJust(), node);
+  } else {
+    response = Response::Error("Either nodeId or objectId must be specified");
+  }
+
+  if (!response.isSuccess())
+    return response;
+
+  std::unique_ptr<InspectorHighlightConfig> highlight_config;
+  response = HighlightConfigFromInspectorObject(
+      std::move(highlight_inspector_object), &highlight_config);
+  if (!response.isSuccess())
+    return response;
+
+  if (client_)
+    client_->HighlightNode(node, *highlight_config, false);
+  return Response::OK();
+}
+
+Response InspectorDOMAgent::highlightFrame(
+    const String& frame_id,
+    Maybe<protocol::DOM::RGBA> color,
+    Maybe<protocol::DOM::RGBA> outline_color) {
+  LocalFrame* frame =
+      IdentifiersFactory::FrameById(inspected_frames_, frame_id);
+  // FIXME: Inspector doesn't currently work cross process.
+  if (frame && frame->DeprecatedLocalOwner()) {
+    std::unique_ptr<InspectorHighlightConfig> highlight_config =
+        WTF::MakeUnique<InspectorHighlightConfig>();
+    highlight_config->show_info = true;  // Always show tooltips for frames.
+    highlight_config->content = ParseColor(color.fromMaybe(nullptr));
+    highlight_config->content_outline =
+        ParseColor(outline_color.fromMaybe(nullptr));
+    if (client_)
+      client_->HighlightNode(frame->DeprecatedLocalOwner(), *highlight_config,
+                             false);
+  }
+  return Response::OK();
+}
+
+Response InspectorDOMAgent::hideHighlight() {
+  if (client_)
+    client_->HideHighlight();
+  return Response::OK();
+}
+
 Response InspectorDOMAgent::copyTo(int node_id,
                                    int target_element_id,
                                    Maybe<int> anchor_node_id,
@@ -1316,7 +1540,7 @@
 
 Response InspectorDOMAgent::requestNode(const String& object_id, int* node_id) {
   Node* node = nullptr;
-  Response response = NodeForRemoteObjectId(object_id, node);
+  Response response = NodeForRemoteId(object_id, node);
   if (!response.isSuccess())
     return response;
   *node_id = PushNodePathToFrontend(node);
@@ -2130,6 +2354,18 @@
   return Response::OK();
 }
 
+Response InspectorDOMAgent::getHighlightObjectForTest(
+    int node_id,
+    std::unique_ptr<protocol::DictionaryValue>* result) {
+  Node* node = nullptr;
+  Response response = AssertNode(node_id, node);
+  if (!response.isSuccess())
+    return response;
+  InspectorHighlight highlight(node, InspectorHighlight::DefaultConfig(), true);
+  *result = highlight.AsProtocolValue();
+  return Response::OK();
+}
+
 std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>
 InspectorDOMAgent::ResolveNode(Node* node, const String& object_group) {
   Document* document =
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
index 37b076c..1e1680f 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -34,6 +34,7 @@
 #include "core/CoreExport.h"
 #include "core/events/EventListenerMap.h"
 #include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/InspectorHighlight.h"
 #include "core/inspector/protocol/DOM.h"
 #include "core/style/ComputedStyleConstants.h"
 #include "platform/geometry/FloatQuad.h"
@@ -47,7 +48,6 @@
 namespace blink {
 
 class CharacterData;
-class Color;
 class DOMEditor;
 class Document;
 class DocumentLoader;
@@ -77,14 +77,33 @@
     virtual void DidModifyDOMAttr(Element*) = 0;
   };
 
+  enum SearchMode {
+    kNotSearching,
+    kSearchingForNormal,
+    kSearchingForUAShadow,
+  };
+
+  class Client {
+   public:
+    virtual ~Client() {}
+    virtual void HideHighlight() {}
+    virtual void HighlightNode(Node*,
+                               const InspectorHighlightConfig&,
+                               bool omit_tooltip) {}
+    virtual void HighlightQuad(std::unique_ptr<FloatQuad>,
+                               const InspectorHighlightConfig&) {}
+    virtual void SetInspectMode(SearchMode search_mode,
+                                std::unique_ptr<InspectorHighlightConfig>) {}
+  };
+
   static protocol::Response ToResponse(ExceptionState&);
   static bool GetPseudoElementType(PseudoId, String*);
   static ShadowRoot* UserAgentShadowRoot(Node*);
-  static Color ParseColor(protocol::DOM::RGBA*);
 
   InspectorDOMAgent(v8::Isolate*,
                     InspectedFrames*,
-                    v8_inspector::V8InspectorSession*);
+                    v8_inspector::V8InspectorSession*,
+                    Client*);
   ~InspectorDOMAgent() override;
   DECLARE_VIRTUAL_TRACE();
 
@@ -146,6 +165,30 @@
   protocol::Response discardSearchResults(const String& search_id) override;
   protocol::Response requestNode(const String& object_id,
                                  int* out_node_id) override;
+  protocol::Response setInspectMode(
+      const String& mode,
+      protocol::Maybe<protocol::DOM::HighlightConfig>) override;
+  protocol::Response highlightRect(
+      int x,
+      int y,
+      int width,
+      int height,
+      protocol::Maybe<protocol::DOM::RGBA> color,
+      protocol::Maybe<protocol::DOM::RGBA> outline_color) override;
+  protocol::Response highlightQuad(
+      std::unique_ptr<protocol::Array<double>> quad,
+      protocol::Maybe<protocol::DOM::RGBA> color,
+      protocol::Maybe<protocol::DOM::RGBA> outline_color) override;
+  protocol::Response highlightNode(
+      std::unique_ptr<protocol::DOM::HighlightConfig>,
+      protocol::Maybe<int> node_id,
+      protocol::Maybe<int> backend_node_id,
+      protocol::Maybe<String> object_id) override;
+  protocol::Response hideHighlight() override;
+  protocol::Response highlightFrame(
+      const String& frame_id,
+      protocol::Maybe<protocol::DOM::RGBA> content_color,
+      protocol::Maybe<protocol::DOM::RGBA> content_outline_color) override;
   protocol::Response pushNodeByPathToFrontend(const String& path,
                                               int* out_node_id) override;
   protocol::Response pushNodesByBackendIdsToFrontend(
@@ -185,6 +228,9 @@
       int* out_node_id) override;
   protocol::Response getRelayoutBoundary(int node_id,
                                          int* out_node_id) override;
+  protocol::Response getHighlightObjectForTest(
+      int node_id,
+      std::unique_ptr<protocol::DictionaryValue>* highlight) override;
 
   bool Enabled() const;
   void ReleaseDanglingNodes();
@@ -215,10 +261,9 @@
   Node* NodeForId(int node_id);
   int BoundNodeId(Node*);
   void SetDOMListener(DOMListener*);
+  void Inspect(Node*);
+  void NodeHighlightedInOverlay(Node*);
   int PushNodePathToFrontend(Node*);
-  protocol::Response PushDocumentUponHandlelessOperation();
-  protocol::Response NodeForRemoteObjectId(const String& remote_object_id,
-                                           Node*&);
 
   static String DocumentURLString(Document*);
 
@@ -251,6 +296,14 @@
   void SetDocument(Document*);
   void InnerEnable();
 
+  protocol::Response SetSearchingForNode(
+      SearchMode,
+      protocol::Maybe<protocol::DOM::HighlightConfig>);
+  protocol::Response HighlightConfigFromInspectorObject(
+      protocol::Maybe<protocol::DOM::HighlightConfig>
+          highlight_inspector_object,
+      std::unique_ptr<InspectorHighlightConfig>*);
+
   // Node-related methods.
   typedef HeapHashMap<Member<Node>, int> NodeToIdMap;
   int Bind(Node*, NodeToIdMap*);
@@ -292,14 +345,22 @@
   BuildDistributedNodesForSlot(HTMLSlotElement*);
 
   Node* NodeForPath(const String& path);
+  protocol::Response NodeForRemoteId(const String& id, Node*&);
 
   void DiscardFrontendBindings();
 
+  void InnerHighlightQuad(std::unique_ptr<FloatQuad>,
+                          protocol::Maybe<protocol::DOM::RGBA> color,
+                          protocol::Maybe<protocol::DOM::RGBA> outline_color);
+
+  protocol::Response PushDocumentUponHandlelessOperation();
+
   InspectorRevalidateDOMTask* RevalidateTask();
 
   v8::Isolate* isolate_;
   Member<InspectedFrames> inspected_frames_;
   v8_inspector::V8InspectorSession* v8_session_;
+  Client* client_;
   Member<DOMListener> dom_listener_;
   Member<NodeToIdMap> document_node_to_id_map_;
   // Owns node mappings for dangling nodes.
@@ -317,6 +378,7 @@
   Member<InspectorHistory> history_;
   Member<DOMEditor> dom_editor_;
   bool suppress_attribute_modified_event_;
+  int backend_node_id_to_inspect_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.cpp b/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.cpp
index 2db1b96..8054b7ba 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.cpp
@@ -30,8 +30,7 @@
 
 namespace blink {
 
-InspectorOverlayHost::InspectorOverlayHost(Listener* listener)
-    : listener_(listener) {}
+InspectorOverlayHost::InspectorOverlayHost() : listener_(nullptr) {}
 
 void InspectorOverlayHost::resume() {
   if (listener_)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.h b/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.h
index 167833c..0d5d4be 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorOverlayHost.h
@@ -40,20 +40,23 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
+  static InspectorOverlayHost* Create() { return new InspectorOverlayHost(); }
+  DECLARE_TRACE();
+
+  void resume();
+  void stepOver();
+
   class Listener : public GarbageCollectedMixin {
    public:
     virtual ~Listener() {}
     virtual void OverlayResumed() = 0;
     virtual void OverlaySteppedOver() = 0;
   };
-
-  explicit InspectorOverlayHost(Listener*);
-  DECLARE_TRACE();
-
-  void resume();
-  void stepOver();
+  void SetListener(Listener* listener) { listener_ = listener; }
 
  private:
+  InspectorOverlayHost();
+
   Member<Listener> listener_;
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
index 2e2a503..428dba6e 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -81,6 +81,8 @@
     "pageAgentScriptsToEvaluateOnLoad";
 static const char kScreencastEnabled[] = "screencastEnabled";
 static const char kAutoAttachToCreatedPages[] = "autoAttachToCreatedPages";
+static const char kOverlaySuspended[] = "overlaySuspended";
+static const char kOverlayMessage[] = "overlayMessage";
 }
 
 namespace {
@@ -374,6 +376,13 @@
 void InspectorPageAgent::Restore() {
   if (state_->booleanProperty(PageAgentState::kPageAgentEnabled, false))
     enable();
+  if (client_) {
+    String overlay_message;
+    state_->getString(PageAgentState::kOverlayMessage, &overlay_message);
+    client_->ConfigureOverlay(
+        state_->booleanProperty(PageAgentState::kOverlaySuspended, false),
+        overlay_message);
+  }
 }
 
 Response InspectorPageAgent::enable() {
@@ -394,6 +403,7 @@
       resource_content_loader_client_id_);
 
   stopScreencast();
+  configureOverlay(false, String());
 
   FinishReload();
   return Response::OK();
@@ -854,6 +864,18 @@
   return Response::OK();
 }
 
+Response InspectorPageAgent::configureOverlay(Maybe<bool> suspended,
+                                              Maybe<String> message) {
+  state_->setBoolean(PageAgentState::kOverlaySuspended,
+                     suspended.fromMaybe(false));
+  state_->setString(PageAgentState::kOverlaySuspended,
+                    message.fromMaybe(String()));
+  if (client_)
+    client_->ConfigureOverlay(suspended.fromMaybe(false),
+                              message.fromMaybe(String()));
+  return Response::OK();
+}
+
 Response InspectorPageAgent::getLayoutMetrics(
     std::unique_ptr<protocol::Page::LayoutViewport>* out_layout_viewport,
     std::unique_ptr<protocol::Page::VisualViewport>* out_visual_viewport,
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h
index 48ec089b..0080aa1 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.h
@@ -66,6 +66,7 @@
    public:
     virtual ~Client() {}
     virtual void PageLayoutInvalidated(bool resized) {}
+    virtual void ConfigureOverlay(bool suspended, const String& message) {}
     virtual void WaitForCreateWindow(LocalFrame*) {}
   };
 
@@ -138,6 +139,8 @@
                                      Maybe<int> max_height,
                                      Maybe<int> every_nth_frame) override;
   protocol::Response stopScreencast() override;
+  protocol::Response configureOverlay(Maybe<bool> suspended,
+                                      Maybe<String> message) override;
   protocol::Response getLayoutMetrics(
       std::unique_ptr<protocol::Page::LayoutViewport>*,
       std::unique_ptr<protocol::Page::VisualViewport>*,
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index ccc2d2b3b..cca3bc9 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -469,6 +469,15 @@
                 ]
             },
             {
+                "name": "configureOverlay",
+                "parameters": [
+                    { "name": "suspended", "type": "boolean", "optional": true, "description": "Whether overlay should be suspended and not consume any resources." },
+                    { "name": "message", "type": "string", "optional": true, "description": "Overlay message to display." }
+                ],
+                "experimental": true,
+                "description": "Configures overlay."
+            },
+            {
                 "name": "getAppManifest",
                 "experimental": true,
                 "returns": [
@@ -636,50 +645,11 @@
         ]
     },
     {
-        "domain": "Overlay",
-        "description": "This domain provides various functionality related to drawing atop the inspected page.",
-        "dependencies": ["DOM", "Page", "Runtime"],
+        "domain": "Rendering",
+        "description": "This domain allows to control rendering of the page.",
         "experimental": true,
-        "types": [
-            {
-                "id": "HighlightConfig",
-                "type": "object",
-                "properties": [
-                    { "name": "showInfo", "type": "boolean", "optional": true, "description": "Whether the node info tooltip should be shown (default: false)." },
-                    { "name": "showRulers", "type": "boolean", "optional": true, "description": "Whether the rulers should be shown (default: false)." },
-                    { "name": "showExtensionLines", "type": "boolean", "optional": true, "description": "Whether the extension lines from node to the rulers should be shown (default: false)." },
-                    { "name": "displayAsMaterial", "type": "boolean", "optional": true},
-                    { "name": "contentColor", "$ref": "DOM.RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
-                    { "name": "paddingColor", "$ref": "DOM.RGBA", "optional": true, "description": "The padding highlight fill color (default: transparent)." },
-                    { "name": "borderColor", "$ref": "DOM.RGBA", "optional": true, "description": "The border highlight fill color (default: transparent)." },
-                    { "name": "marginColor", "$ref": "DOM.RGBA", "optional": true, "description": "The margin highlight fill color (default: transparent)." },
-                    { "name": "eventTargetColor", "$ref": "DOM.RGBA", "optional": true, "description": "The event target element highlight fill color (default: transparent)." },
-                    { "name": "shapeColor", "$ref": "DOM.RGBA", "optional": true, "description": "The shape outside fill color (default: transparent)." },
-                    { "name": "shapeMarginColor", "$ref": "DOM.RGBA", "optional": true, "description": "The shape margin fill color (default: transparent)." },
-                    { "name": "selectorList", "type": "string", "optional": true, "description": "Selectors to highlight relevant nodes."}
-                ],
-                "description": "Configuration data for the highlighting of page elements."
-            },
-            {
-                "id": "InspectMode",
-                "type": "string",
-                "enum": [
-                    "searchForNode",
-                    "searchForUAShadowDOM",
-                    "none"
-                ]
-            }
-        ],
         "commands": [
             {
-                "name": "enable",
-                "description": "Enables domain notifications."
-            },
-            {
-                "name": "disable",
-                "description": "Disables domain notifications."
-            },
-            {
                 "name": "setShowPaintRects",
                 "description": "Requests that backend shows paint rectangles",
                 "parameters": [
@@ -713,96 +683,6 @@
                 "parameters": [
                     { "name": "show", "type": "boolean", "description": "Whether to paint size or not." }
                 ]
-            },
-            {
-                "name": "setPausedInDebuggerMessage",
-                "parameters": [
-                    { "name": "message", "type": "string", "optional": true, "description": "The message to display, also triggers resume and step over controls." }
-                ]
-            },
-            {
-                "name": "setSuspended",
-                "parameters": [
-                    { "name": "suspended", "type": "boolean", "description": "Whether overlay should be suspended and not consume any resources until resumed." }
-                ]
-            },
-            {
-                "name": "setInspectMode",
-                "description": "Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection.",
-                "parameters": [
-                    { "name": "mode", "$ref": "InspectMode", "description": "Set an inspection mode." },
-                    { "name": "highlightConfig", "$ref": "HighlightConfig", "optional": true, "description": "A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>." }
-                ]
-            },
-            {
-                "name": "highlightRect",
-                "description": "Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport.",
-                "parameters": [
-                    { "name": "x", "type": "integer", "description": "X coordinate" },
-                    { "name": "y", "type": "integer", "description": "Y coordinate" },
-                    { "name": "width", "type": "integer", "description": "Rectangle width" },
-                    { "name": "height", "type": "integer", "description": "Rectangle height" },
-                    { "name": "color", "$ref": "DOM.RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
-                    { "name": "outlineColor", "$ref": "DOM.RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
-                ]
-            },
-            {
-                "name": "highlightQuad",
-                "description": "Highlights given quad. Coordinates are absolute with respect to the main frame viewport.",
-                "parameters": [
-                    { "name": "quad", "$ref": "DOM.Quad", "description": "Quad to highlight" },
-                    { "name": "color", "$ref": "DOM.RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
-                    { "name": "outlineColor", "$ref": "DOM.RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
-                ]
-            },
-            {
-                "name": "highlightNode",
-                "description": "Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified.",
-                "parameters": [
-                    { "name": "highlightConfig", "$ref": "HighlightConfig",  "description": "A descriptor for the highlight appearance." },
-                    { "name": "nodeId", "$ref": "DOM.NodeId", "optional": true, "description": "Identifier of the node to highlight." },
-                    { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "optional": true, "description": "Identifier of the backend node to highlight." },
-                    { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "JavaScript object id of the node to be highlighted." }
-                ]
-            },
-            {
-                "name": "highlightFrame",
-                "description": "Highlights owner element of the frame with given id.",
-                "parameters": [
-                    { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame to highlight." },
-                    { "name": "contentColor", "$ref": "DOM.RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
-                    { "name": "contentOutlineColor", "$ref": "DOM.RGBA", "optional": true, "description": "The content box highlight outline color (default: transparent)." }
-                ]
-            },
-            {
-                "name": "hideHighlight",
-                "description": "Hides any highlight."
-            },
-            {
-                "name": "getHighlightObjectForTest",
-                "description": "For testing.",
-                "parameters": [
-                    { "name": "nodeId", "$ref": "DOM.NodeId", "description": "Id of the node to get highlight object for." }
-                ],
-                "returns": [
-                    { "name": "highlight", "type": "object", "description": "Highlight data for the node." }
-                ]
-            }
-        ],
-        "events": [
-            {
-                "name": "nodeHighlightRequested",
-                "description": "Fired when the node should be highlighted. This happens after call to <code>setInspectMode</code>.",
-                "parameters": [
-                    { "name": "nodeId", "$ref": "DOM.NodeId" }
-                ]
-            },
-            {
-                "name": "inspectNodeRequested",
-                "description": "Fired when the node should be inspected. This happens after call to <code>setInspectMode</code> or when user manually inspects an element.",
-                "parameters": [
-                    { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "description": "Id of the node to inspect." }
-                ]
             }
         ]
     },
@@ -2258,6 +2138,35 @@
                     { "name": "height", "type": "number", "description": "Rectangle height" }
                 ],
                 "description": "Rectangle."
+            },
+            {
+                "id": "HighlightConfig",
+                "type": "object",
+                "properties": [
+                    { "name": "showInfo", "type": "boolean", "optional": true, "description": "Whether the node info tooltip should be shown (default: false)." },
+                    { "name": "showRulers", "type": "boolean", "optional": true, "description": "Whether the rulers should be shown (default: false)." },
+                    { "name": "showExtensionLines", "type": "boolean", "optional": true, "description": "Whether the extension lines from node to the rulers should be shown (default: false)." },
+                    { "name": "displayAsMaterial", "type": "boolean", "optional": true, "experimental": true},
+                    { "name": "contentColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
+                    { "name": "paddingColor", "$ref": "RGBA", "optional": true, "description": "The padding highlight fill color (default: transparent)." },
+                    { "name": "borderColor", "$ref": "RGBA", "optional": true, "description": "The border highlight fill color (default: transparent)." },
+                    { "name": "marginColor", "$ref": "RGBA", "optional": true, "description": "The margin highlight fill color (default: transparent)." },
+                    { "name": "eventTargetColor", "$ref": "RGBA", "optional": true, "experimental": true, "description": "The event target element highlight fill color (default: transparent)." },
+                    { "name": "shapeColor", "$ref": "RGBA", "optional": true, "experimental": true, "description": "The shape outside fill color (default: transparent)." },
+                    { "name": "shapeMarginColor", "$ref": "RGBA", "optional": true, "experimental": true, "description": "The shape margin fill color (default: transparent)." },
+                    { "name": "selectorList", "type": "string", "optional": true, "description": "Selectors to highlight relevant nodes."}
+                ],
+                "description": "Configuration data for the highlighting of page elements."
+            },
+            {
+                "id": "InspectMode",
+                "type": "string",
+                "experimental": true,
+                "enum": [
+                    "searchForNode",
+                    "searchForUAShadowDOM",
+                    "none"
+                ]
             }
         ],
         "commands": [
@@ -2448,19 +2357,59 @@
                 "description": "Requests that the node is sent to the caller given the JavaScript node object reference. All nodes that form the path from the node to the root are also sent to the client as a series of <code>setChildNodes</code> notifications."
             },
             {
+                "name": "setInspectMode",
+                "experimental": true,
+                "parameters": [
+                    { "name": "mode", "$ref": "InspectMode", "description": "Set an inspection mode." },
+                    { "name": "highlightConfig", "$ref": "HighlightConfig", "optional": true, "description": "A descriptor for the highlight appearance of hovered-over nodes. May be omitted if <code>enabled == false</code>." }
+                ],
+                "description": "Enters the 'inspect' mode. In this mode, elements that user is hovering over are highlighted. Backend then generates 'inspectNodeRequested' event upon element selection."
+            },
+            {
                 "name": "highlightRect",
-                "description": "Highlights given rectangle.",
-                "redirect": "Overlay"
+                "parameters": [
+                    { "name": "x", "type": "integer", "description": "X coordinate" },
+                    { "name": "y", "type": "integer", "description": "Y coordinate" },
+                    { "name": "width", "type": "integer", "description": "Rectangle width" },
+                    { "name": "height", "type": "integer", "description": "Rectangle height" },
+                    { "name": "color", "$ref": "RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
+                    { "name": "outlineColor", "$ref": "RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
+                ],
+                "description": "Highlights given rectangle. Coordinates are absolute with respect to the main frame viewport."
+            },
+            {
+                "name": "highlightQuad",
+                "parameters": [
+                    { "name": "quad", "$ref": "Quad", "description": "Quad to highlight" },
+                    { "name": "color", "$ref": "RGBA", "optional": true, "description": "The highlight fill color (default: transparent)." },
+                    { "name": "outlineColor", "$ref": "RGBA", "optional": true, "description": "The highlight outline color (default: transparent)." }
+                ],
+                "description": "Highlights given quad. Coordinates are absolute with respect to the main frame viewport.",
+                "experimental": true
             },
             {
                 "name": "highlightNode",
-                "description": "Highlights DOM node.",
-                "redirect": "Overlay"
+                "parameters": [
+                    { "name": "highlightConfig", "$ref": "HighlightConfig",  "description": "A descriptor for the highlight appearance." },
+                    { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Identifier of the node to highlight." },
+                    { "name": "backendNodeId", "$ref": "BackendNodeId", "optional": true, "description": "Identifier of the backend node to highlight." },
+                    { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "JavaScript object id of the node to be highlighted.", "experimental": true }
+                ],
+                "description": "Highlights DOM node with given id or with the given JavaScript object wrapper. Either nodeId or objectId must be specified."
             },
             {
                 "name": "hideHighlight",
-                "description": "Hides any highlight.",
-                "redirect": "Overlay"
+                "description": "Hides DOM node highlight."
+            },
+            {
+                "name": "highlightFrame",
+                "parameters": [
+                    { "name": "frameId", "$ref": "Page.FrameId", "description": "Identifier of the frame to highlight." },
+                    { "name": "contentColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight fill color (default: transparent)." },
+                    { "name": "contentOutlineColor", "$ref": "RGBA", "optional": true, "description": "The content box highlight outline color (default: transparent)." }
+                ],
+                "description": "Highlights owner element of the frame with given id.",
+                "experimental": true
             },
             {
                 "name": "pushNodeByPathToFrontend",
@@ -2604,6 +2553,17 @@
                 ],
                 "description": "Returns the id of the nearest ancestor that is a relayout boundary.",
                 "experimental": true
+            },
+            {
+                "name": "getHighlightObjectForTest",
+                "parameters": [
+                    { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get highlight object for." }
+                ],
+                "returns": [
+                    { "name": "highlight", "type": "object", "description": "Highlight data for the node." }
+                ],
+                "description": "For testing.",
+                "experimental": true
             }
         ],
         "events": [
@@ -2612,6 +2572,14 @@
                 "description": "Fired when <code>Document</code> has been totally updated. Node ids are no longer valid."
             },
             {
+                "name": "inspectNodeRequested",
+                "parameters": [
+                    { "name": "backendNodeId", "$ref": "BackendNodeId", "description": "Id of the node to inspect." }
+                ],
+                "description": "Fired when the node should be inspected. This happens after call to <code>setInspectMode</code>.",
+                "experimental" : true
+            },
+            {
                 "name": "setChildNodes",
                 "parameters": [
                     { "name": "parentId", "$ref": "NodeId", "description": "Parent node id to populate with children." },
@@ -2721,6 +2689,13 @@
                 ],
                 "description": "Called when distrubution is changed.",
                 "experimental": true
+            },
+            {
+                "name": "nodeHighlightRequested",
+                "parameters": [
+                    {"name": "nodeId", "$ref": "NodeId"}
+                ],
+                "experimental": true
             }
         ]
     },
diff --git a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
index 4fb3f5b6..21048f15 100644
--- a/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
+++ b/third_party/WebKit/Source/core/inspector/inspector_protocol_config.json
@@ -51,7 +51,7 @@
                 "domain": "Log"
             },
             {
-                "domain": "Overlay"
+                "domain": "Rendering"
             },
             {
                 "domain": "Input",
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index ef3a824..2d0b917 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -70,6 +70,12 @@
   if (layout_object.HasBackdropFilter())
     return false;
 
+  // Always paint when 'will-change: opacity' is present. Reduces jank for
+  // common animation implementation approaches, for example, an element that
+  // starts with opacity zero and later begins to animate.
+  if (layout_object.StyleRef().HasWillChangeOpacityHint())
+    return false;
+
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     if (layout_object.StyleRef().Opacity())
       return false;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
index 636320de..fd3922c 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
@@ -54,6 +54,8 @@
                               const GlobalPaintFlags);
 
  private:
+  friend class PaintLayerPainterTest;
+
   enum ClipState { kHasNotClipped, kHasClipped };
 
   inline bool IsFixedPositionObjectInPagedMedia();
@@ -149,17 +151,6 @@
   bool PaintedOutputInvisible(const PaintLayerPaintingInfo&);
 
   PaintLayer& paint_layer_;
-
-  FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest, DontPaintWithTinyOpacity);
-  FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest,
-                           DontPaintWithTinyOpacityAndBackdropFilter);
-  FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest,
-                           DoPaintWithCompositedTinyOpacity);
-  FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest, DoPaintWithNonTinyOpacity);
-  FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest,
-                           DoPaintWithEffectAnimationZeroOpacity);
-  FRIEND_TEST_ALL_PREFIXES(PaintLayerPainterTest,
-                           DoNotPaintWithTransformAnimationZeroOpacity);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
index d44e07c9..13e261855 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
@@ -32,6 +32,29 @@
       : ScopedRootLayerScrollingForTest(GetParam().root_layer_scrolling),
         PaintControllerPaintTestBase(GetParam().slimming_paint_v2) {}
 
+  void ExpectPaintedOutputVisibility(const char* element_name,
+                                     bool expected_spv1) {
+    ExpectPaintedOutputVisibility(element_name, expected_spv1, expected_spv1);
+  }
+
+  void ExpectPaintedOutputVisibility(const char* element_name,
+                                     bool expected_spv1,
+                                     bool expected_spv2) {
+    PaintLayer* target_layer =
+        ToLayoutBox(GetLayoutObjectByElementId(element_name))->Layer();
+    PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
+                                         kGlobalPaintNormalPhase, LayoutSize());
+    bool invisible =
+        PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info);
+    bool expected_value = RuntimeEnabledFeatures::slimmingPaintV2Enabled()
+                              ? expected_spv2
+                              : expected_spv1;
+    EXPECT_EQ(expected_value, invisible)
+        << "Failed painted output visibility [spv2_enabled="
+        << RuntimeEnabledFeatures::slimmingPaintV2Enabled()
+        << ", expected=" << expected_value << ", actual=" << invisible << "].";
+  }
+
  private:
   void SetUp() override {
     PaintControllerPaintTestBase::SetUp();
@@ -772,52 +795,42 @@
 TEST_P(PaintLayerPainterTest, DontPaintWithTinyOpacity) {
   SetBodyInnerHTML(
       "<div id='target' style='background: blue; opacity: 0.0001'></div>");
-  PaintLayer* target_layer =
-      ToLayoutBox(GetLayoutObjectByElementId("target"))->Layer();
-  PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
-                                       kGlobalPaintNormalPhase, LayoutSize());
-  if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    EXPECT_FALSE(
-        PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
-  } else {
-    EXPECT_TRUE(
-        PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
-  }
+  ExpectPaintedOutputVisibility("target", true, false);
 }
 
-TEST_P(PaintLayerPainterTest, DontPaintWithTinyOpacityAndBackdropFilter) {
+TEST_P(PaintLayerPainterTest, DoPaintWithTinyOpacityAndWillChangeOpacity) {
+  SetBodyInnerHTML(
+      "<div id='target' style='background: blue; opacity: 0.0001; "
+      "will-change: opacity'></div>");
+  ExpectPaintedOutputVisibility("target", false);
+}
+
+TEST_P(PaintLayerPainterTest, DoPaintWithTinyOpacityAndBackdropFilter) {
   SetBodyInnerHTML(
       "<div id='target' style='background: blue; opacity: 0.0001;"
       "  backdrop-filter: blur(2px);'></div>");
-  PaintLayer* target_layer =
-      ToLayoutBox(GetLayoutObjectByElementId("target"))->Layer();
-  PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
-                                       kGlobalPaintNormalPhase, LayoutSize());
-  EXPECT_FALSE(
-      PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
+  ExpectPaintedOutputVisibility("target", false);
+}
+
+TEST_P(PaintLayerPainterTest,
+       DoPaintWithTinyOpacityAndBackdropFilterAndWillChangeOpacity) {
+  SetBodyInnerHTML(
+      "<div id='target' style='background: blue; opacity: 0.0001;"
+      "  backdrop-filter: blur(2px); will-change: opacity'></div>");
+  ExpectPaintedOutputVisibility("target", false);
 }
 
 TEST_P(PaintLayerPainterTest, DoPaintWithCompositedTinyOpacity) {
   SetBodyInnerHTML(
       "<div id='target' style='background: blue; opacity: 0.0001;"
       " will-change: transform'></div>");
-  PaintLayer* target_layer =
-      ToLayoutBox(GetLayoutObjectByElementId("target"))->Layer();
-  PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
-                                       kGlobalPaintNormalPhase, LayoutSize());
-  EXPECT_FALSE(
-      PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
+  ExpectPaintedOutputVisibility("target", false);
 }
 
 TEST_P(PaintLayerPainterTest, DoPaintWithNonTinyOpacity) {
   SetBodyInnerHTML(
       "<div id='target' style='background: blue; opacity: 0.1'></div>");
-  PaintLayer* target_layer =
-      ToLayoutBox(GetLayoutObjectByElementId("target"))->Layer();
-  PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
-                                       kGlobalPaintNormalPhase, LayoutSize());
-  EXPECT_FALSE(
-      PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
+  ExpectPaintedOutputVisibility("target", false);
 }
 
 TEST_P(PaintLayerPainterTest, DoPaintWithEffectAnimationZeroOpacity) {
@@ -835,15 +848,10 @@
       "} "
       "</style> "
       "<div id='target'></div>");
-  PaintLayer* target_layer =
-      ToLayoutBox(GetLayoutObjectByElementId("target"))->Layer();
-  PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
-                                       kGlobalPaintNormalPhase, LayoutSize());
-  EXPECT_FALSE(
-      PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
+  ExpectPaintedOutputVisibility("target", false);
 }
 
-TEST_P(PaintLayerPainterTest, DoNotPaintWithTransformAnimationZeroOpacity) {
+TEST_P(PaintLayerPainterTest, DontPaintWithTransformAnimationZeroOpacity) {
   SetBodyInnerHTML(
       "<style> "
       "div#target { "
@@ -857,17 +865,68 @@
       "} "
       "</style> "
       "<div id='target'>x</div></div>");
-  PaintLayer* target_layer =
-      ToLayoutBox(GetLayoutObjectByElementId("target"))->Layer();
-  PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
-                                       kGlobalPaintNormalPhase, LayoutSize());
-  if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-    EXPECT_TRUE(
-        PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
-  } else {
-    EXPECT_FALSE(
-        PaintLayerPainter(*target_layer).PaintedOutputInvisible(painting_info));
-  }
+  ExpectPaintedOutputVisibility("target", false, true);
+}
+
+TEST_P(PaintLayerPainterTest,
+       DoPaintWithTransformAnimationZeroOpacityWillChangeOpacity) {
+  SetBodyInnerHTML(
+      "<style> "
+      "div#target { "
+      "  animation-name: example; "
+      "  animation-duration: 4s; "
+      "  opacity: 0.0; "
+      "  will-change: opacity; "
+      "} "
+      "@keyframes example { "
+      " from { transform: translate(0px, 0px); } "
+      " to { transform: translate(3em, 0px); } "
+      "} "
+      "</style> "
+      "<div id='target'>x</div></div>");
+  ExpectPaintedOutputVisibility("target", false);
+}
+
+TEST_P(PaintLayerPainterTest, DoPaintWithWillChangeOpacity) {
+  SetBodyInnerHTML(
+      "<style> "
+      "div { "
+      "  width: 100px; "
+      "  height: 100px; "
+      "  will-change: opacity;"
+      "}"
+      "</style> "
+      "<div id='target'></div>");
+  ExpectPaintedOutputVisibility("target", false);
+}
+
+TEST_P(PaintLayerPainterTest, DoPaintWithZeroOpacityAndWillChangeOpacity) {
+  SetBodyInnerHTML(
+      "<style> "
+      "div { "
+      "  width: 100px; "
+      "  height: 100px; "
+      "  opacity: 0; "
+      "  will-change: opacity;"
+      "}"
+      "</style> "
+      "<div id='target'></div>");
+  ExpectPaintedOutputVisibility("target", false);
+}
+
+TEST_P(PaintLayerPainterTest,
+       DoPaintWithNoContentAndZeroOpacityAndWillChangeOpacity) {
+  SetBodyInnerHTML(
+      "<style> "
+      "div { "
+      "  width: 100px; "
+      "  height: 100px; "
+      "  opacity: 0; "
+      "  will-change: opacity;"
+      "}"
+      "</style> "
+      "<div id='target'></div>");
+  ExpectPaintedOutputVisibility("target", false);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
index 7b035be..19538f8 100644
--- a/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGImageElement.cpp
@@ -23,6 +23,8 @@
 
 #include "core/CSSPropertyNames.h"
 #include "core/dom/StyleChangeReason.h"
+#include "core/frame/ImageBitmap.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/layout/LayoutImageResource.h"
 #include "core/layout/svg/LayoutSVGImage.h"
 
diff --git a/third_party/WebKit/Source/core/svg/SVGImageElement.h b/third_party/WebKit/Source/core/svg/SVGImageElement.h
index 90fc988..b7a2260 100644
--- a/third_party/WebKit/Source/core/svg/SVGImageElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGImageElement.h
@@ -22,7 +22,7 @@
 #define SVGImageElement_h
 
 #include "core/SVGNames.h"
-#include "core/html/canvas/CanvasImageElementSource.h"
+#include "core/html/canvas/ImageElementBase.h"
 #include "core/svg/SVGAnimatedLength.h"
 #include "core/svg/SVGAnimatedPreserveAspectRatio.h"
 #include "core/svg/SVGGraphicsElement.h"
@@ -33,7 +33,7 @@
 namespace blink {
 
 class CORE_EXPORT SVGImageElement final : public SVGGraphicsElement,
-                                          public CanvasImageElementSource,
+                                          public ImageElementBase,
                                           public SVGURIReference {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(SVGImageElement);
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index c15e36f..96dfa7b 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -292,6 +292,7 @@
   "front_end/main/GCActionDelegate.js",
   "front_end/main/Main.js",
   "front_end/main/module.json",
+  "front_end/main/OverlayController.js",
   "front_end/main/remoteDebuggingTerminatedScreen.css",
   "front_end/main/renderingOptions.css",
   "front_end/main/RenderingOptions.js",
@@ -368,6 +369,7 @@
   "front_end/perf_ui/PieChart.js",
   "front_end/perf_ui/timelineGrid.css",
   "front_end/perf_ui/TimelineGrid.js",
+  "front_end/perf_ui/timelineOverviewInfo.css",
   "front_end/perf_ui/TimelineOverviewPane.js",
   "front_end/persistence/Automapping.js",
   "front_end/persistence/DefaultMapping.js",
@@ -472,7 +474,6 @@
   "front_end/sdk/module.json",
   "front_end/sdk/NetworkManager.js",
   "front_end/sdk/NetworkRequest.js",
-  "front_end/sdk/OverlayModel.js",
   "front_end/sdk/PaintProfiler.js",
   "front_end/sdk/ProfileTreeModel.js",
   "front_end/sdk/RemoteObject.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
index 884dd30..fc69390e 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
@@ -157,7 +157,7 @@
       if (!this.node())
         return;
       // Highlight and scroll into view the currently inspected node.
-      this.node().domModel().overlayModel().nodeHighlightRequested(this.node().id);
+      this.node().domModel().nodeHighlightRequested(this.node().id);
     }
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js
index 87dd668..5fe56b5 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilityModel.js
@@ -156,7 +156,7 @@
     this.deferredDOMNode().resolvePromise().then(node => {
       if (!node)
         return;
-      node.domModel().overlayModel().nodeHighlightRequested(node.id);
+      node.domModel().nodeHighlightRequested(node.id);
     });
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js b/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js
index 2b76773..5a8ddfc 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js
@@ -880,7 +880,7 @@
     }
 
     /**
-     * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
+     * @param {?Array<!Protocol.DOM.NodeId>} nodeIds
      */
     function getStyles(nodeIds) {
       if (progress.isCanceled()) {
@@ -987,8 +987,8 @@
 
     /**
      * @param {!SDK.DOMNode} root
-     * @param {!Array.<!Protocol.DOM.NodeId>=} inlineStyleNodeIds
-     * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
+     * @param {!Array<!Protocol.DOM.NodeId>} inlineStyleNodeIds
+     * @param {?Array<!Protocol.DOM.NodeId>} nodeIds
      */
     function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds) {
       if (progress.isCanceled()) {
@@ -1017,7 +1017,7 @@
 
     /**
      * @param {!SDK.DOMNode} root
-     * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
+     * @param {?Array<!Protocol.DOM.NodeId>} nodeIds
      */
     function inlineStylesReceived(root, nodeIds) {
       if (progress.isCanceled()) {
@@ -1102,7 +1102,7 @@
 
     /**
      * @param {!Array.<!Protocol.DOM.NodeId>} lateStyleIds
-     * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
+     * @param {?Array.<!Protocol.DOM.NodeId>} nodeIds
      */
     function cssBeforeInlineReceived(lateStyleIds, nodeIds) {
       if (progress.isCanceled()) {
@@ -1131,7 +1131,7 @@
 
     /**
      * @param {!SDK.DOMDocument} root
-     * @param {!Array.<!Protocol.DOM.NodeId>=} nodeIds
+     * @param {?Array<!Protocol.DOM.NodeId>} nodeIds
      */
     function lateStylesReceived(root, nodeIds) {
       if (progress.isCanceled()) {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
index 71ab24c..679710f 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
@@ -117,7 +117,7 @@
 
   link.addEventListener('click', Common.Revealer.reveal.bind(Common.Revealer, node, undefined), false);
   link.addEventListener('mouseover', node.highlight.bind(node, undefined, undefined), false);
-  link.addEventListener('mouseleave', () => SDK.OverlayModel.hideDOMNodeHighlight(), false);
+  link.addEventListener('mouseleave', SDK.DOMModel.hideDOMNodeHighlight.bind(SDK.DOMModel), false);
 
   return root;
 };
@@ -415,7 +415,8 @@
    * @return {boolean}
    */
   function isCSSIdentifier(value) {
-    return /^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value);
+    // Double hyphen prefixes are not allowed by specification, but many sites use it.
+    return /^-{0,2}[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value);
   }
 
   var prefixedOwnClassNamesArray = prefixedElementClassNames(node);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsBreadcrumbs.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsBreadcrumbs.js
index 24a45c6..67bca2f 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsBreadcrumbs.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsBreadcrumbs.js
@@ -56,7 +56,7 @@
 
   _mouseMovedOutOfCrumbs(event) {
     if (this._currentDOMNode)
-      SDK.OverlayModel.hideDOMNodeHighlight();
+      SDK.DOMModel.hideDOMNodeHighlight();
   }
 
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index 3f3c33d..aba07ef 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -330,7 +330,7 @@
   willHide() {
     UI.context.setFlavor(Elements.ElementsPanel, null);
 
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
     for (var i = 0; i < this._treeOutlines.length; ++i) {
       var treeOutline = this._treeOutlines[i];
       treeOutline.setVisible(false);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElementHighlighter.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElementHighlighter.js
index 7b7e454..f8d7034 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElementHighlighter.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElementHighlighter.js
@@ -15,9 +15,8 @@
     this._treeOutline.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._clearState, this);
     this._treeOutline.addEventListener(Elements.ElementsTreeOutline.Events.SelectedNodeChanged, this._clearState, this);
     SDK.targetManager.addModelListener(
-        SDK.OverlayModel, SDK.OverlayModel.Events.HighlightNodeRequested, this._highlightNode, this);
-    this._treeOutline.domModel().overlayModel().addEventListener(
-        SDK.OverlayModel.Events.InspectModeWillBeToggled, this._clearState, this);
+        SDK.DOMModel, SDK.DOMModel.Events.NodeHighlightedInOverlay, this._highlightNode, this);
+    this._treeOutline.domModel().addEventListener(SDK.DOMModel.Events.InspectModeWillBeToggled, this._clearState, this);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
index a0c0471..ad4fbca 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -620,20 +620,20 @@
     this.setHoverEffect(element);
 
     if (element instanceof Elements.ElementsTreeElement) {
-      this._domModel.overlayModel().highlightDOMNodeWithConfig(
+      this._domModel.highlightDOMNodeWithConfig(
           element.node().id, {mode: 'all', showInfo: !UI.KeyboardShortcut.eventHasCtrlOrMeta(event)});
       return;
     }
 
     if (element instanceof Elements.ElementsTreeOutline.ShortcutTreeElement) {
-      this._domModel.overlayModel().highlightDOMNodeWithConfig(
+      this._domModel.highlightDOMNodeWithConfig(
           undefined, {mode: 'all', showInfo: !UI.KeyboardShortcut.eventHasCtrlOrMeta(event)}, element.backendNodeId());
     }
   }
 
   _onmouseleave(event) {
     this.setHoverEffect(null);
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
   }
 
   _ondragstart(event) {
@@ -653,7 +653,7 @@
     event.dataTransfer.effectAllowed = 'copyMove';
     this._treeElementBeingDragged = treeElement;
 
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
 
     return true;
   }
@@ -971,7 +971,7 @@
     this.selectDOMNode(null, false);
     this._popoverHelper.hidePopover();
     delete this._clipboardNodeData;
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
     this._updateRecords.clear();
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js b/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js
index 0eee986..63fe1ce 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js
@@ -26,46 +26,46 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * @implements {SDK.SDKModelObserver<!SDK.OverlayModel>}
+ * @implements {SDK.SDKModelObserver<!SDK.DOMModel>}
  * @unrestricted
  */
 Elements.InspectElementModeController = class {
   constructor() {
     this._toggleSearchAction = UI.actionRegistry.action('elements.toggle-element-search');
-    this._mode = Protocol.Overlay.InspectMode.None;
+    this._mode = Protocol.DOM.InspectMode.None;
     SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
-    SDK.targetManager.observeModels(SDK.OverlayModel, this);
+    SDK.targetManager.observeModels(SDK.DOMModel, this);
   }
 
   /**
    * @override
-   * @param {!SDK.OverlayModel} overlayModel
+   * @param {!SDK.DOMModel} domModel
    */
-  modelAdded(overlayModel) {
+  modelAdded(domModel) {
     // When DevTools are opening in the inspect element mode, the first target comes in
     // much later than the InspectorFrontendAPI.enterInspectElementMode event.
-    if (this._mode === Protocol.Overlay.InspectMode.None)
+    if (this._mode === Protocol.DOM.InspectMode.None)
       return;
-    overlayModel.setInspectMode(this._mode);
+    domModel.setInspectMode(this._mode);
   }
 
   /**
    * @override
-   * @param {!SDK.OverlayModel} overlayModel
+   * @param {!SDK.DOMModel} domModel
    */
-  modelRemoved(overlayModel) {
+  modelRemoved(domModel) {
   }
 
   /**
    * @return {boolean}
    */
   isInInspectElementMode() {
-    return this._mode === Protocol.Overlay.InspectMode.SearchForNode ||
-        this._mode === Protocol.Overlay.InspectMode.SearchForUAShadowDOM;
+    return this._mode === Protocol.DOM.InspectMode.SearchForNode ||
+        this._mode === Protocol.DOM.InspectMode.SearchForUAShadowDOM;
   }
 
   stopInspection() {
-    if (this._mode && this._mode !== Protocol.Overlay.InspectMode.None)
+    if (this._mode && this._mode !== Protocol.DOM.InspectMode.None)
       this._toggleInspectMode();
   }
 
@@ -75,22 +75,22 @@
 
     var mode;
     if (this.isInInspectElementMode()) {
-      mode = Protocol.Overlay.InspectMode.None;
+      mode = Protocol.DOM.InspectMode.None;
     } else {
-      mode = Common.moduleSetting('showUAShadowDOM').get() ? Protocol.Overlay.InspectMode.SearchForUAShadowDOM :
-                                                             Protocol.Overlay.InspectMode.SearchForNode;
+      mode = Common.moduleSetting('showUAShadowDOM').get() ? Protocol.DOM.InspectMode.SearchForUAShadowDOM :
+                                                             Protocol.DOM.InspectMode.SearchForNode;
     }
 
     this._setMode(mode);
   }
 
   /**
-   * @param {!Protocol.Overlay.InspectMode} mode
+   * @param {!Protocol.DOM.InspectMode} mode
    */
   _setMode(mode) {
     this._mode = mode;
-    for (var overlayModel of SDK.targetManager.models(SDK.OverlayModel))
-      overlayModel.setInspectMode(mode);
+    for (var domModel of SDK.targetManager.models(SDK.DOMModel))
+      domModel.setInspectMode(mode);
     this._toggleSearchAction.setToggled(this.isInInspectElementMode());
   }
 
@@ -98,7 +98,7 @@
     if (!SDK.targetManager.allTargetsSuspended())
       return;
 
-    this._mode = Protocol.Overlay.InspectMode.None;
+    this._mode = Protocol.DOM.InspectMode.None;
     this._toggleSearchAction.setToggled(false);
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js
index 8e3a2b2..d9cba702 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js
@@ -124,7 +124,7 @@
       this.node().highlight(mode);
     } else {
       delete this._highlightMode;
-      SDK.OverlayModel.hideDOMNodeHighlight();
+      SDK.DOMModel.hideDOMNodeHighlight();
     }
 
     for (var i = 0; this._boxElements && i < this._boxElements.length; ++i) {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index 2c8f9e32..155b4ca 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -815,7 +815,7 @@
   _onMouseOutSelector() {
     if (this._hoverTimer)
       clearTimeout(this._hoverTimer);
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
   }
 
   _onMouseEnterSelector() {
@@ -825,11 +825,11 @@
   }
 
   _highlight() {
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
     var node = this._parentPane.node();
+    var domModel = node.domModel();
     var selectors = this._style.parentRule ? this._style.parentRule.selectorText() : undefined;
-    node.domModel().overlayModel().highlightDOMNodeWithConfig(
-        node.id, {mode: 'all', showInfo: undefined, selectors: selectors});
+    domModel.highlightDOMNodeWithConfig(node.id, {mode: 'all', showInfo: undefined, selectors: selectors});
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
index c56410ef..8f3b059 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
@@ -472,9 +472,8 @@
               this._uaSetting.get() === Emulation.DeviceModeModel.UA.Mobile,
           this._uaSetting.get() === Emulation.DeviceModeModel.UA.Mobile);
     }
-    var overlayModel = this._target ? this._target.model(SDK.OverlayModel) : null;
-    if (overlayModel)
-      overlayModel.setShowViewportSizeOnResize(this._type === Emulation.DeviceModeModel.Type.None);
+    if (this._target)
+      this._target.renderingAgent().setShowViewportSizeOnResize(this._type === Emulation.DeviceModeModel.Type.None);
     this._updateCallback.call(null);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
index 828ea98..04e9011 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
@@ -363,9 +363,9 @@
    * @return {!Promise}
    */
   async captureScreenshot() {
-    SDK.OverlayModel.muteHighlight();
+    SDK.DOMModel.muteHighlight();
     var screenshot = await this._model.captureScreenshot(false);
-    SDK.OverlayModel.unmuteHighlight();
+    SDK.DOMModel.unmuteHighlight();
     if (screenshot === null)
       return;
 
@@ -398,9 +398,9 @@
    * @return {!Promise}
    */
   async captureFullSizeScreenshot() {
-    SDK.OverlayModel.muteHighlight();
+    SDK.DOMModel.muteHighlight();
     var screenshot = await this._model.captureScreenshot(true);
-    SDK.OverlayModel.unmuteHighlight();
+    SDK.DOMModel.unmuteHighlight();
     if (screenshot === null)
       return;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js
index 883ccf6..ce997a4 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js
@@ -54,8 +54,8 @@
     if (this._customTouchEnabled)
       current = {enabled: true, configuration: 'mobile'};
 
-    var overlayModel = target.model(SDK.OverlayModel);
-    var inspectModeEnabled = overlayModel ? overlayModel.inspectModeEnabled() : false;
+    var domModel = target.model(SDK.DOMModel);
+    var inspectModeEnabled = domModel ? domModel.inspectModeEnabled() : false;
     if (inspectModeEnabled)
       current = {enabled: false, configuration: 'mobile'};
 
@@ -107,8 +107,8 @@
    * @param {!Common.Event} event
    */
   _inspectModeToggled(event) {
-    var overlayModel = /** @type {!SDK.OverlayModel} */ (event.data);
-    this._applyToTarget(overlayModel.target());
+    var domModel = /** @type {!SDK.DOMModel} */ (event.data);
+    this._applyToTarget(domModel.target());
   }
 
   /**
@@ -116,9 +116,9 @@
    * @param {!SDK.Target} target
    */
   targetAdded(target) {
-    var overlayModel = target.model(SDK.OverlayModel);
-    if (overlayModel)
-      overlayModel.addEventListener(SDK.OverlayModel.Events.InspectModeWillBeToggled, this._inspectModeToggled, this);
+    var domModel = target.model(SDK.DOMModel);
+    if (domModel)
+      domModel.addEventListener(SDK.DOMModel.Events.InspectModeWillBeToggled, this._inspectModeToggled, this);
     this._applyToTarget(target);
   }
 
@@ -127,11 +127,9 @@
    * @param {!SDK.Target} target
    */
   targetRemoved(target) {
-    var overlayModel = target.model(SDK.OverlayModel);
-    if (overlayModel) {
-      overlayModel.removeEventListener(
-          SDK.OverlayModel.Events.InspectModeWillBeToggled, this._inspectModeToggled, this);
-    }
+    var domModel = target.model(SDK.DOMModel);
+    if (domModel)
+      domModel.removeEventListener(SDK.DOMModel.Events.InspectModeWillBeToggled, this._inspectModeToggled, this);
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/ESTreeWalker.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/ESTreeWalker.js
index 38b0da84..0fb4bbe0 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/ESTreeWalker.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/ESTreeWalker.js
@@ -123,6 +123,7 @@
   'MethodDefinition': ['key', 'value'],
   'NewExpression': ['callee', 'arguments'],
   'ObjectExpression': ['properties'],
+  'ParenthesizedExpression': ['expression'],
   'Program': ['body'],
   'Property': ['key', 'value'],
   'ReturnStatement': ['argument'],
diff --git a/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js b/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js
index 640ddb4d..116e06c7 100644
--- a/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js
+++ b/third_party/WebKit/Source/devtools/front_end/formatter_worker/JavaScriptFormatter.js
@@ -51,7 +51,7 @@
     this._content = text.substring(this._fromOffset, this._toOffset);
     this._lastLineNumber = 0;
     this._tokenizer = new FormatterWorker.AcornTokenizer(this._content);
-    var ast = acorn.parse(this._content, {ranges: false, ecmaVersion: 8});
+    var ast = acorn.parse(this._content, {ranges: false, ecmaVersion: 8, preserveParens: true});
     var walker = new FormatterWorker.ESTreeWalker(this._beforeVisit.bind(this), this._afterVisit.bind(this));
     walker.walk(ast);
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerViewHost.js b/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerViewHost.js
index 7ea875e9..ff3ac68 100644
--- a/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerViewHost.js
+++ b/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerViewHost.js
@@ -255,6 +255,6 @@
       node.highlightForTwoSeconds();
       return;
     }
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index 72eb0a9..3bde351 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -197,6 +197,7 @@
     Persistence.persistence =
         new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager, Workspace.fileSystemMapping);
 
+    new Main.OverlayController();
     new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
     Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);
 
@@ -796,8 +797,7 @@
  */
 Main.Main.InspectedNodeRevealer = class {
   constructor() {
-    SDK.targetManager.addModelListener(
-        SDK.OverlayModel, SDK.OverlayModel.Events.InspectNodeRequested, this._inspectNode, this);
+    SDK.targetManager.addModelListener(SDK.DOMModel, SDK.DOMModel.Events.NodeInspected, this._inspectNode, this);
   }
 
   /**
@@ -933,6 +933,7 @@
    */
   targetAdded(target) {
     this._updateTarget(target);
+    target.renderingAgent().setShowViewportSizeOnResize(true);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/main/OverlayController.js b/third_party/WebKit/Source/devtools/front_end/main/OverlayController.js
new file mode 100644
index 0000000..e6800ce
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/main/OverlayController.js
@@ -0,0 +1,43 @@
+// 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.
+/**
+ * @unrestricted
+ */
+Main.OverlayController = class {
+  constructor() {
+    Common.moduleSetting('disablePausedStateOverlay').addChangeListener(this._updateAllOverlays, this);
+    SDK.targetManager.addModelListener(
+        SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._updateOverlay, this);
+    SDK.targetManager.addModelListener(
+        SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerResumed, this._updateOverlay, this);
+    // TODO(dgozman): we should get DebuggerResumed on navigations instead of listening to GlobalObjectCleared.
+    SDK.targetManager.addModelListener(
+        SDK.DebuggerModel, SDK.DebuggerModel.Events.GlobalObjectCleared, this._updateOverlay, this);
+    SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._updateAllOverlays, this);
+  }
+
+  _updateAllOverlays() {
+    for (var debuggerModel of SDK.targetManager.models(SDK.DebuggerModel))
+      this._updateTargetOverlay(debuggerModel);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _updateOverlay(event) {
+    this._updateTargetOverlay(/** @type {!SDK.DebuggerModel} */ (event.data));
+  }
+
+  /**
+   * @param {!SDK.DebuggerModel} debuggerModel
+   */
+  _updateTargetOverlay(debuggerModel) {
+    if (!debuggerModel.target().hasBrowserCapability())
+      return;
+    var message = debuggerModel.isPaused() && !Common.moduleSetting('disablePausedStateOverlay').get() ?
+        Common.UIString('Paused in debugger') :
+        undefined;
+    debuggerModel.target().pageAgent().configureOverlay(SDK.targetManager.allTargetsSuspended(), message);
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
index 521a8a8..8613dec 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
@@ -36,22 +36,35 @@
     super(true);
     this.registerRequiredCSS('main/renderingOptions.css');
 
-    this._appendCheckbox(
-        Common.UIString('Paint Flashing'),
-        Common.UIString('Highlights areas of the page (green) that need to be repainted'),
-        Common.moduleSetting('showPaintRects'));
-    this._appendCheckbox(
-        Common.UIString('Layer Borders'), Common.UIString('Shows layer borders (orange/olive) and tiles (cyan)'),
-        Common.moduleSetting('showDebugBorders'));
-    this._appendCheckbox(
-        Common.UIString('FPS Meter'),
-        Common.UIString('Plots frames per second, frame rate distribution, and GPU memory'),
-        Common.moduleSetting('showFPSCounter'));
-    this._appendCheckbox(
-        Common.UIString('Scrolling Performance Issues'),
-        Common.UIString(
+    /** @type {!Map.<string, !Element>} */
+    this._settings = new Map();
+
+    var options = [
+      {
+        label: Common.UIString('Paint Flashing'),
+        subtitle: Common.UIString('Highlights areas of the page (green) that need to be repainted'),
+        setterName: 'setShowPaintRects'
+      },
+      {
+        label: Common.UIString('Layer Borders'),
+        subtitle: Common.UIString('Shows layer borders (orange/olive) and tiles (cyan)'),
+        setterName: 'setShowDebugBorders'
+      },
+      {
+        label: Common.UIString('FPS Meter'),
+        subtitle: Common.UIString('Plots frames per second, frame rate distribution, and GPU memory'),
+        setterName: 'setShowFPSCounter'
+      },
+      {
+        label: Common.UIString('Scrolling Performance Issues'),
+        subtitle: Common.UIString(
             'Highlights elements (teal) that can slow down scrolling, including touch & wheel event handlers and other main-thread scrolling situations.'),
-        Common.moduleSetting('showScrollBottleneckRects'));
+        setterName: 'setShowScrollBottleneckRects'
+      }
+    ];
+    for (var i = 0; i < options.length; i++)
+      this._appendCheckbox(options[i].label, options[i].setterName, options[i].subtitle);
+
     this.contentElement.createChild('div').classList.add('panel-section-separator');
 
     var cssMediaSubtitle = Common.UIString('Forces media type for testing print and screen styles');
@@ -67,7 +80,7 @@
     this._mediaSelect.addEventListener('change', this._mediaToggled.bind(this), false);
     this._mediaSelect.disabled = true;
 
-    SDK.targetManager.observeTargets(this);
+    SDK.targetManager.observeTargets(this, SDK.Target.Capability.Browser);
   }
 
   /**
@@ -81,21 +94,35 @@
 
   /**
    * @param {string} label
-   * @param {string} subtitle
-   * @param {!Common.Setting} setting
+   * @param {string} setterName
+   * @param {string=} subtitle
    */
-  _appendCheckbox(label, subtitle, setting) {
+  _appendCheckbox(label, setterName, subtitle) {
     var checkboxLabel = UI.CheckboxLabel.create(label, false, subtitle);
-    UI.SettingsUI.bindCheckbox(checkboxLabel.checkboxElement, setting);
+    this._settings.set(setterName, checkboxLabel.checkboxElement);
+    checkboxLabel.checkboxElement.addEventListener('click', this._settingToggled.bind(this, setterName));
     this.contentElement.appendChild(checkboxLabel);
   }
 
   /**
+   * @param {string} setterName
+   */
+  _settingToggled(setterName) {
+    var enabled = this._settings.get(setterName).checked;
+    for (var target of SDK.targetManager.targets(SDK.Target.Capability.Browser))
+      target.renderingAgent()[setterName](enabled);
+  }
+
+  /**
    * @override
    * @param {!SDK.Target} target
    */
   targetAdded(target) {
-    if (this._mediaCheckbox.checked && target.hasBrowserCapability())
+    for (var setterName of this._settings.keysArray()) {
+      if (this._settings.get(setterName).checked)
+        target.renderingAgent()[setterName](true);
+    }
+    if (this._mediaCheckbox.checked)
       this._applyPrintMediaOverride(target);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/main/module.json b/third_party/WebKit/Source/devtools/front_end/main/module.json
index c07180d6..9e5a909 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/main/module.json
@@ -450,6 +450,7 @@
     "scripts": [
         "RenderingOptions.js",
         "SimpleApp.js",
+        "OverlayController.js",
         "GCActionDelegate.js",
         "RequestAppBannerActionDelegate.js",
         "ExecutionContextSelector.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index 015fb7d..a602a1f 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -46,6 +46,71 @@
     this._requestOrFirstKnownChildRequest = null;
     /** @type {!Map<string, !UI.Icon>} */
     this._columnIcons = new Map();
+    /** @type {?Common.Color} */
+    this._backgroundColor = null;
+  }
+
+  /**
+   * @return {!Network.NetworkNode._SupportedBackgroundColors}
+   */
+  static _themedBackgroundColors() {
+    if (Network.NetworkNode._themedBackgroundColorsCache)
+      return Network.NetworkNode._themedBackgroundColorsCache;
+    var themedColors = {};
+    for (var name in Network.NetworkNode._backgroundColors) {
+      var color = Common.Color.fromRGBA(Network.NetworkNode._backgroundColors[name]);
+      themedColors[name] = UI.themeSupport.patchColor(color, UI.ThemeSupport.ColorUsage.Background);
+    }
+    Network.NetworkNode._themedBackgroundColorsCache =
+        /** @type {!Network.NetworkNode._SupportedBackgroundColors} */ (themedColors);
+    return Network.NetworkNode._themedBackgroundColorsCache;
+  }
+
+  /**
+   * @return {string}
+   */
+  backgroundColor() {
+    var bgColors = Network.NetworkNode._themedBackgroundColors();
+    var color = this.isStriped() ? bgColors.Stripe : bgColors.Default;
+    if (this.isNavigationRequest())
+      color = color.blendWith(bgColors.Navigation);
+    if (this.hovered())
+      color = color.blendWith(bgColors.Hovered);
+    if (this._backgroundColor)
+      color = color.blendWith(this._backgroundColor);
+    if (this.isOnInitiatorPath())
+      color = color.blendWith(bgColors.InitiatorPath);
+    if (this.isOnInitiatedPath())
+      color = color.blendWith(bgColors.InitiatedPath);
+    if (this.selected)
+      color = color.blendWith(bgColors.Selected);
+
+    return /** @type {string} */ (color.asString(Common.Color.Format.HEX));
+  }
+
+  /**
+   * @param {?Common.Color} color
+   */
+  setBackgroundColor(color) {
+    this._backgroundColor = color;
+    this._updateBackgroundColor();
+  }
+
+  _updateBackgroundColor() {
+    var element = this.existingElement();
+    if (!element)
+      return;
+    element.style.backgroundColor = this.backgroundColor();
+    this._parentView.stylesChanged();
+  }
+
+  /**
+   * @override
+   * @param {boolean} isStriped
+   */
+  setStriped(isStriped) {
+    super.setStriped(isStriped);
+    this._updateBackgroundColor();
   }
 
   /**
@@ -101,6 +166,7 @@
       this.showingInitiatorChainChanged();
     }
     this._parentView.stylesChanged();
+    this._updateBackgroundColor();
   }
 
   /**
@@ -184,6 +250,31 @@
   }
 };
 
+/** @type {!Object<string, !Array<number>>} */
+Network.NetworkNode._backgroundColors = {
+  Default: [255, 255, 255, 1.0],
+  Stripe: [245, 245, 245, 1.0],
+  Navigation: [221, 238, 255, 1.0],
+  Hovered: [235, 242, 252, 0.7],
+  InitiatorPath: [58, 217, 58, 0.4],
+  InitiatedPath: [217, 58, 58, 0.4],
+  Selected: [63, 81, 181, .6]
+};
+
+/** @typedef {!{
+  Default: !Common.Color,
+  Stripe: !Common.Color,
+  Navigation: !Common.Color,
+  Hovered: !Common.Color,
+  InitiatorPath: !Common.Color,
+  InitiatedPath: !Common.Color,
+  Selected: !Common.Color
+}} */
+Network.NetworkNode._SupportedBackgroundColors;
+
+/** @type {!Network.NetworkNode._SupportedBackgroundColors} */
+Network.NetworkNode._themedBackgroundColorsCache;
+
 /**
  * @unrestricted
  */
@@ -524,7 +615,7 @@
     if (this._isOnInitiatorPath === isOnInitiatorPath || !this.attached())
       return;
     this._isOnInitiatorPath = isOnInitiatorPath;
-    this.element().classList.toggle('network-node-on-initiator-path', isOnInitiatorPath);
+    this._updateBackgroundColor();
   }
 
   /**
@@ -542,7 +633,7 @@
     if (this._isOnInitiatedPath === isOnInitiatedPath || !this.attached())
       return;
     this._isOnInitiatedPath = isOnInitiatedPath;
-    this.element().classList.toggle('network-node-on-initiated-path', isOnInitiatedPath);
+    this._updateBackgroundColor();
   }
 
   /**
@@ -594,6 +685,7 @@
   markAsNavigationRequest() {
     this._isNavigationRequest = true;
     this.refresh();
+    this._updateBackgroundColor();
   }
 
   /**
@@ -617,6 +709,7 @@
     for (var rowDecorator of this._parentView.rowDecorators())
       rowDecorator.decorate(this);
     super.createCells(element);
+    this._updateBackgroundColor();
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js
index d20bf03..fd8bdcb 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js
@@ -49,14 +49,6 @@
     /** @type {(number|undefined)} */
     this._updateRequestID;
 
-    var colorUsage = UI.ThemeSupport.ColorUsage;
-    this._rowNavigationRequestColor = UI.themeSupport.patchColorText('#def', colorUsage.Background);
-    this._rowStripeColor = UI.themeSupport.patchColorText('#f5f5f5', colorUsage.Background);
-    this._rowHoverColor = UI.themeSupport.patchColorText(
-        '#ebf2fc', /** @type {!UI.ThemeSupport.ColorUsage} */ (colorUsage.Background | colorUsage.Selection));
-    this._parentInitiatorColor = UI.themeSupport.patchColorText('hsla(120, 68%, 54%, 0.2)', colorUsage.Background);
-    this._initiatedColor = UI.themeSupport.patchColorText('hsla(0, 68%, 54%, 0.2)', colorUsage.Background);
-
     this.element.addEventListener('mousemove', this._onMouseMove.bind(this), true);
     this.element.addEventListener('mouseleave', event => this._setHoveredNode(null, false), true);
 
@@ -593,38 +585,12 @@
    * @param {number} y
    */
   _decorateRow(context, node, y) {
-    var isStriped = node.isStriped();
-    if (!isStriped && !node.hovered() && !node.isNavigationRequest() && !node.isOnInitiatorPath() &&
-        !node.isOnInitiatedPath())
-      return;
-
-    var color = getRowColor.call(this);
-    if (color === 'transparent')
-      return;
     context.save();
     context.beginPath();
-    context.fillStyle = color;
+    context.fillStyle = node.backgroundColor();
     context.rect(0, y, this._offsetWidth, this._rowHeight);
     context.fill();
     context.restore();
-
-    /**
-     * @return {string}
-     * @this {Network.NetworkWaterfallColumn}
-     */
-    function getRowColor() {
-      if (node.hovered())
-        return this._rowHoverColor;
-      if (node.isOnInitiatorPath())
-        return this._parentInitiatorColor;
-      if (node.isOnInitiatedPath())
-        return this._initiatedColor;
-      if (node.isNavigationRequest())
-        return this._rowNavigationRequestColor;
-      if (!isStriped)
-        return 'transparent';
-      return this._rowStripeColor;
-    }
   }
 };
 
@@ -632,4 +598,4 @@
 Network.NetworkWaterfallColumn._LayerStyle;
 
 /** @typedef {!{x: number, y: number, text: string}} */
-Network.NetworkWaterfallColumn._TextLayer;
\ No newline at end of file
+Network.NetworkWaterfallColumn._TextLayer;
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 5c58da1a..37842b76 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/networkLogView.css
+++ b/third_party/WebKit/Source/devtools/front_end/network/networkLogView.css
@@ -56,15 +56,6 @@
     background: transparent;
 }
 
-.network-log-grid .odd {
-    background: #f5f5f5;
-}
-
-.network-log-grid .network-navigation-row,
-.network-log-grid .network-navigation-row.odd {
-    background: #def;
-}
-
 .network-log-grid.data-grid td {
     height: 41px;
     border-left: 1px solid #e1e1e1;
@@ -106,7 +97,6 @@
 
 .network-log-grid.data-grid select {
     -webkit-appearance: none;
-    background-color: transparent;
     border: none;
     width: 100%;
     color: inherit;
@@ -315,18 +305,6 @@
     overflow: hidden;
 }
 
-.network-log-grid.data-grid .data-container tr:not(.data-grid-filler-row):not(.selected).hover {
-    background-color: #ebf2fc;
-}
-
-.network-log-grid .network-node-on-initiator-path {
-    background-color: hsla(120, 68%, 54%, 0.2) !important;
-}
-
-.network-log-grid .network-node-on-initiated-path {
-    background-color: hsla(0, 68%, 54%, 0.2) !important;
-}
-
 .network-status-pane {
     color: #777;
     background-color: white;
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPopoverHelper.js b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPopoverHelper.js
index 40ed2d4..29c1533 100644
--- a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPopoverHelper.js
+++ b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPopoverHelper.js
@@ -40,7 +40,7 @@
 
   dispose() {
     if (this._resultHighlightedAsDOM)
-      SDK.OverlayModel.hideDOMNodeHighlight();
+      SDK.DOMModel.hideDOMNodeHighlight();
     if (this._linkifier)
       this._linkifier.dispose();
   }
@@ -131,7 +131,7 @@
       var linkifier = null;
       var resultHighlightedAsDOM = false;
       if (result.subtype === 'node') {
-        SDK.OverlayModel.highlightObjectAsDOMNode(result);
+        SDK.DOMModel.highlightObjectAsDOMNode(result);
         resultHighlightedAsDOM = true;
       }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
index abc625e..f0558a0 100644
--- a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -306,8 +306,8 @@
         Common.Revealer.reveal(value);
         event.consume(true);
       }, false);
-      valueElement.addEventListener('mousemove', () => SDK.OverlayModel.highlightObjectAsDOMNode(value), false);
-      valueElement.addEventListener('mouseleave', () => SDK.OverlayModel.hideDOMNodeHighlight(), false);
+      valueElement.addEventListener('mousemove', () => SDK.DOMModel.highlightObjectAsDOMNode(value), false);
+      valueElement.addEventListener('mouseleave', () => SDK.DOMModel.hideDOMNodeHighlight(), false);
       return valueElement;
     }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
index fd984c3..5541156 100644
--- a/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
@@ -53,10 +53,7 @@
     this._overviewControls = [];
     this._markers = new Map();
 
-    this._popoverHelper = new UI.PopoverHelper(this._cursorArea, this._getPopoverRequest.bind(this));
-    this._popoverHelper.setHasPadding(true);
-    this._popoverHelper.setTimeout(0, 0, true);
-
+    this._overviewInfo = new PerfUI.TimelineOverviewPane.OverviewInfo(this._cursorElement);
     this._updateThrottler = new Common.Throttler(100);
 
     this._cursorEnabled = false;
@@ -66,30 +63,6 @@
 
   /**
    * @param {!Event} event
-   * @return {?UI.PopoverRequest}
-   */
-  _getPopoverRequest(event) {
-    return {
-      box: this._cursorElement.boxInWindow(),
-      show: popover => this._buildPopoverContents().then(fragment => {
-        if (!fragment.firstChild)
-          return false;
-        var content = new PerfUI.TimelineOverviewPane.PopoverContents();
-        this._popoverContents = content.contentElement.createChild('div');
-        this._popoverContents.appendChild(fragment);
-        this._popover = popover;
-        content.show(popover.contentElement);
-        return true;
-      }),
-      hide: () => {
-        this._popover = null;
-        this._popoverContents = null;
-      }
-    };
-  }
-
-  /**
-   * @param {!Event} event
    */
   _onMouseMove(event) {
     if (!this._cursorEnabled)
@@ -97,46 +70,25 @@
     this._cursorPosition = event.offsetX + event.target.offsetLeft;
     this._cursorElement.style.left = this._cursorPosition + 'px';
     this._cursorElement.style.visibility = 'visible';
-    if (!this._popover)
-      return;
-    this._buildPopoverContents().then(updatePopover.bind(this));
-    this._popover.setContentAnchorBox(this._cursorElement.boxInWindow());
-
-    /**
-     * @param {!DocumentFragment} fragment
-     * @this {PerfUI.TimelineOverviewPane}
-     */
-    function updatePopover(fragment) {
-      if (!this._popoverContents)
-        return;
-      this._popoverContents.removeChildren();
-      this._popoverContents.appendChild(fragment);
-    }
+    this._buildOverviewInfo().then(content => this._overviewInfo.setContent(content));
   }
 
   /**
    * @return {!Promise<!DocumentFragment>}
    */
-  _buildPopoverContents() {
+  async _buildOverviewInfo() {
     var document = this.element.ownerDocument;
     var x = this._cursorPosition;
-    var promises = this._overviewControls.map(control => control.popoverElementPromise(x));
-    return Promise.all(promises).then(buildFragment);
-
-    /**
-     * @param {!Array<?Element>} elements
-     * @return {!DocumentFragment}
-     */
-    function buildFragment(elements) {
-      var fragment = document.createDocumentFragment();
-      elements.remove(null);
-      fragment.appendChildren.apply(fragment, elements);
-      return fragment;
-    }
+    var elements = await Promise.all(this._overviewControls.map(control => control.overviewInfoPromise(x)));
+    var fragment = document.createDocumentFragment();
+    elements.remove(null);
+    fragment.appendChildren.apply(fragment, elements);
+    return fragment;
   }
 
   _hideCursor() {
     this._cursorElement.style.visibility = 'hidden';
+    this._overviewInfo.hide();
   }
 
   /**
@@ -150,7 +102,7 @@
    * @override
    */
   willHide() {
-    this._popoverHelper.hidePopover();
+    this._overviewInfo.hide();
   }
 
   /**
@@ -245,9 +197,9 @@
     this._cursorEnabled = false;
     this._hideCursor();
     this._markers = new Map();
-    for (var i = 0; i < this._overviewControls.length; ++i)
-      this._overviewControls[i].reset();
-    this._popoverHelper.hidePopover();
+    for (var control of this._overviewControls)
+      control.reset();
+    this._overviewInfo.hide();
     this.scheduleUpdate();
   }
 
@@ -256,11 +208,7 @@
    * @return {boolean}
    */
   _onClick(event) {
-    for (var overviewControl of this._overviewControls) {
-      if (overviewControl.onClick(event))
-        return true;
-    }
-    return false;
+    return this._overviewControls.some(control => control.onClick(event));
   }
 
   /**
@@ -301,7 +249,6 @@
   _updateWindow() {
     if (!this._overviewControls.length)
       return;
-
     var absoluteMin = this._overviewCalculator.minimumBoundary();
     var timeSpan = this._overviewCalculator.maximumBoundary() - absoluteMin;
     var haveRecords = absoluteMin > 0;
@@ -319,16 +266,6 @@
 };
 
 /**
- * @unrestricted
- */
-PerfUI.TimelineOverviewPane.PopoverContents = class extends UI.VBox {
-  constructor() {
-    super(true);
-    this.contentElement.classList.add('timeline-overview-popover');
-  }
-};
-
-/**
  * @implements {PerfUI.TimelineGrid.Calculator}
  * @unrestricted
  */
@@ -439,7 +376,7 @@
    * @param {number} x
    * @return {!Promise<?Element>}
    */
-  popoverElementPromise(x) {},
+  overviewInfoPromise(x) {},
 
   /**
    * @param {!Event} event
@@ -509,7 +446,7 @@
    * @param {number} x
    * @return {!Promise<?Element>}
    */
-  popoverElementPromise(x) {
+  overviewInfoPromise(x) {
     return Promise.resolve(/** @type {?Element} */ (null));
   }
 
@@ -534,3 +471,34 @@
     this._canvas.height = this.element.clientHeight * window.devicePixelRatio;
   }
 };
+
+PerfUI.TimelineOverviewPane.OverviewInfo = class {
+  /**
+   * @param {!Element} anchor
+   */
+  constructor(anchor) {
+    this._anchorElement = anchor;
+    this._glassPane = new UI.GlassPane();
+    this._glassPane.setBlockPointerEvents(false);
+    this._glassPane.setMarginBehavior(UI.GlassPane.MarginBehavior.NoMargin);
+    this._glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
+    this._element =
+        UI.createShadowRootWithCoreStyles(this._glassPane.contentElement, 'perf_ui/timelineOverviewInfo.css')
+            .createChild('div', 'overview-info');
+  }
+
+  /**
+   * @param {!DocumentFragment} content
+   */
+  setContent(content) {
+    this._element.removeChildren();
+    this._element.appendChild(content);
+    this._glassPane.setContentAnchorBox(this._anchorElement.boxInWindow());
+    if (!this._glassPane.isShowing())
+      this._glassPane.show(/** @type {!Document} */ (this._anchorElement.ownerDocument));
+  }
+
+  hide() {
+    this._glassPane.hide();
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json b/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json
index 96050a3..ce804b90 100644
--- a/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/module.json
@@ -29,6 +29,7 @@
         "flameChart.css",
         "overviewGrid.css",
         "pieChart.css",
-        "timelineGrid.css"
+        "timelineGrid.css",
+        "timelineOverviewInfo.css"
     ]
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css b/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css
new file mode 100644
index 0000000..0799e94
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/timelineOverviewInfo.css
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+.overview-info {
+    display: flex;
+    background: white;
+    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0, 0, 0, 0.1);
+    pointer-events: none;
+}
+
+.overview-info .frame .time {
+    display: none;
+}
+
+.overview-info .frame .thumbnail img {
+    max-width: 400px;
+    max-height: 500px;
+}
+
+
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js
index 2ffe0362..047cb83 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js
@@ -155,17 +155,18 @@
     this._panel.showCategoryView(this.titleAsText());
 
     this.listItemElement.classList.remove('hovered');
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
     return false;
   }
 
   set hovered(hovered) {
     if (hovered) {
       this.listItemElement.classList.add('hovered');
-      this._frame.resourceTreeModel().domModel().overlayModel().highlightFrame(this._frameId);
+      var domModel = this._frame.resourceTreeModel().domModel();
+      domModel.highlightFrame(this._frameId);
     } else {
       this.listItemElement.classList.remove('hovered');
-      SDK.OverlayModel.hideDOMNodeHighlight();
+      SDK.DOMModel.hideDOMNodeHighlight();
     }
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
index a1250e9..91bbe66 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * @implements {SDK.OverlayModel.Highlighter}
+ * @implements {SDK.DOMNodeHighlighter}
  * @unrestricted
  */
 Screencast.ScreencastView = class extends UI.VBox {
@@ -39,7 +39,6 @@
     super();
     this._screenCaptureModel = screenCaptureModel;
     this._domModel = screenCaptureModel.target().model(SDK.DOMModel);
-    this._overlayModel = screenCaptureModel.target().model(SDK.OverlayModel);
     this._resourceTreeModel = screenCaptureModel.target().model(SDK.ResourceTreeModel);
     this._networkManager = screenCaptureModel.target().model(SDK.NetworkManager);
     this._inputModel = screenCaptureModel.target().model(Screencast.InputModel);
@@ -131,8 +130,8 @@
         Math.floor(Math.min(maxImageDimension, dimensions.height)), undefined, this._screencastFrame.bind(this),
         this._screencastVisibilityChanged.bind(this));
     Emulation.MultitargetTouchModel.instance().setCustomTouchEnabled(true);
-    if (this._overlayModel)
-      this._overlayModel.setHighlighter(this);
+    if (this._domModel)
+      this._domModel.setHighlighter(this);
   }
 
   _stopCasting() {
@@ -141,8 +140,8 @@
     this._isCasting = false;
     this._screenCaptureModel.stopScreencast();
     Emulation.MultitargetTouchModel.instance().setCustomTouchEnabled(false);
-    if (this._overlayModel)
-      this._overlayModel.setHighlighter(null);
+    if (this._domModel)
+      this._domModel.setHighlighter(null);
   }
 
   /**
@@ -246,7 +245,7 @@
         return;
       if (event.type === 'mousemove') {
         this.highlightDOMNode(node, this._inspectModeConfig);
-        this._domModel.overlayModel().nodeHighlightRequested(node.id);
+        this._domModel.nodeHighlightRequested(node.id);
       } else if (event.type === 'click') {
         Common.Revealer.reveal(node);
       }
@@ -317,7 +316,7 @@
   /**
    * @override
    * @param {?SDK.DOMNode} node
-   * @param {?Protocol.Overlay.HighlightConfig} config
+   * @param {?Protocol.DOM.HighlightConfig} config
    * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
    * @param {!Protocol.Runtime.RemoteObjectId=} objectId
    */
@@ -570,13 +569,14 @@
 
   /**
    * @override
-   * @param {!Protocol.Overlay.InspectMode} mode
-   * @param {!Protocol.Overlay.HighlightConfig} config
-   * @return {!Promise}
+   * @param {!Protocol.DOM.InspectMode} mode
+   * @param {!Protocol.DOM.HighlightConfig} config
+   * @param {function(?Protocol.Error)=} callback
    */
-  setInspectMode(mode, config) {
-    this._inspectModeConfig = mode !== Protocol.Overlay.InspectMode.None ? config : null;
-    return Promise.resolve();
+  setInspectMode(mode, config, callback) {
+    this._inspectModeConfig = mode !== Protocol.DOM.InspectMode.None ? config : null;
+    if (callback)
+      callback(null);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js
index f4cc534c..061af7ee 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js
@@ -214,7 +214,7 @@
      * @param {!SDK.DOMNode} node
      * @param {string} selectorText
      * @param {function()} callback
-     * @param {!Array.<!Protocol.DOM.NodeId>=} matchingNodeIds
+     * @param {?Array<!Protocol.DOM.NodeId>} matchingNodeIds
      * @this {SDK.CSSMatchedStyles}
      */
     function onQueryComplete(node, selectorText, callback, matchingNodeIds) {
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CookieModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CookieModel.js
index 5920342..d9d958d 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CookieModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CookieModel.js
@@ -90,7 +90,7 @@
 
   /**
    * @param {!SDK.Cookie} cookie
-   * @param {function(?Protocol.Error, ?)=} callback
+   * @param {function(?Protocol.Error, boolean)} callback
    */
   saveCookie(cookie, callback) {
     var domain = cookie.domain();
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
index 9eb2626..7780a00 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -840,11 +840,11 @@
    * @param {!Protocol.Runtime.RemoteObjectId=} objectId
    */
   highlight(mode, objectId) {
-    this._domModel.overlayModel().highlightDOMNode(this.id, mode, undefined, objectId);
+    this._domModel.highlightDOMNode(this.id, mode, undefined, objectId);
   }
 
   highlightForTwoSeconds() {
-    this._domModel.overlayModel().highlightDOMNodeForTwoSeconds(this.id);
+    this._domModel.highlightDOMNodeForTwoSeconds(this.id);
   }
 
   /**
@@ -1011,7 +1011,7 @@
 
   highlight() {
     if (this._domModel)
-      this._domModel.overlayModel().highlightDOMNode(undefined, undefined, this._backendNodeId);
+      this._domModel.highlightDOMNode(undefined, undefined, this._backendNodeId);
   }
 };
 
@@ -1068,8 +1068,12 @@
     this._attributeLoadNodeIds = {};
     target.registerDOMDispatcher(new SDK.DOMDispatcher(this));
 
+    this._inspectModeEnabled = false;
     this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
 
+    this._defaultHighlighter = new SDK.DefaultDOMNodeHighlighter(this._agent);
+    this._highlighter = this._defaultHighlighter;
+
     this._agent.enable();
   }
 
@@ -1088,10 +1092,26 @@
   }
 
   /**
-   * @return {!SDK.OverlayModel}
+   * @param {!SDK.RemoteObject} object
    */
-  overlayModel() {
-    return /** @type {!SDK.OverlayModel} */ (this.target().model(SDK.OverlayModel));
+  static highlightObjectAsDOMNode(object) {
+    var domModel = object.runtimeModel().target().model(SDK.DOMModel);
+    if (domModel)
+      domModel.highlightDOMNode(undefined, undefined, undefined, object.objectId);
+  }
+
+  static hideDOMNodeHighlight() {
+    for (var domModel of SDK.targetManager.models(SDK.DOMModel))
+      domModel.highlightDOMNode(0);
+  }
+
+  static muteHighlight() {
+    SDK.DOMModel.hideDOMNodeHighlight();
+    SDK.DOMModel._highlightDisabled = true;
+  }
+
+  static unmuteHighlight() {
+    SDK.DOMModel._highlightDisabled = false;
   }
 
   static cancelSearch() {
@@ -1183,7 +1203,7 @@
 
   /**
    * @param {string} path
-   * @param {function(?number)=} callback
+   * @param {function(?number)} callback
    */
   pushNodeByPathToFrontend(path, callback) {
     this._dispatchWhenDocumentAvailable(this._agent.pushNodeByPathToFrontend.bind(this._agent, path), callback);
@@ -1217,28 +1237,26 @@
   }
 
   /**
-   * @param {function(!T)=} callback
-   * @return {function(?Protocol.Error, !T=)|undefined}
+   * @param {function(?T)} callback
+   * @return {function(?Protocol.Error, !T=)}
    * @template T
    */
   _wrapClientCallback(callback) {
-    if (!callback)
-      return;
     /**
      * @param {?Protocol.Error} error
      * @param {!T=} result
      * @template T
      */
-    var wrapper = function(error, result) {
+    function wrapper(error, result) {
       // Caller is responsible for handling the actual error.
-      callback(error ? null : result);
-    };
+      callback(error ? null : result || null);
+    }
     return wrapper;
   }
 
   /**
-   * @param {function(function(?Protocol.Error, !T=)=)} func
-   * @param {function(!T)=} callback
+   * @param {function(function(?Protocol.Error, !T))} func
+   * @param {function(?T)} callback
    * @template T
    */
   _dispatchWhenDocumentAvailable(func, callback) {
@@ -1521,6 +1539,14 @@
   }
 
   /**
+   * @param {!Protocol.DOM.BackendNodeId} backendNodeId
+   */
+  _inspectNodeRequested(backendNodeId) {
+    var deferredNode = new SDK.DeferredDOMNode(this.target(), backendNodeId);
+    this.dispatchEventToListeners(SDK.DOMModel.Events.NodeInspected, deferredNode);
+  }
+
+  /**
    * @param {string} query
    * @param {boolean} includeUserAgentShadowDOM
    * @param {function(number)} searchCallback
@@ -1635,7 +1661,7 @@
   /**
    * @param {!Protocol.DOM.NodeId} nodeId
    * @param {string} selectors
-   * @param {function(?Protocol.DOM.NodeId)=} callback
+   * @param {function(?Protocol.DOM.NodeId)} callback
    */
   querySelector(nodeId, selectors, callback) {
     this._agent.querySelector(nodeId, selectors, this._wrapClientCallback(callback));
@@ -1644,13 +1670,114 @@
   /**
    * @param {!Protocol.DOM.NodeId} nodeId
    * @param {string} selectors
-   * @param {function(!Array.<!Protocol.DOM.NodeId>=)=} callback
+   * @param {function(?Array<!Protocol.DOM.NodeId>)} callback
    */
   querySelectorAll(nodeId, selectors, callback) {
     this._agent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback));
   }
 
   /**
+   * @param {!Protocol.DOM.NodeId=} nodeId
+   * @param {string=} mode
+   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
+   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
+   */
+  highlightDOMNode(nodeId, mode, backendNodeId, objectId) {
+    this.highlightDOMNodeWithConfig(nodeId, {mode: mode}, backendNodeId, objectId);
+  }
+
+  /**
+   * @param {!Protocol.DOM.NodeId=} nodeId
+   * @param {!{mode: (string|undefined), showInfo: (boolean|undefined), selectors: (string|undefined)}=} config
+   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
+   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
+   */
+  highlightDOMNodeWithConfig(nodeId, config, backendNodeId, objectId) {
+    if (SDK.DOMModel._highlightDisabled)
+      return;
+    config = config || {mode: 'all', showInfo: undefined, selectors: undefined};
+    if (this._hideDOMNodeHighlightTimeout) {
+      clearTimeout(this._hideDOMNodeHighlightTimeout);
+      delete this._hideDOMNodeHighlightTimeout;
+    }
+    var highlightConfig = this._buildHighlightConfig(config.mode);
+    if (typeof config.showInfo !== 'undefined')
+      highlightConfig.showInfo = config.showInfo;
+    if (typeof config.selectors !== 'undefined')
+      highlightConfig.selectorList = config.selectors;
+    this._highlighter.highlightDOMNode(this.nodeForId(nodeId || 0), highlightConfig, backendNodeId, objectId);
+  }
+
+  /**
+   * @param {!Protocol.DOM.NodeId} nodeId
+   */
+  highlightDOMNodeForTwoSeconds(nodeId) {
+    this.highlightDOMNode(nodeId);
+    this._hideDOMNodeHighlightTimeout = setTimeout(SDK.DOMModel.hideDOMNodeHighlight.bind(SDK.DOMModel), 2000);
+  }
+
+  /**
+   * @param {!Protocol.Page.FrameId} frameId
+   */
+  highlightFrame(frameId) {
+    if (SDK.DOMModel._highlightDisabled)
+      return;
+    this._highlighter.highlightFrame(frameId);
+  }
+
+  /**
+   * @param {!Protocol.DOM.InspectMode} mode
+   * @param {function(?Protocol.Error)=} callback
+   */
+  setInspectMode(mode, callback) {
+    /**
+     * @this {SDK.DOMModel}
+     */
+    function onDocumentAvailable() {
+      this._inspectModeEnabled = mode !== Protocol.DOM.InspectMode.None;
+      this.dispatchEventToListeners(SDK.DOMModel.Events.InspectModeWillBeToggled, this);
+      this._highlighter.setInspectMode(mode, this._buildHighlightConfig(), callback);
+    }
+    this.requestDocument(onDocumentAvailable.bind(this));
+  }
+
+  /**
+   * @return {boolean}
+   */
+  inspectModeEnabled() {
+    return this._inspectModeEnabled;
+  }
+
+  /**
+   * @param {string=} mode
+   * @return {!Protocol.DOM.HighlightConfig}
+   */
+  _buildHighlightConfig(mode) {
+    mode = mode || 'all';
+    var showRulers = Common.moduleSetting('showMetricsRulers').get();
+    var highlightConfig = {showInfo: mode === 'all', showRulers: showRulers, showExtensionLines: showRulers};
+    if (mode === 'all' || mode === 'content')
+      highlightConfig.contentColor = Common.Color.PageHighlight.Content.toProtocolRGBA();
+
+    if (mode === 'all' || mode === 'padding')
+      highlightConfig.paddingColor = Common.Color.PageHighlight.Padding.toProtocolRGBA();
+
+    if (mode === 'all' || mode === 'border')
+      highlightConfig.borderColor = Common.Color.PageHighlight.Border.toProtocolRGBA();
+
+    if (mode === 'all' || mode === 'margin')
+      highlightConfig.marginColor = Common.Color.PageHighlight.Margin.toProtocolRGBA();
+
+    if (mode === 'all') {
+      highlightConfig.eventTargetColor = Common.Color.PageHighlight.EventTarget.toProtocolRGBA();
+      highlightConfig.shapeColor = Common.Color.PageHighlight.Shape.toProtocolRGBA();
+      highlightConfig.shapeMarginColor = Common.Color.PageHighlight.ShapeMargin.toProtocolRGBA();
+      highlightConfig.displayAsMaterial = true;
+    }
+    return highlightConfig;
+  }
+
+  /**
    * @param {!SDK.DOMNode} node
    * @param {function(?Protocol.Error, ...)=} callback
    * @return {function(...)}
@@ -1690,6 +1817,13 @@
   }
 
   /**
+   * @param {?SDK.DOMNodeHighlighter} highlighter
+   */
+  setHighlighter(highlighter) {
+    this._highlighter = highlighter || this._defaultHighlighter;
+  }
+
+  /**
    * @param {number} x
    * @param {number} y
    * @param {boolean} includeUserAgentShadowDOM
@@ -1764,6 +1898,17 @@
       this._agent.enable(fulfill);
     }
   }
+
+  /**
+   * @param {!Protocol.DOM.NodeId} nodeId
+   */
+  nodeHighlightRequested(nodeId) {
+    var node = this.nodeForId(nodeId);
+    if (!node)
+      return;
+
+    this.dispatchEventToListeners(SDK.DOMModel.Events.NodeHighlightedInOverlay, node);
+  }
 };
 
 SDK.SDKModel.register(SDK.DOMModel, SDK.Target.Capability.DOM, true);
@@ -1775,10 +1920,13 @@
   CharacterDataModified: Symbol('CharacterDataModified'),
   DOMMutated: Symbol('DOMMutated'),
   NodeInserted: Symbol('NodeInserted'),
+  NodeInspected: Symbol('NodeInspected'),
+  NodeHighlightedInOverlay: Symbol('NodeHighlightedInOverlay'),
   NodeRemoved: Symbol('NodeRemoved'),
   DocumentUpdated: Symbol('DocumentUpdated'),
   ChildNodeCountUpdated: Symbol('ChildNodeCountUpdated'),
   DistributedNodesChanged: Symbol('DistributedNodesChanged'),
+  InspectModeWillBeToggled: Symbol('InspectModeWillBeToggled'),
   MarkersChanged: Symbol('MarkersChanged')
 };
 
@@ -1805,6 +1953,14 @@
   /**
    * @override
    * @param {!Protocol.DOM.NodeId} nodeId
+   */
+  inspectNodeRequested(nodeId) {
+    this._domModel._inspectNodeRequested(nodeId);
+  }
+
+  /**
+   * @override
+   * @param {!Protocol.DOM.NodeId} nodeId
    * @param {string} name
    * @param {string} value
    */
@@ -1919,4 +2075,86 @@
   distributedNodesUpdated(insertionPointId, distributedNodes) {
     this._domModel._distributedNodesUpdated(insertionPointId, distributedNodes);
   }
+
+  /**
+   * @override
+   * @param {!Protocol.DOM.NodeId} nodeId
+   */
+  nodeHighlightRequested(nodeId) {
+    this._domModel.nodeHighlightRequested(nodeId);
+  }
+};
+
+/**
+ * @interface
+ */
+SDK.DOMNodeHighlighter = function() {};
+
+SDK.DOMNodeHighlighter.prototype = {
+  /**
+   * @param {?SDK.DOMNode} node
+   * @param {!Protocol.DOM.HighlightConfig} config
+   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
+   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
+   */
+  highlightDOMNode(node, config, backendNodeId, objectId) {},
+
+  /**
+   * @param {!Protocol.DOM.InspectMode} mode
+   * @param {!Protocol.DOM.HighlightConfig} config
+   * @param {function(?Protocol.Error)=} callback
+   */
+  setInspectMode(mode, config, callback) {},
+
+  /**
+   * @param {!Protocol.Page.FrameId} frameId
+   */
+  highlightFrame(frameId) {}
+};
+
+/**
+ * @implements {SDK.DOMNodeHighlighter}
+ * @unrestricted
+ */
+SDK.DefaultDOMNodeHighlighter = class {
+  /**
+   * @param {!Protocol.DOMAgent} agent
+   */
+  constructor(agent) {
+    this._agent = agent;
+  }
+
+  /**
+   * @override
+   * @param {?SDK.DOMNode} node
+   * @param {!Protocol.DOM.HighlightConfig} config
+   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
+   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
+   */
+  highlightDOMNode(node, config, backendNodeId, objectId) {
+    if (objectId || node || backendNodeId)
+      this._agent.highlightNode(config, (objectId || backendNodeId) ? undefined : node.id, backendNodeId, objectId);
+    else
+      this._agent.hideHighlight();
+  }
+
+  /**
+   * @override
+   * @param {!Protocol.DOM.InspectMode} mode
+   * @param {!Protocol.DOM.HighlightConfig} config
+   * @param {function(?Protocol.Error)=} callback
+   */
+  setInspectMode(mode, config, callback) {
+    this._agent.setInspectMode(mode, config, callback);
+  }
+
+  /**
+   * @override
+   * @param {!Protocol.Page.FrameId} frameId
+   */
+  highlightFrame(frameId) {
+    this._agent.highlightFrame(
+        frameId, Common.Color.PageHighlight.Content.toProtocolRGBA(),
+        Common.Color.PageHighlight.ContentOutline.toProtocolRGBA());
+  }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js
deleted file mode 100644
index de8d729..0000000
--- a/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js
+++ /dev/null
@@ -1,320 +0,0 @@
-// 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.
-
-/**
- * @implements {Protocol.OverlayDispatcher}
- */
-SDK.OverlayModel = class extends SDK.SDKModel {
-  /**
-   * @param {!SDK.Target} target
-   */
-  constructor(target) {
-    super(target);
-    this._domModel = /** @type {!SDK.DOMModel} */ (target.model(SDK.DOMModel));
-
-    target.registerOverlayDispatcher(this);
-    this._overlayAgent = target.overlayAgent();
-    this._overlayAgent.enable();
-    this._overlayAgent.setShowViewportSizeOnResize(true);
-
-    this._debuggerModel = target.model(SDK.DebuggerModel);
-    if (this._debuggerModel) {
-      Common.moduleSetting('disablePausedStateOverlay').addChangeListener(this._updatePausedInDebuggerMessage, this);
-      this._debuggerModel.addEventListener(
-          SDK.DebuggerModel.Events.DebuggerPaused, this._updatePausedInDebuggerMessage, this);
-      this._debuggerModel.addEventListener(
-          SDK.DebuggerModel.Events.DebuggerResumed, this._updatePausedInDebuggerMessage, this);
-      // TODO(dgozman): we should get DebuggerResumed on navigations instead of listening to GlobalObjectCleared.
-      this._debuggerModel.addEventListener(
-          SDK.DebuggerModel.Events.GlobalObjectCleared, this._updatePausedInDebuggerMessage, this);
-    }
-
-    this._inspectModeEnabled = false;
-    this._hideHighlightTimeout = null;
-    this._defaultHighlighter = new SDK.OverlayModel.DefaultHighlighter(this);
-    this._highlighter = this._defaultHighlighter;
-
-    this._showPaintRectsSetting = Common.moduleSetting('showPaintRects');
-    this._showPaintRectsSetting.addChangeListener(
-        () => this._overlayAgent.setShowPaintRects(this._showPaintRectsSetting.get()));
-    if (this._showPaintRectsSetting.get())
-      this._overlayAgent.setShowPaintRects(true);
-
-    this._showDebugBordersSetting = Common.moduleSetting('showDebugBorders');
-    this._showDebugBordersSetting.addChangeListener(
-        () => this._overlayAgent.setShowDebugBorders(this._showDebugBordersSetting.get()));
-    if (this._showDebugBordersSetting.get())
-      this._overlayAgent.setShowDebugBorders(true);
-
-    this._showFPSCounterSetting = Common.moduleSetting('showFPSCounter');
-    this._showFPSCounterSetting.addChangeListener(
-        () => this._overlayAgent.setShowFPSCounter(this._showFPSCounterSetting.get()));
-    if (this._showFPSCounterSetting.get())
-      this._overlayAgent.setShowFPSCounter(true);
-
-    this._showScrollBottleneckRectsSetting = Common.moduleSetting('showScrollBottleneckRects');
-    this._showScrollBottleneckRectsSetting.addChangeListener(
-        () => this._overlayAgent.setShowScrollBottleneckRects(this._showScrollBottleneckRectsSetting.get()));
-    if (this._showScrollBottleneckRectsSetting.get())
-      this._overlayAgent.setShowScrollBottleneckRects(true);
-  }
-
-  /**
-   * @param {!SDK.RemoteObject} object
-   */
-  static highlightObjectAsDOMNode(object) {
-    var domModel = object.runtimeModel().target().model(SDK.DOMModel);
-    if (domModel)
-      domModel.overlayModel().highlightDOMNode(undefined, undefined, undefined, object.objectId);
-  }
-
-  static hideDOMNodeHighlight() {
-    for (var overlayModel of SDK.targetManager.models(SDK.OverlayModel))
-      overlayModel.highlightDOMNode(0);
-  }
-
-  static muteHighlight() {
-    SDK.OverlayModel.hideDOMNodeHighlight();
-    SDK.OverlayModel._highlightDisabled = true;
-  }
-
-  static unmuteHighlight() {
-    SDK.OverlayModel._highlightDisabled = false;
-  }
-
-  /**
-   * @override
-   * @return {!Promise}
-   */
-  suspendModel() {
-    return this._overlayAgent.setSuspended(true);
-  }
-
-  /**
-   * @override
-   * @return {!Promise}
-   */
-  resumeModel() {
-    return this._overlayAgent.setSuspended(false);
-  }
-
-  setShowViewportSizeOnResize(show) {
-    this._overlayAgent.setShowViewportSizeOnResize(show);
-  }
-
-  _updatePausedInDebuggerMessage() {
-    var message = this._debuggerModel.isPaused() && !Common.moduleSetting('disablePausedStateOverlay').get() ?
-        Common.UIString('Paused in debugger') :
-        undefined;
-    this._overlayAgent.setPausedInDebuggerMessage(message);
-  }
-
-  /**
-   * @param {?SDK.OverlayModel.Highlighter} highlighter
-   */
-  setHighlighter(highlighter) {
-    this._highlighter = highlighter || this._defaultHighlighter;
-  }
-
-  /**
-   * @param {!Protocol.Overlay.InspectMode} mode
-   * @return {!Promise}
-   */
-  setInspectMode(mode) {
-    var requestDocumentPromise = new Promise(fulfill => this._domModel.requestDocument(fulfill));
-    return requestDocumentPromise.then(() => {
-      this._inspectModeEnabled = mode !== Protocol.Overlay.InspectMode.None;
-      this.dispatchEventToListeners(SDK.OverlayModel.Events.InspectModeWillBeToggled, this);
-      return this._highlighter.setInspectMode(mode, this._buildHighlightConfig());
-    });
-  }
-
-  /**
-   * @return {boolean}
-   */
-  inspectModeEnabled() {
-    return this._inspectModeEnabled;
-  }
-
-  /**
-   * @param {!Protocol.DOM.NodeId=} nodeId
-   * @param {string=} mode
-   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
-   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
-   */
-  highlightDOMNode(nodeId, mode, backendNodeId, objectId) {
-    this.highlightDOMNodeWithConfig(nodeId, {mode: mode}, backendNodeId, objectId);
-  }
-
-  /**
-   * @param {!Protocol.DOM.NodeId=} nodeId
-   * @param {!{mode: (string|undefined), showInfo: (boolean|undefined), selectors: (string|undefined)}=} config
-   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
-   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
-   */
-  highlightDOMNodeWithConfig(nodeId, config, backendNodeId, objectId) {
-    if (SDK.OverlayModel._highlightDisabled)
-      return;
-    config = config || {mode: 'all', showInfo: undefined, selectors: undefined};
-    if (this._hideHighlightTimeout) {
-      clearTimeout(this._hideHighlightTimeout);
-      this._hideHighlightTimeout = null;
-    }
-    var highlightConfig = this._buildHighlightConfig(config.mode);
-    if (typeof config.showInfo !== 'undefined')
-      highlightConfig.showInfo = config.showInfo;
-    if (typeof config.selectors !== 'undefined')
-      highlightConfig.selectorList = config.selectors;
-    this._highlighter.highlightDOMNode(this._domModel.nodeForId(nodeId || 0), highlightConfig, backendNodeId, objectId);
-  }
-
-  /**
-   * @param {!Protocol.DOM.NodeId} nodeId
-   */
-  highlightDOMNodeForTwoSeconds(nodeId) {
-    this.highlightDOMNode(nodeId);
-    this._hideHighlightTimeout = setTimeout(() => this.highlightDOMNode(0), 2000);
-  }
-
-  /**
-   * @param {!Protocol.Page.FrameId} frameId
-   */
-  highlightFrame(frameId) {
-    if (SDK.OverlayModel._highlightDisabled)
-      return;
-    this._highlighter.highlightFrame(frameId);
-  }
-
-  /**
-   * @param {string=} mode
-   * @return {!Protocol.Overlay.HighlightConfig}
-   */
-  _buildHighlightConfig(mode) {
-    mode = mode || 'all';
-    var showRulers = Common.moduleSetting('showMetricsRulers').get();
-    var highlightConfig = {showInfo: mode === 'all', showRulers: showRulers, showExtensionLines: showRulers};
-    if (mode === 'all' || mode === 'content')
-      highlightConfig.contentColor = Common.Color.PageHighlight.Content.toProtocolRGBA();
-
-    if (mode === 'all' || mode === 'padding')
-      highlightConfig.paddingColor = Common.Color.PageHighlight.Padding.toProtocolRGBA();
-
-    if (mode === 'all' || mode === 'border')
-      highlightConfig.borderColor = Common.Color.PageHighlight.Border.toProtocolRGBA();
-
-    if (mode === 'all' || mode === 'margin')
-      highlightConfig.marginColor = Common.Color.PageHighlight.Margin.toProtocolRGBA();
-
-    if (mode === 'all') {
-      highlightConfig.eventTargetColor = Common.Color.PageHighlight.EventTarget.toProtocolRGBA();
-      highlightConfig.shapeColor = Common.Color.PageHighlight.Shape.toProtocolRGBA();
-      highlightConfig.shapeMarginColor = Common.Color.PageHighlight.ShapeMargin.toProtocolRGBA();
-      highlightConfig.displayAsMaterial = true;
-    }
-    return highlightConfig;
-  }
-
-  /**
-   * @override
-   * @param {!Protocol.DOM.NodeId} nodeId
-   */
-  nodeHighlightRequested(nodeId) {
-    var node = this._domModel.nodeForId(nodeId);
-    if (node)
-      this.dispatchEventToListeners(SDK.OverlayModel.Events.HighlightNodeRequested, node);
-  }
-
-  /**
-   * @override
-   * @param {!Protocol.DOM.BackendNodeId} backendNodeId
-   */
-  inspectNodeRequested(backendNodeId) {
-    var deferredNode = new SDK.DeferredDOMNode(this.target(), backendNodeId);
-    this.dispatchEventToListeners(SDK.OverlayModel.Events.InspectNodeRequested, deferredNode);
-  }
-};
-
-SDK.SDKModel.register(SDK.OverlayModel, SDK.Target.Capability.DOM, true);
-
-/** @enum {symbol} */
-SDK.OverlayModel.Events = {
-  InspectModeWillBeToggled: Symbol('InspectModeWillBeToggled'),
-  HighlightNodeRequested: Symbol('HighlightNodeRequested'),
-  InspectNodeRequested: Symbol('InspectNodeRequested'),
-};
-
-/**
- * @interface
- */
-SDK.OverlayModel.Highlighter = function() {};
-
-SDK.OverlayModel.Highlighter.prototype = {
-  /**
-   * @param {?SDK.DOMNode} node
-   * @param {!Protocol.Overlay.HighlightConfig} config
-   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
-   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
-   */
-  highlightDOMNode(node, config, backendNodeId, objectId) {},
-
-  /**
-   * @param {!Protocol.Overlay.InspectMode} mode
-   * @param {!Protocol.Overlay.HighlightConfig} config
-   * @return {!Promise}
-   */
-  setInspectMode(mode, config) {},
-
-  /**
-   * @param {!Protocol.Page.FrameId} frameId
-   */
-  highlightFrame(frameId) {}
-};
-
-/**
- * @implements {SDK.OverlayModel.Highlighter}
- */
-SDK.OverlayModel.DefaultHighlighter = class {
-  /**
-   * @param {!SDK.OverlayModel} model
-   */
-  constructor(model) {
-    this._model = model;
-  }
-
-  /**
-   * @override
-   * @param {?SDK.DOMNode} node
-   * @param {!Protocol.Overlay.HighlightConfig} config
-   * @param {!Protocol.DOM.BackendNodeId=} backendNodeId
-   * @param {!Protocol.Runtime.RemoteObjectId=} objectId
-   */
-  highlightDOMNode(node, config, backendNodeId, objectId) {
-    if (objectId || node || backendNodeId) {
-      this._model._overlayAgent.highlightNode(
-          config, (objectId || backendNodeId) ? undefined : node.id, backendNodeId, objectId);
-    } else {
-      this._model._overlayAgent.hideHighlight();
-    }
-  }
-
-  /**
-   * @override
-   * @param {!Protocol.Overlay.InspectMode} mode
-   * @param {!Protocol.Overlay.HighlightConfig} config
-   * @return {!Promise}
-   */
-  setInspectMode(mode, config) {
-    return this._model._overlayAgent.setInspectMode(mode, config);
-  }
-
-  /**
-   * @override
-   * @param {!Protocol.Page.FrameId} frameId
-   */
-  highlightFrame(frameId) {
-    this._model._overlayAgent.highlightFrame(
-        frameId, Common.Color.PageHighlight.Content.toProtocolRGBA(),
-        Common.Color.PageHighlight.ContentOutline.toProtocolRGBA());
-  }
-};
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/module.json b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
index e4c2be3..8bb5fab 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
@@ -84,34 +84,6 @@
         },
         {
             "type": "setting",
-            "settingName": "showPaintRects",
-            "settingType": "boolean",
-            "storageType": "session",
-            "defaultValue": false
-        },
-        {
-            "type": "setting",
-            "settingName": "showDebugBorders",
-            "settingType": "boolean",
-            "storageType": "session",
-            "defaultValue": false
-        },
-        {
-            "type": "setting",
-            "settingName": "showFPSCounter",
-            "settingType": "boolean",
-            "storageType": "session",
-            "defaultValue": false
-        },
-        {
-            "type": "setting",
-            "settingName": "showScrollBottleneckRects",
-            "settingType": "boolean",
-            "storageType": "session",
-            "defaultValue": false
-        },
-        {
-            "type": "setting",
             "category": "Console",
             "title": "Enable custom formatters",
             "settingName": "customFormatters",
@@ -165,7 +137,6 @@
         "ServiceWorkerManager.js",
         "TracingManager.js",
         "TracingModel.js",
-        "OverlayModel.js",
         "RuntimeModel.js",
         "ScreenCaptureModel.js",
         "Script.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
index 6d4c06d..a1ce9bf7 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -436,11 +436,11 @@
      */
     function hoverCallback(hovered) {
       if (hovered) {
-        var overlayModel = target.model(SDK.OverlayModel);
-        if (overlayModel)
-          overlayModel.highlightFrame(frame.id);
+        var domModel = target.model(SDK.DOMModel);
+        if (domModel)
+          domModel.highlightFrame(frame.id);
       } else {
-        SDK.OverlayModel.hideDOMNodeHighlight();
+        SDK.DOMModel.hideDOMNodeHighlight();
       }
     }
     return frameNode;
diff --git a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
index d270d6c..66e9556 100644
--- a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
+++ b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
@@ -8,9 +8,10 @@
 self.testRunner;
 
 TestRunner.executeTestScript = function() {
-  fetch(`${Runtime.queryParam('test')}`)
+  const testScriptURL = /** @type {string} */ (Runtime.queryParam('test'));
+  fetch(testScriptURL)
       .then(data => data.text())
-      .then(testScript => eval(`(function(){${testScript}})()`))
+      .then(testScript => eval(`(function test(){${testScript}})()\n//# sourceURL=${testScriptURL}`))
       .catch(error => {
         TestRunner.addResult(`Unable to execute test script because of error: ${error}`);
         TestRunner.completeTest();
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
index c28b7969..45b6cab 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
@@ -454,7 +454,7 @@
    * @param {number} x
    * @return {!Promise<?Element>}
    */
-  popoverElementPromise(x) {
+  overviewInfoPromise(x) {
     if (!this._model || !this._model.filmStripModel().frames().length)
       return Promise.resolve(/** @type {?Element} */ (null));
 
@@ -473,7 +473,6 @@
     function createFrameElement(image) {
       var element = createElementWithClass('div', 'frame');
       element.createChild('div', 'thumbnail').appendChild(image);
-      UI.appendStyle(element, 'timeline/timelinePanel.css');
       this._lastFrame = frame;
       this._lastElement = element;
       return element;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js
index 81d5220..8a1df75 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChartView.js
@@ -154,7 +154,7 @@
    * @param {!Common.Event} commonEvent
    */
   _onEntryHighlighted(commonEvent) {
-    SDK.OverlayModel.hideDOMNodeHighlight();
+    SDK.DOMModel.hideDOMNodeHighlight();
     var entryIndex = /** @type {number} */ (commonEvent.data);
     var event = this._mainDataProvider.eventByIndex(entryIndex);
     if (!event)
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
index 8fbe22a..620d574 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -487,15 +487,6 @@
     border: 1px solid #ddd;
 }
 
-.timeline-overview-popover .frame .time {
-    display: none;
-}
-
-.timeline-overview-popover .frame .thumbnail img {
-    max-width: 300px;
-    max-height: 500px;
-}
-
 .timeline-tree-view {
     display: flex;
     overflow: hidden;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Popover.js b/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
index 5ac4910c..6c4790a 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
@@ -52,12 +52,10 @@
   /**
    * @param {number} showTimeout
    * @param {number=} hideTimeout
-   * @param {boolean=} hideOnAnchorLeave
    */
-  setTimeout(showTimeout, hideTimeout, hideOnAnchorLeave) {
+  setTimeout(showTimeout, hideTimeout) {
     this._showTimeout = showTimeout;
     this._hideTimeout = typeof hideTimeout === 'number' ? hideTimeout : showTimeout / 2;
-    this._hideOnAnchorLeave = hideOnAnchorLeave;
   }
 
   /**
@@ -241,7 +239,7 @@
   }
 
   _stopHidePopoverTimer() {
-    if (!this._hidePopoverTimer || this._hideOnAnchorLeave)
+    if (!this._hidePopoverTimer)
       return;
     clearTimeout(this._hidePopoverTimer);
     delete this._hidePopoverTimer;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js b/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js
index 1d19ce2..3d33e23 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SearchableView.js
@@ -95,7 +95,8 @@
     this._searchInputElement.addEventListener('keydown', this._onSearchKeyDown.bind(this), true);
     this._searchInputElement.addEventListener('input', this._onInput.bind(this), false);
 
-    this._replaceInputElement = searchInputElements.createChild('input', 'search-replace toolbar-replace-control');
+    this._replaceInputElement =
+        searchInputElements.createChild('input', 'search-replace toolbar-replace-control hidden');
     this._replaceInputElement.addEventListener('keydown', this._onReplaceKeyDown.bind(this), true);
     this._replaceInputElement.placeholder = Common.UIString('Replace');
 
@@ -468,6 +469,7 @@
     var secondRowVisible = this._replaceCheckboxElement.checked;
     this._footerElementContainer.classList.toggle('replaceable', secondRowVisible);
     this._buttonsContainer.classList.toggle('hidden', !secondRowVisible);
+    this._replaceInputElement.classList.toggle('hidden', !secondRowVisible);
     this._replaceCheckboxElement.tabIndex = secondRowVisible ? -1 : 0;
 
     if (secondRowVisible)
diff --git a/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py b/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py
index a231f09e..bd7e22f 100755
--- a/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py
+++ b/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py
@@ -44,23 +44,6 @@
     "object": "!Object",
 }
 
-# yapf: disable
-promisified_domains = {
-    "Accessibility",
-    "Animation",
-    "Browser",
-    "CSS",
-    "DOMDebugger",
-    "Emulation",
-    "HeapProfiler",
-    "Overlay",
-    "Page",
-    "Profiler",
-    "LayerTree",
-    "Tracing"
-}
-# yapf: enable
-
 ref_types = {}
 
 
@@ -107,6 +90,11 @@
             return "!! Type not found: " + type_id
 
 
+def param_name(param):
+    name = param["name"]
+    return name if name != "arguments" else "_arguments"
+
+
 def load_schema(file, domains):
     input_file = open(file, "r")
     json_string = input_file.read()
@@ -129,7 +117,6 @@
 
     for domain in domains:
         domain_name = domain["domain"]
-        promisified = domain_name in promisified_domains
 
         output_file.write("Protocol.%s = {};\n" % domain_name)
         output_file.write("\n\n/**\n * @constructor\n*/\n")
@@ -141,23 +128,17 @@
                 params = []
                 param_to_type = {}
                 has_return_value = "returns" in command
-                explicit_parameters = promisified and has_return_value
                 if "parameters" in command:
                     for in_param in command["parameters"]:
+                        in_param_name = param_name(in_param)
                         if "optional" in in_param:
-                            param_to_type[in_param["name"]] = "(%s|undefined)" % param_type(domain_name, in_param)
-                            if explicit_parameters:
-                                params.append("%s" % in_param["name"])
-                                output_file.write(" * @param {%s|undefined} %s\n" %
-                                                  (param_type(domain_name, in_param), in_param["name"]))
-                            else:
-                                params.append("opt_%s" % in_param["name"])
-                                output_file.write(" * @param {%s=} opt_%s\n" %
-                                                  (param_type(domain_name, in_param), in_param["name"]))
+                            param_to_type[in_param_name] = "(%s|undefined)" % param_type(domain_name, in_param)
+                            params.append("opt_%s" % in_param_name)
+                            output_file.write(" * @param {%s=} opt_%s\n" % (param_type(domain_name, in_param), in_param_name))
                         else:
-                            param_to_type[in_param["name"]] = param_type(domain_name, in_param)
-                            params.append(in_param["name"])
-                            output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, in_param), in_param["name"]))
+                            param_to_type[in_param_name] = param_type(domain_name, in_param)
+                            params.append(in_param_name)
+                            output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, in_param), in_param_name))
                 returns = []
                 returns.append("?Protocol.Error")
                 if ("error" in command):
@@ -168,15 +149,9 @@
                             returns.append("%s=" % param_type(domain_name, out_param))
                         else:
                             returns.append("%s" % param_type(domain_name, out_param))
-                callback_return_type = "void="
-                if explicit_parameters:
-                    callback_return_type = "T"
-                elif promisified:
-                    callback_return_type = "T="
-                output_file.write(" * @param {function(%s):%s} opt_callback\n" % (", ".join(returns), callback_return_type))
-                if (promisified):
-                    output_file.write(" * @return {!Promise.<T>}\n")
-                    output_file.write(" * @template T\n")
+                output_file.write(" * @param {function(%s):T=} opt_callback\n" % ", ".join(returns))
+                output_file.write(" * @return {!Promise<T>}\n")
+                output_file.write(" * @template T\n")
                 params.append("opt_callback")
 
                 output_file.write(" */\n")
diff --git a/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp b/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp
index 19d9bc5..3d6a1ee 100644
--- a/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp
+++ b/third_party/WebKit/Source/modules/device_light/DeviceLightDispatcher.cpp
@@ -4,9 +4,22 @@
 
 #include "modules/device_light/DeviceLightDispatcher.h"
 
+#include <cmath>
+
 #include "modules/device_light/DeviceLightController.h"
 #include "public/platform/Platform.h"
 
+namespace {
+double EnsureRoundedLuxValue(double lux) {
+  // Make sure to round the lux value to nearest integer, to
+  // avoid too precise values and hence reduce fingerprinting risk.
+  // The special case when the lux value is infinity (no data can be
+  // provided) is simply returned as is.
+  // TODO(timvolodine): consider reducing the lux value precision further.
+  return std::isinf(lux) ? lux : std::round(lux);
+}
+}  // namespace
+
 namespace blink {
 
 DeviceLightDispatcher& DeviceLightDispatcher::Instance() {
@@ -33,8 +46,11 @@
 }
 
 void DeviceLightDispatcher::DidChangeDeviceLight(double value) {
-  last_device_light_data_ = value;
-  NotifyControllers();
+  double newValue = EnsureRoundedLuxValue(value);
+  if (last_device_light_data_ != newValue) {
+    last_device_light_data_ = newValue;
+    NotifyControllers();
+  }
 }
 
 double DeviceLightDispatcher::LatestDeviceLightData() const {
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 002e02b..66a85e11 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -494,6 +494,11 @@
       status: "experimental",
     },
     {
+      name: "IdleTimeColdModeSpellChecking",
+      depends_on: ["IdleTimeSpellChecking"],
+      status: "test",
+    },
+    {
       name: "IdleTimeSpellChecking",
       status: "test",
     },
diff --git a/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp b/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp
index 203c591..7872782 100644
--- a/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp
+++ b/third_party/WebKit/Source/platform/animation/TimingFunctionTest.cpp
@@ -415,35 +415,35 @@
 TEST_F(TimingFunctionTest, StepsEvaluate) {
   RefPtr<TimingFunction> steps_timing_start =
       StepsTimingFunction::Preset(StepsTimingFunction::StepPosition::START);
-  EXPECT_EQ(0.00, steps_timing_start->Evaluate(-1.10, 0));
+  EXPECT_EQ(-1.00, steps_timing_start->Evaluate(-1.10, 0));
   EXPECT_EQ(0.00, steps_timing_start->Evaluate(-0.10, 0));
   EXPECT_EQ(1.00, steps_timing_start->Evaluate(0.00, 0));
   EXPECT_EQ(1.00, steps_timing_start->Evaluate(0.20, 0));
   EXPECT_EQ(1.00, steps_timing_start->Evaluate(0.60, 0));
   EXPECT_EQ(1.00, steps_timing_start->Evaluate(1.00, 0));
-  EXPECT_EQ(1.00, steps_timing_start->Evaluate(2.00, 0));
+  EXPECT_EQ(3.00, steps_timing_start->Evaluate(2.00, 0));
 
   RefPtr<TimingFunction> steps_timing_middle =
       StepsTimingFunction::Preset(StepsTimingFunction::StepPosition::MIDDLE);
-  EXPECT_EQ(0.00, steps_timing_middle->Evaluate(-2.50, 0));
+  EXPECT_EQ(-2.00, steps_timing_middle->Evaluate(-2.50, 0));
   EXPECT_EQ(0.00, steps_timing_middle->Evaluate(0.00, 0));
   EXPECT_EQ(0.00, steps_timing_middle->Evaluate(0.49, 0));
   EXPECT_EQ(1.00, steps_timing_middle->Evaluate(0.50, 0));
   EXPECT_EQ(1.00, steps_timing_middle->Evaluate(1.00, 0));
-  EXPECT_EQ(1.00, steps_timing_middle->Evaluate(2.50, 0));
+  EXPECT_EQ(3.00, steps_timing_middle->Evaluate(2.50, 0));
 
   RefPtr<TimingFunction> steps_timing_end =
       StepsTimingFunction::Preset(StepsTimingFunction::StepPosition::END);
-  EXPECT_EQ(0.00, steps_timing_end->Evaluate(-2.00, 0));
+  EXPECT_EQ(-2.00, steps_timing_end->Evaluate(-2.00, 0));
   EXPECT_EQ(0.00, steps_timing_end->Evaluate(0.00, 0));
   EXPECT_EQ(0.00, steps_timing_end->Evaluate(0.20, 0));
   EXPECT_EQ(0.00, steps_timing_end->Evaluate(0.60, 0));
   EXPECT_EQ(1.00, steps_timing_end->Evaluate(1.00, 0));
-  EXPECT_EQ(1.00, steps_timing_end->Evaluate(2.00, 0));
+  EXPECT_EQ(2.00, steps_timing_end->Evaluate(2.00, 0));
 
   RefPtr<TimingFunction> steps_timing_custom_start =
       StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::START);
-  EXPECT_EQ(0.00, steps_timing_custom_start->Evaluate(-0.50, 0));
+  EXPECT_EQ(-0.25, steps_timing_custom_start->Evaluate(-0.50, 0));
   EXPECT_EQ(0.25, steps_timing_custom_start->Evaluate(0.00, 0));
   EXPECT_EQ(0.25, steps_timing_custom_start->Evaluate(0.24, 0));
   EXPECT_EQ(0.50, steps_timing_custom_start->Evaluate(0.25, 0));
@@ -452,11 +452,11 @@
   EXPECT_EQ(0.75, steps_timing_custom_start->Evaluate(0.74, 0));
   EXPECT_EQ(1.00, steps_timing_custom_start->Evaluate(0.75, 0));
   EXPECT_EQ(1.00, steps_timing_custom_start->Evaluate(1.00, 0));
-  EXPECT_EQ(1.00, steps_timing_custom_start->Evaluate(1.50, 0));
+  EXPECT_EQ(1.75, steps_timing_custom_start->Evaluate(1.50, 0));
 
   RefPtr<TimingFunction> steps_timing_custom_middle =
       StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::MIDDLE);
-  EXPECT_EQ(0.00, steps_timing_custom_middle->Evaluate(-2.00, 0));
+  EXPECT_EQ(-2.00, steps_timing_custom_middle->Evaluate(-2.00, 0));
   EXPECT_EQ(0.00, steps_timing_custom_middle->Evaluate(0.00, 0));
   EXPECT_EQ(0.00, steps_timing_custom_middle->Evaluate(0.12, 0));
   EXPECT_EQ(0.25, steps_timing_custom_middle->Evaluate(0.13, 0));
@@ -467,11 +467,11 @@
   EXPECT_EQ(0.75, steps_timing_custom_middle->Evaluate(0.87, 0));
   EXPECT_EQ(1.00, steps_timing_custom_middle->Evaluate(0.88, 0));
   EXPECT_EQ(1.00, steps_timing_custom_middle->Evaluate(1.00, 0));
-  EXPECT_EQ(1.00, steps_timing_custom_middle->Evaluate(3.00, 0));
+  EXPECT_EQ(3.00, steps_timing_custom_middle->Evaluate(3.00, 0));
 
   RefPtr<TimingFunction> steps_timing_custom_end =
       StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::END);
-  EXPECT_EQ(0.00, steps_timing_custom_end->Evaluate(-2.00, 0));
+  EXPECT_EQ(-2.00, steps_timing_custom_end->Evaluate(-2.00, 0));
   EXPECT_EQ(0.00, steps_timing_custom_end->Evaluate(0.00, 0));
   EXPECT_EQ(0.00, steps_timing_custom_end->Evaluate(0.24, 0));
   EXPECT_EQ(0.25, steps_timing_custom_end->Evaluate(0.25, 0));
@@ -481,7 +481,7 @@
   EXPECT_EQ(0.75, steps_timing_custom_end->Evaluate(0.75, 0));
   EXPECT_EQ(0.75, steps_timing_custom_end->Evaluate(0.99, 0));
   EXPECT_EQ(1.00, steps_timing_custom_end->Evaluate(1.00, 0));
-  EXPECT_EQ(1.00, steps_timing_custom_end->Evaluate(2.00, 0));
+  EXPECT_EQ(2.00, steps_timing_custom_end->Evaluate(2.00, 0));
 }
 
 }  // namespace
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintCanvas.h b/third_party/WebKit/Source/platform/graphics/paint/PaintCanvas.h
index 87a87a5..ec30f6d 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintCanvas.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintCanvas.h
@@ -12,7 +12,6 @@
 using cc::PaintCanvas;
 using cc::SkiaPaintCanvas;
 using cc::PaintCanvasAutoRestore;
-using cc::ToPixmap;
 }
 
 #endif  // PaintCanvas_h
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index aff5086e..b9bd306 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -79,8 +79,10 @@
     "IndexedDBClientImpl.h",
     "InspectorEmulationAgent.cpp",
     "InspectorEmulationAgent.h",
-    "InspectorOverlayAgent.cpp",
-    "InspectorOverlayAgent.h",
+    "InspectorOverlay.cpp",
+    "InspectorOverlay.h",
+    "InspectorRenderingAgent.cpp",
+    "InspectorRenderingAgent.h",
     "LinkHighlightImpl.cpp",
     "LinkHighlightImpl.h",
     "LocalFileSystemClient.cpp",
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.cpp b/third_party/WebKit/Source/web/InspectorOverlay.cpp
new file mode 100644
index 0000000..850d283
--- /dev/null
+++ b/third_party/WebKit/Source/web/InspectorOverlay.cpp
@@ -0,0 +1,827 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "web/InspectorOverlay.h"
+
+#include <memory>
+
+#include "bindings/core/v8/ScriptController.h"
+#include "bindings/core/v8/ScriptSourceCode.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8InspectorOverlayHost.h"
+#include "core/dom/Node.h"
+#include "core/dom/StaticNodeList.h"
+#include "core/dom/TaskRunnerHelper.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/LocalFrameClient.h"
+#include "core/frame/Settings.h"
+#include "core/frame/VisualViewport.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/input/EventHandler.h"
+#include "core/inspector/InspectorOverlayHost.h"
+#include "core/layout/api/LayoutViewItem.h"
+#include "core/loader/EmptyClients.h"
+#include "core/loader/FrameLoadRequest.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Page.h"
+#include "platform/ScriptForbiddenScope.h"
+#include "platform/graphics/Color.h"
+#include "platform/graphics/GraphicsContext.h"
+#include "platform/graphics/paint/CullRect.h"
+#include "platform/wtf/AutoReset.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebData.h"
+#include "v8/include/v8.h"
+#include "web/ChromeClientImpl.h"
+#include "web/PageOverlay.h"
+#include "web/WebInputEventConversion.h"
+#include "web/WebLocalFrameImpl.h"
+
+namespace blink {
+
+namespace {
+
+Node* HoveredNodeForPoint(LocalFrame* frame,
+                          const IntPoint& point_in_root_frame,
+                          bool ignore_pointer_events_none) {
+  HitTestRequest::HitTestRequestType hit_type =
+      HitTestRequest::kMove | HitTestRequest::kReadOnly |
+      HitTestRequest::kAllowChildFrameContent;
+  if (ignore_pointer_events_none)
+    hit_type |= HitTestRequest::kIgnorePointerEventsNone;
+  HitTestRequest request(hit_type);
+  HitTestResult result(request,
+                       frame->View()->RootFrameToContents(point_in_root_frame));
+  frame->ContentLayoutItem().HitTest(result);
+  Node* node = result.InnerPossiblyPseudoNode();
+  while (node && node->getNodeType() == Node::kTextNode)
+    node = node->parentNode();
+  return node;
+}
+
+Node* HoveredNodeForEvent(LocalFrame* frame,
+                          const WebGestureEvent& event,
+                          bool ignore_pointer_events_none) {
+  return HoveredNodeForPoint(frame,
+                             RoundedIntPoint(event.PositionInRootFrame()),
+                             ignore_pointer_events_none);
+}
+
+Node* HoveredNodeForEvent(LocalFrame* frame,
+                          const WebMouseEvent& event,
+                          bool ignore_pointer_events_none) {
+  return HoveredNodeForPoint(frame,
+                             RoundedIntPoint(event.PositionInRootFrame()),
+                             ignore_pointer_events_none);
+}
+
+Node* HoveredNodeForEvent(LocalFrame* frame,
+                          const WebTouchEvent& event,
+                          bool ignore_pointer_events_none) {
+  if (!event.touches_length)
+    return nullptr;
+  WebTouchPoint transformed_point = event.TouchPointInRootFrame(0);
+  return HoveredNodeForPoint(frame, RoundedIntPoint(transformed_point.position),
+                             ignore_pointer_events_none);
+}
+}  // namespace
+
+class InspectorOverlay::InspectorPageOverlayDelegate final
+    : public PageOverlay::Delegate {
+ public:
+  explicit InspectorPageOverlayDelegate(InspectorOverlay& overlay)
+      : overlay_(&overlay) {}
+
+  void PaintPageOverlay(const PageOverlay&,
+                        GraphicsContext& graphics_context,
+                        const WebSize& web_view_size) const override {
+    if (overlay_->IsEmpty())
+      return;
+
+    FrameView* view = overlay_->OverlayMainFrame()->View();
+    DCHECK(!view->NeedsLayout());
+    view->Paint(graphics_context,
+                CullRect(IntRect(0, 0, view->Width(), view->Height())));
+  }
+
+ private:
+  Persistent<InspectorOverlay> overlay_;
+};
+
+class InspectorOverlay::InspectorOverlayChromeClient final
+    : public EmptyChromeClient {
+ public:
+  static InspectorOverlayChromeClient* Create(ChromeClient& client,
+                                              InspectorOverlay& overlay) {
+    return new InspectorOverlayChromeClient(client, overlay);
+  }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(client_);
+    visitor->Trace(overlay_);
+    EmptyChromeClient::Trace(visitor);
+  }
+
+  void SetCursor(const Cursor& cursor, LocalFrame* local_root) override {
+    ToChromeClientImpl(client_)->SetCursorOverridden(false);
+    ToChromeClientImpl(client_)->SetCursor(cursor,
+                                           overlay_->frame_impl_->GetFrame());
+    ToChromeClientImpl(client_)->SetCursorOverridden(false);
+  }
+
+  void SetToolTip(LocalFrame& frame,
+                  const String& tooltip,
+                  TextDirection direction) override {
+    DCHECK_EQ(&frame, overlay_->OverlayMainFrame());
+    client_->SetToolTip(*overlay_->frame_impl_->GetFrame(), tooltip, direction);
+  }
+
+  void InvalidateRect(const IntRect&) override { overlay_->Invalidate(); }
+
+  void ScheduleAnimation(LocalFrame* frame) override {
+    if (overlay_->in_layout_)
+      return;
+
+    client_->ScheduleAnimation(frame);
+  }
+
+ private:
+  InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay& overlay)
+      : client_(&client), overlay_(&overlay) {}
+
+  Member<ChromeClient> client_;
+  Member<InspectorOverlay> overlay_;
+};
+
+InspectorOverlay::InspectorOverlay(WebLocalFrameImpl* frame_impl)
+    : frame_impl_(frame_impl),
+      overlay_host_(InspectorOverlayHost::Create()),
+      draw_view_size_(false),
+      resize_timer_active_(false),
+      omit_tooltip_(false),
+      timer_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer,
+                                   frame_impl->GetFrame()),
+             this,
+             &InspectorOverlay::OnTimer),
+      suspended_(false),
+      show_reloading_blanket_(false),
+      in_layout_(false),
+      needs_update_(false),
+      swallow_next_mouse_up_(false),
+      inspect_mode_(InspectorDOMAgent::kNotSearching) {}
+
+InspectorOverlay::~InspectorOverlay() {
+  DCHECK(!overlay_page_);
+}
+
+DEFINE_TRACE(InspectorOverlay) {
+  visitor->Trace(frame_impl_);
+  visitor->Trace(highlight_node_);
+  visitor->Trace(event_target_node_);
+  visitor->Trace(overlay_page_);
+  visitor->Trace(overlay_chrome_client_);
+  visitor->Trace(overlay_host_);
+  visitor->Trace(dom_agent_);
+  visitor->Trace(hovered_node_for_inspect_mode_);
+}
+
+void InspectorOverlay::Init(v8_inspector::V8InspectorSession* v8_session,
+                            InspectorDOMAgent* dom_agent) {
+  v8_session_ = v8_session;
+  dom_agent_ = dom_agent;
+  overlay_host_->SetListener(this);
+}
+
+void InspectorOverlay::Invalidate() {
+  if (!page_overlay_) {
+    page_overlay_ = PageOverlay::Create(
+        frame_impl_, WTF::WrapUnique(new InspectorPageOverlayDelegate(*this)));
+  }
+
+  page_overlay_->Update();
+}
+
+void InspectorOverlay::UpdateAllLifecyclePhases() {
+  if (IsEmpty())
+    return;
+
+  AutoReset<bool> scoped(&in_layout_, true);
+  if (needs_update_) {
+    needs_update_ = false;
+    RebuildOverlayPage();
+  }
+  OverlayMainFrame()->View()->UpdateAllLifecyclePhases();
+}
+
+bool InspectorOverlay::HandleInputEvent(const WebInputEvent& input_event) {
+  bool handled = false;
+
+  if (IsEmpty())
+    return false;
+
+  if (input_event.GetType() == WebInputEvent::kGestureTap) {
+    // We only have a use for gesture tap.
+    WebGestureEvent transformed_event = TransformWebGestureEvent(
+        frame_impl_->GetFrameView(),
+        static_cast<const WebGestureEvent&>(input_event));
+    handled = HandleGestureEvent(transformed_event);
+    if (handled)
+      return true;
+
+    OverlayMainFrame()->GetEventHandler().HandleGestureEvent(transformed_event);
+  }
+  if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
+    WebMouseEvent mouse_event =
+        TransformWebMouseEvent(frame_impl_->GetFrameView(),
+                               static_cast<const WebMouseEvent&>(input_event));
+
+    if (mouse_event.GetType() == WebInputEvent::kMouseMove)
+      handled = HandleMouseMove(mouse_event);
+    else if (mouse_event.GetType() == WebInputEvent::kMouseDown)
+      handled = HandleMouseDown();
+    else if (mouse_event.GetType() == WebInputEvent::kMouseUp)
+      handled = HandleMouseUp();
+
+    if (handled)
+      return true;
+
+    if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
+      handled = OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
+                    mouse_event, TransformWebMouseEventVector(
+                                     frame_impl_->GetFrameView(),
+                                     std::vector<const WebInputEvent*>())) !=
+                WebInputEventResult::kNotHandled;
+    }
+    if (mouse_event.GetType() == WebInputEvent::kMouseDown)
+      handled = OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
+                    mouse_event) != WebInputEventResult::kNotHandled;
+    if (mouse_event.GetType() == WebInputEvent::kMouseUp)
+      handled = OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
+                    mouse_event) != WebInputEventResult::kNotHandled;
+  }
+
+  if (WebInputEvent::IsTouchEventType(input_event.GetType())) {
+    WebTouchEvent transformed_event =
+        TransformWebTouchEvent(frame_impl_->GetFrameView(),
+                               static_cast<const WebTouchEvent&>(input_event));
+    handled = HandleTouchEvent(transformed_event);
+    if (handled)
+      return true;
+    OverlayMainFrame()->GetEventHandler().HandleTouchEvent(
+        transformed_event, Vector<WebTouchEvent>());
+  }
+  if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
+    OverlayMainFrame()->GetEventHandler().KeyEvent(
+        static_cast<const WebKeyboardEvent&>(input_event));
+  }
+
+  if (input_event.GetType() == WebInputEvent::kMouseWheel) {
+    WebMouseWheelEvent transformed_event = TransformWebMouseWheelEvent(
+        frame_impl_->GetFrameView(),
+        static_cast<const WebMouseWheelEvent&>(input_event));
+    handled = OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
+                  transformed_event) != WebInputEventResult::kNotHandled;
+  }
+
+  return handled;
+}
+
+void InspectorOverlay::SetPausedInDebuggerMessage(const String& message) {
+  paused_in_debugger_message_ = message;
+  ScheduleUpdate();
+}
+
+void InspectorOverlay::ShowReloadingBlanket() {
+  show_reloading_blanket_ = true;
+  ScheduleUpdate();
+}
+
+void InspectorOverlay::HideReloadingBlanket() {
+  if (!show_reloading_blanket_)
+    return;
+  show_reloading_blanket_ = false;
+  if (suspended_)
+    ClearInternal();
+  else
+    ScheduleUpdate();
+}
+
+void InspectorOverlay::HideHighlight() {
+  highlight_node_.Clear();
+  event_target_node_.Clear();
+  highlight_quad_.reset();
+  ScheduleUpdate();
+}
+
+void InspectorOverlay::HighlightNode(
+    Node* node,
+    const InspectorHighlightConfig& highlight_config,
+    bool omit_tooltip) {
+  HighlightNode(node, nullptr, highlight_config, omit_tooltip);
+}
+
+void InspectorOverlay::HighlightNode(
+    Node* node,
+    Node* event_target,
+    const InspectorHighlightConfig& highlight_config,
+    bool omit_tooltip) {
+  node_highlight_config_ = highlight_config;
+  highlight_node_ = node;
+  event_target_node_ = event_target;
+  omit_tooltip_ = omit_tooltip;
+  ScheduleUpdate();
+}
+
+void InspectorOverlay::SetInspectMode(
+    InspectorDOMAgent::SearchMode search_mode,
+    std::unique_ptr<InspectorHighlightConfig> highlight_config) {
+  inspect_mode_ = search_mode;
+  ScheduleUpdate();
+
+  if (search_mode != InspectorDOMAgent::kNotSearching) {
+    inspect_mode_highlight_config_ = std::move(highlight_config);
+  } else {
+    hovered_node_for_inspect_mode_.Clear();
+    HideHighlight();
+  }
+}
+
+void InspectorOverlay::HighlightQuad(
+    std::unique_ptr<FloatQuad> quad,
+    const InspectorHighlightConfig& highlight_config) {
+  quad_highlight_config_ = highlight_config;
+  highlight_quad_ = std::move(quad);
+  omit_tooltip_ = false;
+  ScheduleUpdate();
+}
+
+bool InspectorOverlay::IsEmpty() {
+  if (show_reloading_blanket_)
+    return false;
+  if (suspended_)
+    return true;
+  bool has_visible_elements = highlight_node_ || event_target_node_ ||
+                              highlight_quad_ ||
+                              (resize_timer_active_ && draw_view_size_) ||
+                              !paused_in_debugger_message_.IsNull();
+  return !has_visible_elements &&
+         inspect_mode_ == InspectorDOMAgent::kNotSearching;
+}
+
+void InspectorOverlay::ScheduleUpdate() {
+  if (IsEmpty()) {
+    if (page_overlay_)
+      page_overlay_.reset();
+    return;
+  }
+  needs_update_ = true;
+  LocalFrame* frame = frame_impl_->GetFrame();
+  if (frame) {
+    frame->GetPage()->GetChromeClient().ScheduleAnimation(frame);
+  }
+}
+
+void InspectorOverlay::RebuildOverlayPage() {
+  FrameView* view = frame_impl_->GetFrameView();
+  LocalFrame* frame = frame_impl_->GetFrame();
+  if (!view || !frame)
+    return;
+
+  IntRect visible_rect_in_document =
+      view->GetScrollableArea()->VisibleContentRect();
+  IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
+  OverlayMainFrame()->View()->Resize(viewport_size);
+  OverlayPage()->GetVisualViewport().SetSize(viewport_size);
+  OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale());
+
+  Reset(viewport_size, visible_rect_in_document.Location());
+
+  if (show_reloading_blanket_) {
+    EvaluateInOverlay("showReloadingBlanket", "");
+    return;
+  }
+  DrawNodeHighlight();
+  DrawQuadHighlight();
+  DrawPausedInDebuggerMessage();
+  DrawViewSize();
+}
+
+static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
+    const IntSize& size) {
+  std::unique_ptr<protocol::DictionaryValue> result =
+      protocol::DictionaryValue::create();
+  result->setInteger("width", size.Width());
+  result->setInteger("height", size.Height());
+  return result;
+}
+
+void InspectorOverlay::DrawNodeHighlight() {
+  if (!highlight_node_)
+    return;
+
+  String selectors = node_highlight_config_.selector_list;
+  StaticElementList* elements = nullptr;
+  DummyExceptionStateForTesting exception_state;
+  ContainerNode* query_base = highlight_node_->ContainingShadowRoot();
+  if (!query_base)
+    query_base = highlight_node_->ownerDocument();
+  if (selectors.length())
+    elements =
+        query_base->QuerySelectorAll(AtomicString(selectors), exception_state);
+  if (elements && !exception_state.HadException()) {
+    for (unsigned i = 0; i < elements->length(); ++i) {
+      Element* element = elements->item(i);
+      InspectorHighlight highlight(element, node_highlight_config_, false);
+      std::unique_ptr<protocol::DictionaryValue> highlight_json =
+          highlight.AsProtocolValue();
+      EvaluateInOverlay("drawHighlight", std::move(highlight_json));
+    }
+  }
+
+  bool append_element_info =
+      highlight_node_->IsElementNode() && !omit_tooltip_ &&
+      node_highlight_config_.show_info && highlight_node_->GetLayoutObject() &&
+      highlight_node_->GetDocument().GetFrame();
+  InspectorHighlight highlight(highlight_node_.Get(), node_highlight_config_,
+                               append_element_info);
+  if (event_target_node_)
+    highlight.AppendEventTargetQuads(event_target_node_.Get(),
+                                     node_highlight_config_);
+
+  std::unique_ptr<protocol::DictionaryValue> highlight_json =
+      highlight.AsProtocolValue();
+  EvaluateInOverlay("drawHighlight", std::move(highlight_json));
+}
+
+void InspectorOverlay::DrawQuadHighlight() {
+  if (!highlight_quad_)
+    return;
+
+  InspectorHighlight highlight(WindowToViewportScale());
+  highlight.AppendQuad(*highlight_quad_, quad_highlight_config_.content,
+                       quad_highlight_config_.content_outline);
+  EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue());
+}
+
+void InspectorOverlay::DrawPausedInDebuggerMessage() {
+  if (inspect_mode_ == InspectorDOMAgent::kNotSearching &&
+      !paused_in_debugger_message_.IsNull())
+    EvaluateInOverlay("drawPausedInDebuggerMessage",
+                      paused_in_debugger_message_);
+}
+
+void InspectorOverlay::DrawViewSize() {
+  if (resize_timer_active_ && draw_view_size_)
+    EvaluateInOverlay("drawViewSize", "");
+}
+
+float InspectorOverlay::WindowToViewportScale() const {
+  LocalFrame* frame = frame_impl_->GetFrame();
+  if (!frame)
+    return 1.0f;
+  return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f);
+}
+
+Page* InspectorOverlay::OverlayPage() {
+  if (overlay_page_)
+    return overlay_page_.Get();
+
+  ScriptForbiddenScope::AllowUserAgentScript allow_script;
+
+  DEFINE_STATIC_LOCAL(LocalFrameClient, dummy_local_frame_client,
+                      (EmptyLocalFrameClient::Create()));
+  Page::PageClients page_clients;
+  FillWithEmptyClients(page_clients);
+  DCHECK(!overlay_chrome_client_);
+  overlay_chrome_client_ = InspectorOverlayChromeClient::Create(
+      frame_impl_->GetFrame()->GetPage()->GetChromeClient(), *this);
+  page_clients.chrome_client = overlay_chrome_client_.Get();
+  overlay_page_ = Page::Create(page_clients);
+
+  Settings& settings = frame_impl_->GetFrame()->GetPage()->GetSettings();
+  Settings& overlay_settings = overlay_page_->GetSettings();
+
+  overlay_settings.GetGenericFontFamilySettings().UpdateStandard(
+      settings.GetGenericFontFamilySettings().Standard());
+  overlay_settings.GetGenericFontFamilySettings().UpdateSerif(
+      settings.GetGenericFontFamilySettings().Serif());
+  overlay_settings.GetGenericFontFamilySettings().UpdateSansSerif(
+      settings.GetGenericFontFamilySettings().SansSerif());
+  overlay_settings.GetGenericFontFamilySettings().UpdateCursive(
+      settings.GetGenericFontFamilySettings().Cursive());
+  overlay_settings.GetGenericFontFamilySettings().UpdateFantasy(
+      settings.GetGenericFontFamilySettings().Fantasy());
+  overlay_settings.GetGenericFontFamilySettings().UpdatePictograph(
+      settings.GetGenericFontFamilySettings().Pictograph());
+  overlay_settings.SetMinimumFontSize(settings.GetMinimumFontSize());
+  overlay_settings.SetMinimumLogicalFontSize(
+      settings.GetMinimumLogicalFontSize());
+  overlay_settings.SetScriptEnabled(true);
+  overlay_settings.SetPluginsEnabled(false);
+  overlay_settings.SetLoadsImagesAutomatically(true);
+  // FIXME: http://crbug.com/363843. Inspector should probably create its
+  // own graphics layers and attach them to the tree rather than going
+  // through some non-composited paint function.
+  overlay_settings.SetAcceleratedCompositingEnabled(false);
+
+  LocalFrame* frame =
+      LocalFrame::Create(&dummy_local_frame_client, *overlay_page_, 0);
+  frame->SetView(FrameView::Create(*frame));
+  frame->Init();
+  FrameLoader& loader = frame->Loader();
+  frame->View()->SetCanHaveScrollbars(false);
+  frame->View()->SetBaseBackgroundColor(Color::kTransparent);
+
+  const WebData& overlay_page_html_resource =
+      Platform::Current()->LoadResource("InspectorOverlayPage.html");
+  loader.Load(
+      FrameLoadRequest(0, ResourceRequest(BlankURL()),
+                       SubstituteData(overlay_page_html_resource, "text/html",
+                                      "UTF-8", KURL(), kForceSynchronousLoad)));
+  v8::Isolate* isolate = ToIsolate(frame);
+  ScriptState* script_state = ToScriptStateForMainWorld(frame);
+  DCHECK(script_state);
+  ScriptState::Scope scope(script_state);
+  v8::Local<v8::Object> global = script_state->GetContext()->Global();
+  v8::Local<v8::Value> overlay_host_obj =
+      ToV8(overlay_host_.Get(), global, isolate);
+  DCHECK(!overlay_host_obj.IsEmpty());
+  global
+      ->Set(script_state->GetContext(),
+            V8AtomicString(isolate, "InspectorOverlayHost"), overlay_host_obj)
+      .ToChecked();
+
+#if OS(WIN)
+  EvaluateInOverlay("setPlatform", "windows");
+#elif OS(MACOSX)
+  EvaluateInOverlay("setPlatform", "mac");
+#elif OS(POSIX)
+  EvaluateInOverlay("setPlatform", "linux");
+#endif
+
+  return overlay_page_.Get();
+}
+
+LocalFrame* InspectorOverlay::OverlayMainFrame() {
+  return ToLocalFrame(OverlayPage()->MainFrame());
+}
+
+void InspectorOverlay::Reset(const IntSize& viewport_size,
+                             const IntPoint& document_scroll_offset) {
+  std::unique_ptr<protocol::DictionaryValue> reset_data =
+      protocol::DictionaryValue::create();
+  reset_data->setDouble(
+      "deviceScaleFactor",
+      frame_impl_->GetFrame()->GetPage()->DeviceScaleFactorDeprecated());
+  reset_data->setDouble(
+      "pageScaleFactor",
+      frame_impl_->GetFrame()->GetPage()->GetVisualViewport().Scale());
+
+  IntRect viewport_in_screen =
+      frame_impl_->GetFrame()->GetPage()->GetChromeClient().ViewportToScreen(
+          IntRect(IntPoint(), viewport_size), frame_impl_->GetFrame()->View());
+  reset_data->setObject("viewportSize",
+                        BuildObjectForSize(viewport_in_screen.Size()));
+
+  // The zoom factor in the overlay frame already has been multiplied by the
+  // window to viewport scale (aka device scale factor), so cancel it.
+  reset_data->setDouble(
+      "pageZoomFactor",
+      frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale());
+
+  reset_data->setInteger("scrollX", document_scroll_offset.X());
+  reset_data->setInteger("scrollY", document_scroll_offset.Y());
+  EvaluateInOverlay("reset", std::move(reset_data));
+}
+
+void InspectorOverlay::EvaluateInOverlay(const String& method,
+                                         const String& argument) {
+  ScriptForbiddenScope::AllowUserAgentScript allow_script;
+  std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
+  command->pushValue(protocol::StringValue::create(method));
+  command->pushValue(protocol::StringValue::create(argument));
+  ToLocalFrame(OverlayPage()->MainFrame())
+      ->GetScriptController()
+      .ExecuteScriptInMainWorld(
+          "dispatch(" + command->serialize() + ")",
+          ScriptController::kExecuteScriptWhenScriptsDisabled);
+}
+
+void InspectorOverlay::EvaluateInOverlay(
+    const String& method,
+    std::unique_ptr<protocol::Value> argument) {
+  ScriptForbiddenScope::AllowUserAgentScript allow_script;
+  std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
+  command->pushValue(protocol::StringValue::create(method));
+  command->pushValue(std::move(argument));
+  ToLocalFrame(OverlayPage()->MainFrame())
+      ->GetScriptController()
+      .ExecuteScriptInMainWorld(
+          "dispatch(" + command->serialize() + ")",
+          ScriptController::kExecuteScriptWhenScriptsDisabled);
+}
+
+String InspectorOverlay::EvaluateInOverlayForTest(const String& script) {
+  ScriptForbiddenScope::AllowUserAgentScript allow_script;
+  v8::HandleScope handle_scope(ToIsolate(OverlayMainFrame()));
+  v8::Local<v8::Value> string =
+      ToLocalFrame(OverlayPage()->MainFrame())
+          ->GetScriptController()
+          .ExecuteScriptInMainWorldAndReturnValue(
+              ScriptSourceCode(script),
+              ScriptController::kExecuteScriptWhenScriptsDisabled);
+  return ToCoreStringWithUndefinedOrNullCheck(string);
+}
+
+void InspectorOverlay::OnTimer(TimerBase*) {
+  resize_timer_active_ = false;
+  ScheduleUpdate();
+}
+
+void InspectorOverlay::ClearInternal() {
+  if (overlay_page_) {
+    overlay_page_->WillBeDestroyed();
+    overlay_page_.Clear();
+    overlay_chrome_client_.Clear();
+  }
+  resize_timer_active_ = false;
+  paused_in_debugger_message_ = String();
+  inspect_mode_ = InspectorDOMAgent::kNotSearching;
+  timer_.Stop();
+  HideHighlight();
+}
+
+void InspectorOverlay::Clear() {
+  ClearInternal();
+  v8_session_ = nullptr;
+  dom_agent_.Clear();
+  overlay_host_->SetListener(nullptr);
+}
+
+void InspectorOverlay::OverlayResumed() {
+  if (v8_session_)
+    v8_session_->resume();
+}
+
+void InspectorOverlay::OverlaySteppedOver() {
+  if (v8_session_)
+    v8_session_->stepOver();
+}
+
+void InspectorOverlay::Suspend() {
+  if (!suspended_) {
+    suspended_ = true;
+    ClearInternal();
+  }
+}
+
+void InspectorOverlay::Resume() {
+  suspended_ = false;
+}
+
+void InspectorOverlay::PageLayoutInvalidated(bool resized) {
+  if (resized && draw_view_size_) {
+    resize_timer_active_ = true;
+    timer_.StartOneShot(1, BLINK_FROM_HERE);
+  }
+  ScheduleUpdate();
+}
+
+void InspectorOverlay::SetShowViewportSizeOnResize(bool show) {
+  draw_view_size_ = show;
+}
+
+bool InspectorOverlay::HandleMouseMove(const WebMouseEvent& event) {
+  if (!ShouldSearchForNode())
+    return false;
+
+  LocalFrame* frame = frame_impl_->GetFrame();
+  if (!frame || !frame->View() || frame->ContentLayoutItem().IsNull())
+    return false;
+  Node* node = HoveredNodeForEvent(
+      frame, event, event.GetModifiers() & WebInputEvent::kShiftKey);
+
+  // Do not highlight within user agent shadow root unless requested.
+  if (inspect_mode_ != InspectorDOMAgent::kSearchingForUAShadow) {
+    ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node);
+    if (shadow_root)
+      node = &shadow_root->host();
+  }
+
+  // Shadow roots don't have boxes - use host element instead.
+  if (node && node->IsShadowRoot())
+    node = node->ParentOrShadowHostNode();
+
+  if (!node)
+    return true;
+
+  if (node->IsFrameOwnerElement()) {
+    HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(node);
+    if (frame_owner->ContentFrame() &&
+        !frame_owner->ContentFrame()->IsLocalFrame()) {
+      // Do not consume event so that remote frame can handle it.
+      HideHighlight();
+      hovered_node_for_inspect_mode_.Clear();
+      return false;
+    }
+  }
+
+  Node* event_target = (event.GetModifiers() & WebInputEvent::kShiftKey)
+                           ? HoveredNodeForEvent(frame, event, false)
+                           : nullptr;
+  if (event_target == node)
+    event_target = nullptr;
+
+  if (node && inspect_mode_highlight_config_) {
+    hovered_node_for_inspect_mode_ = node;
+    if (dom_agent_)
+      dom_agent_->NodeHighlightedInOverlay(node);
+    HighlightNode(node, event_target, *inspect_mode_highlight_config_,
+                  (event.GetModifiers() &
+                   (WebInputEvent::kControlKey | WebInputEvent::kMetaKey)));
+  }
+  return true;
+}
+
+bool InspectorOverlay::HandleMouseDown() {
+  swallow_next_mouse_up_ = false;
+  if (!ShouldSearchForNode())
+    return false;
+
+  if (hovered_node_for_inspect_mode_) {
+    swallow_next_mouse_up_ = true;
+    Inspect(hovered_node_for_inspect_mode_.Get());
+    hovered_node_for_inspect_mode_.Clear();
+    return true;
+  }
+  return false;
+}
+
+bool InspectorOverlay::HandleMouseUp() {
+  if (swallow_next_mouse_up_) {
+    swallow_next_mouse_up_ = false;
+    return true;
+  }
+  return false;
+}
+
+bool InspectorOverlay::HandleGestureEvent(const WebGestureEvent& event) {
+  if (!ShouldSearchForNode() || event.GetType() != WebInputEvent::kGestureTap)
+    return false;
+  Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
+  if (node && inspect_mode_highlight_config_) {
+    HighlightNode(node, *inspect_mode_highlight_config_, false);
+    Inspect(node);
+    return true;
+  }
+  return false;
+}
+
+bool InspectorOverlay::HandleTouchEvent(const WebTouchEvent& event) {
+  if (!ShouldSearchForNode())
+    return false;
+  Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
+  if (node && inspect_mode_highlight_config_) {
+    HighlightNode(node, *inspect_mode_highlight_config_, false);
+    Inspect(node);
+    return true;
+  }
+  return false;
+}
+
+bool InspectorOverlay::ShouldSearchForNode() {
+  return inspect_mode_ != InspectorDOMAgent::kNotSearching;
+}
+
+void InspectorOverlay::Inspect(Node* node) {
+  if (dom_agent_)
+    dom_agent_->Inspect(node);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.h b/third_party/WebKit/Source/web/InspectorOverlay.h
new file mode 100644
index 0000000..6cc0a65
--- /dev/null
+++ b/third_party/WebKit/Source/web/InspectorOverlay.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InspectorOverlay_h
+#define InspectorOverlay_h
+
+#include <v8-inspector.h>
+#include <memory>
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorOverlayHost.h"
+#include "core/inspector/protocol/Forward.h"
+#include "platform/Timer.h"
+#include "platform/geometry/FloatQuad.h"
+#include "platform/geometry/LayoutRect.h"
+#include "platform/graphics/Color.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/RefPtr.h"
+#include "platform/wtf/text/WTFString.h"
+#include "public/platform/WebInputEvent.h"
+
+namespace blink {
+
+class Color;
+class LocalFrame;
+class Node;
+class Page;
+class PageOverlay;
+class WebGestureEvent;
+class WebMouseEvent;
+class WebLocalFrameImpl;
+class WebTouchEvent;
+
+namespace protocol {
+class Value;
+}
+
+class InspectorOverlay final
+    : public GarbageCollectedFinalized<InspectorOverlay>,
+      public InspectorDOMAgent::Client,
+      public InspectorOverlayHost::Listener {
+  USING_GARBAGE_COLLECTED_MIXIN(InspectorOverlay);
+
+ public:
+  explicit InspectorOverlay(WebLocalFrameImpl*);
+  ~InspectorOverlay() override;
+  DECLARE_TRACE();
+
+  void Init(v8_inspector::V8InspectorSession*, InspectorDOMAgent*);
+
+  void Clear();
+  void Suspend();
+  void Resume();
+  bool HandleInputEvent(const WebInputEvent&);
+  void PageLayoutInvalidated(bool resized);
+  void SetShowViewportSizeOnResize(bool);
+  void ShowReloadingBlanket();
+  void HideReloadingBlanket();
+  void SetPausedInDebuggerMessage(const String&);
+
+  // Does not yet include paint.
+  void UpdateAllLifecyclePhases();
+
+  PageOverlay* GetPageOverlay() { return page_overlay_.get(); };
+  String EvaluateInOverlayForTest(const String&);
+
+ private:
+  class InspectorOverlayChromeClient;
+  class InspectorPageOverlayDelegate;
+
+  // InspectorOverlayHost::Listener implementation.
+  void OverlayResumed() override;
+  void OverlaySteppedOver() override;
+
+  // InspectorDOMAgent::Client implementation.
+  void HideHighlight() override;
+  void HighlightNode(Node*,
+                     const InspectorHighlightConfig&,
+                     bool omit_tooltip) override;
+  void HighlightQuad(std::unique_ptr<FloatQuad>,
+                     const InspectorHighlightConfig&) override;
+  void SetInspectMode(InspectorDOMAgent::SearchMode,
+                      std::unique_ptr<InspectorHighlightConfig>) override;
+
+  void HighlightNode(Node*,
+                     Node* event_target,
+                     const InspectorHighlightConfig&,
+                     bool omit_tooltip);
+  bool IsEmpty();
+  void DrawNodeHighlight();
+  void DrawQuadHighlight();
+  void DrawPausedInDebuggerMessage();
+  void DrawViewSize();
+
+  float WindowToViewportScale() const;
+
+  Page* OverlayPage();
+  LocalFrame* OverlayMainFrame();
+  void Reset(const IntSize& viewport_size,
+             const IntPoint& document_scroll_offset);
+  void EvaluateInOverlay(const String& method, const String& argument);
+  void EvaluateInOverlay(const String& method,
+                         std::unique_ptr<protocol::Value> argument);
+  void OnTimer(TimerBase*);
+  void RebuildOverlayPage();
+  void Invalidate();
+  void ScheduleUpdate();
+  void ClearInternal();
+
+  bool HandleMouseDown();
+  bool HandleMouseUp();
+  bool HandleGestureEvent(const WebGestureEvent&);
+  bool HandleTouchEvent(const WebTouchEvent&);
+  bool HandleMouseMove(const WebMouseEvent&);
+  bool ShouldSearchForNode();
+  void Inspect(Node*);
+
+  Member<WebLocalFrameImpl> frame_impl_;
+  String paused_in_debugger_message_;
+  Member<Node> highlight_node_;
+  Member<Node> event_target_node_;
+  InspectorHighlightConfig node_highlight_config_;
+  std::unique_ptr<FloatQuad> highlight_quad_;
+  Member<Page> overlay_page_;
+  Member<InspectorOverlayChromeClient> overlay_chrome_client_;
+  Member<InspectorOverlayHost> overlay_host_;
+  InspectorHighlightConfig quad_highlight_config_;
+  bool draw_view_size_;
+  bool resize_timer_active_;
+  bool omit_tooltip_;
+  TaskRunnerTimer<InspectorOverlay> timer_;
+  bool suspended_;
+  bool show_reloading_blanket_;
+  bool in_layout_;
+  bool needs_update_;
+  v8_inspector::V8InspectorSession* v8_session_;
+  Member<InspectorDOMAgent> dom_agent_;
+  std::unique_ptr<PageOverlay> page_overlay_;
+  Member<Node> hovered_node_for_inspect_mode_;
+  bool swallow_next_mouse_up_;
+  InspectorDOMAgent::SearchMode inspect_mode_;
+  std::unique_ptr<InspectorHighlightConfig> inspect_mode_highlight_config_;
+};
+
+}  // namespace blink
+
+#endif  // InspectorOverlay_h
diff --git a/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp b/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp
deleted file mode 100644
index 86e9716..0000000
--- a/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "web/InspectorOverlayAgent.h"
-
-#include <memory>
-
-#include "bindings/core/v8/ScriptController.h"
-#include "bindings/core/v8/ScriptSourceCode.h"
-#include "bindings/core/v8/V8Binding.h"
-#include "bindings/core/v8/V8InspectorOverlayHost.h"
-#include "core/dom/DOMNodeIds.h"
-#include "core/dom/Node.h"
-#include "core/dom/StaticNodeList.h"
-#include "core/dom/TaskRunnerHelper.h"
-#include "core/frame/FrameView.h"
-#include "core/frame/LocalFrame.h"
-#include "core/frame/LocalFrameClient.h"
-#include "core/frame/Settings.h"
-#include "core/frame/VisualViewport.h"
-#include "core/html/HTMLFrameOwnerElement.h"
-#include "core/input/EventHandler.h"
-#include "core/inspector/IdentifiersFactory.h"
-#include "core/inspector/InspectedFrames.h"
-#include "core/inspector/InspectorDOMAgent.h"
-#include "core/inspector/InspectorOverlayHost.h"
-#include "core/layout/api/LayoutViewItem.h"
-#include "core/loader/EmptyClients.h"
-#include "core/loader/FrameLoadRequest.h"
-#include "core/page/ChromeClient.h"
-#include "core/page/Page.h"
-#include "platform/ScriptForbiddenScope.h"
-#include "platform/graphics/Color.h"
-#include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/paint/CullRect.h"
-#include "platform/wtf/AutoReset.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebData.h"
-#include "v8/include/v8.h"
-#include "web/ChromeClientImpl.h"
-#include "web/PageOverlay.h"
-#include "web/WebInputEventConversion.h"
-#include "web/WebLocalFrameImpl.h"
-#include "web/WebViewImpl.h"
-
-namespace blink {
-
-using protocol::Maybe;
-using protocol::Response;
-
-namespace {
-
-namespace OverlayAgentState {
-static const char kEnabled[] = "enabled";
-static const char kShowDebugBorders[] = "showDebugBorders";
-static const char kShowFPSCounter[] = "showFPSCounter";
-static const char kShowPaintRects[] = "showPaintRects";
-static const char kShowScrollBottleneckRects[] = "showScrollBottleneckRects";
-static const char kShowSizeOnResize[] = "showSizeOnResize";
-static const char kSuspended[] = "suspended";
-static const char kPausedInDebuggerMessage[] = "pausedInDebuggerMessage";
-}
-
-Node* HoveredNodeForPoint(LocalFrame* frame,
-                          const IntPoint& point_in_root_frame,
-                          bool ignore_pointer_events_none) {
-  HitTestRequest::HitTestRequestType hit_type =
-      HitTestRequest::kMove | HitTestRequest::kReadOnly |
-      HitTestRequest::kAllowChildFrameContent;
-  if (ignore_pointer_events_none)
-    hit_type |= HitTestRequest::kIgnorePointerEventsNone;
-  HitTestRequest request(hit_type);
-  HitTestResult result(request,
-                       frame->View()->RootFrameToContents(point_in_root_frame));
-  frame->ContentLayoutItem().HitTest(result);
-  Node* node = result.InnerPossiblyPseudoNode();
-  while (node && node->getNodeType() == Node::kTextNode)
-    node = node->parentNode();
-  return node;
-}
-
-Node* HoveredNodeForEvent(LocalFrame* frame,
-                          const WebGestureEvent& event,
-                          bool ignore_pointer_events_none) {
-  return HoveredNodeForPoint(frame,
-                             RoundedIntPoint(event.PositionInRootFrame()),
-                             ignore_pointer_events_none);
-}
-
-Node* HoveredNodeForEvent(LocalFrame* frame,
-                          const WebMouseEvent& event,
-                          bool ignore_pointer_events_none) {
-  return HoveredNodeForPoint(frame,
-                             RoundedIntPoint(event.PositionInRootFrame()),
-                             ignore_pointer_events_none);
-}
-
-Node* HoveredNodeForEvent(LocalFrame* frame,
-                          const WebTouchEvent& event,
-                          bool ignore_pointer_events_none) {
-  if (!event.touches_length)
-    return nullptr;
-  WebTouchPoint transformed_point = event.TouchPointInRootFrame(0);
-  return HoveredNodeForPoint(frame, RoundedIntPoint(transformed_point.position),
-                             ignore_pointer_events_none);
-}
-
-bool ParseQuad(std::unique_ptr<protocol::Array<double>> quad_array,
-               FloatQuad* quad) {
-  const size_t kCoordinatesInQuad = 8;
-  if (!quad_array || quad_array->length() != kCoordinatesInQuad)
-    return false;
-  quad->SetP1(FloatPoint(quad_array->get(0), quad_array->get(1)));
-  quad->SetP2(FloatPoint(quad_array->get(2), quad_array->get(3)));
-  quad->SetP3(FloatPoint(quad_array->get(4), quad_array->get(5)));
-  quad->SetP4(FloatPoint(quad_array->get(6), quad_array->get(7)));
-  return true;
-}
-
-}  // namespace
-
-class InspectorOverlayAgent::InspectorPageOverlayDelegate final
-    : public PageOverlay::Delegate {
- public:
-  explicit InspectorPageOverlayDelegate(InspectorOverlayAgent& overlay)
-      : overlay_(&overlay) {}
-
-  void PaintPageOverlay(const PageOverlay&,
-                        GraphicsContext& graphics_context,
-                        const WebSize& web_view_size) const override {
-    if (overlay_->IsEmpty())
-      return;
-
-    FrameView* view = overlay_->OverlayMainFrame()->View();
-    DCHECK(!view->NeedsLayout());
-    view->Paint(graphics_context,
-                CullRect(IntRect(0, 0, view->Width(), view->Height())));
-  }
-
- private:
-  Persistent<InspectorOverlayAgent> overlay_;
-};
-
-class InspectorOverlayAgent::InspectorOverlayChromeClient final
-    : public EmptyChromeClient {
- public:
-  static InspectorOverlayChromeClient* Create(ChromeClient& client,
-                                              InspectorOverlayAgent& overlay) {
-    return new InspectorOverlayChromeClient(client, overlay);
-  }
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    visitor->Trace(client_);
-    visitor->Trace(overlay_);
-    EmptyChromeClient::Trace(visitor);
-  }
-
-  void SetCursor(const Cursor& cursor, LocalFrame* local_root) override {
-    ToChromeClientImpl(client_)->SetCursorOverridden(false);
-    ToChromeClientImpl(client_)->SetCursor(cursor,
-                                           overlay_->frame_impl_->GetFrame());
-    ToChromeClientImpl(client_)->SetCursorOverridden(false);
-  }
-
-  void SetToolTip(LocalFrame& frame,
-                  const String& tooltip,
-                  TextDirection direction) override {
-    DCHECK_EQ(&frame, overlay_->OverlayMainFrame());
-    client_->SetToolTip(*overlay_->frame_impl_->GetFrame(), tooltip, direction);
-  }
-
-  void InvalidateRect(const IntRect&) override { overlay_->Invalidate(); }
-
-  void ScheduleAnimation(LocalFrame* frame) override {
-    if (overlay_->in_layout_)
-      return;
-
-    client_->ScheduleAnimation(frame);
-  }
-
- private:
-  InspectorOverlayChromeClient(ChromeClient& client,
-                               InspectorOverlayAgent& overlay)
-      : client_(&client), overlay_(&overlay) {}
-
-  Member<ChromeClient> client_;
-  Member<InspectorOverlayAgent> overlay_;
-};
-
-InspectorOverlayAgent::InspectorOverlayAgent(
-    WebLocalFrameImpl* frame_impl,
-    InspectedFrames* inspected_frames,
-    v8_inspector::V8InspectorSession* v8_session,
-    InspectorDOMAgent* dom_agent)
-    : frame_impl_(frame_impl),
-      inspected_frames_(inspected_frames),
-      enabled_(false),
-      overlay_host_(new InspectorOverlayHost(this)),
-      draw_view_size_(false),
-      resize_timer_active_(false),
-      omit_tooltip_(false),
-      timer_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer,
-                                   frame_impl->GetFrame()),
-             this,
-             &InspectorOverlayAgent::OnTimer),
-      suspended_(false),
-      show_reloading_blanket_(false),
-      in_layout_(false),
-      needs_update_(false),
-      v8_session_(v8_session),
-      dom_agent_(dom_agent),
-      swallow_next_mouse_up_(false),
-      inspect_mode_(kNotSearching),
-      backend_node_id_to_inspect_(0) {}
-
-InspectorOverlayAgent::~InspectorOverlayAgent() {
-  DCHECK(!overlay_page_);
-}
-
-DEFINE_TRACE(InspectorOverlayAgent) {
-  visitor->Trace(frame_impl_);
-  visitor->Trace(inspected_frames_);
-  visitor->Trace(highlight_node_);
-  visitor->Trace(event_target_node_);
-  visitor->Trace(overlay_page_);
-  visitor->Trace(overlay_chrome_client_);
-  visitor->Trace(overlay_host_);
-  visitor->Trace(dom_agent_);
-  visitor->Trace(hovered_node_for_inspect_mode_);
-  InspectorBaseAgent::Trace(visitor);
-}
-
-void InspectorOverlayAgent::Restore() {
-  if (state_->booleanProperty(OverlayAgentState::kEnabled, false))
-    enabled_ = true;
-  setShowDebugBorders(
-      state_->booleanProperty(OverlayAgentState::kShowDebugBorders, false));
-  setShowFPSCounter(
-      state_->booleanProperty(OverlayAgentState::kShowFPSCounter, false));
-  setShowPaintRects(
-      state_->booleanProperty(OverlayAgentState::kShowPaintRects, false));
-  setShowScrollBottleneckRects(state_->booleanProperty(
-      OverlayAgentState::kShowScrollBottleneckRects, false));
-  setShowViewportSizeOnResize(
-      state_->booleanProperty(OverlayAgentState::kShowSizeOnResize, false));
-  String message;
-  state_->getString(OverlayAgentState::kPausedInDebuggerMessage, &message);
-  setPausedInDebuggerMessage(message);
-  setSuspended(state_->booleanProperty(OverlayAgentState::kSuspended, false));
-}
-
-Response InspectorOverlayAgent::enable() {
-  if (!dom_agent_->Enabled())
-    return Response::Error("DOM should be enabled first");
-  state_->setBoolean(OverlayAgentState::kEnabled, true);
-  enabled_ = true;
-  if (backend_node_id_to_inspect_)
-    GetFrontend()->inspectNodeRequested(backend_node_id_to_inspect_);
-  backend_node_id_to_inspect_ = 0;
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::disable() {
-  state_->setBoolean(OverlayAgentState::kEnabled, false);
-  enabled_ = false;
-  setShowDebugBorders(false);
-  setShowFPSCounter(false);
-  setShowPaintRects(false);
-  setShowScrollBottleneckRects(false);
-  setShowViewportSizeOnResize(false);
-  setPausedInDebuggerMessage(String());
-  setSuspended(false);
-  SetSearchingForNode(kNotSearching,
-                      Maybe<protocol::Overlay::HighlightConfig>());
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setShowDebugBorders(bool show) {
-  state_->setBoolean(OverlayAgentState::kShowDebugBorders, show);
-  if (show) {
-    Response response = CompositingEnabled();
-    if (!response.isSuccess())
-      return response;
-  }
-  frame_impl_->ViewImpl()->SetShowDebugBorders(show);
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setShowFPSCounter(bool show) {
-  state_->setBoolean(OverlayAgentState::kShowFPSCounter, show);
-  if (show) {
-    Response response = CompositingEnabled();
-    if (!response.isSuccess())
-      return response;
-  }
-  frame_impl_->ViewImpl()->SetShowFPSCounter(show);
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setShowPaintRects(bool show) {
-  state_->setBoolean(OverlayAgentState::kShowPaintRects, show);
-  if (show) {
-    Response response = CompositingEnabled();
-    if (!response.isSuccess())
-      return response;
-  }
-  frame_impl_->ViewImpl()->SetShowPaintRects(show);
-  if (!show && frame_impl_->GetFrameView())
-    frame_impl_->GetFrameView()->Invalidate();
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setShowScrollBottleneckRects(bool show) {
-  state_->setBoolean(OverlayAgentState::kShowScrollBottleneckRects, show);
-  if (show) {
-    Response response = CompositingEnabled();
-    if (!response.isSuccess())
-      return response;
-  }
-  frame_impl_->ViewImpl()->SetShowScrollBottleneckRects(show);
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setShowViewportSizeOnResize(bool show) {
-  state_->setBoolean(OverlayAgentState::kShowSizeOnResize, show);
-  draw_view_size_ = show;
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setPausedInDebuggerMessage(
-    Maybe<String> message) {
-  String just_message = message.fromMaybe(String());
-  state_->setString(OverlayAgentState::kPausedInDebuggerMessage, just_message);
-  paused_in_debugger_message_ = just_message;
-  ScheduleUpdate();
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setSuspended(bool suspended) {
-  state_->setBoolean(OverlayAgentState::kSuspended, suspended);
-  if (suspended && !suspended_ && !show_reloading_blanket_)
-    ClearInternal();
-  suspended_ = suspended;
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::setInspectMode(
-    const String& mode,
-    Maybe<protocol::Overlay::HighlightConfig> highlight_config) {
-  SearchMode search_mode;
-  if (mode == protocol::Overlay::InspectModeEnum::SearchForNode) {
-    search_mode = kSearchingForNormal;
-  } else if (mode == protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM) {
-    search_mode = kSearchingForUAShadow;
-  } else if (mode == protocol::Overlay::InspectModeEnum::None) {
-    search_mode = kNotSearching;
-  } else {
-    return Response::Error(
-        String("Unknown mode \"" + mode + "\" was provided."));
-  }
-
-  if (search_mode != kNotSearching) {
-    Response response = dom_agent_->PushDocumentUponHandlelessOperation();
-    if (!response.isSuccess())
-      return response;
-  }
-
-  return SetSearchingForNode(search_mode, std::move(highlight_config));
-}
-
-Response InspectorOverlayAgent::highlightRect(
-    int x,
-    int y,
-    int width,
-    int height,
-    Maybe<protocol::DOM::RGBA> color,
-    Maybe<protocol::DOM::RGBA> outline_color) {
-  std::unique_ptr<FloatQuad> quad =
-      WTF::WrapUnique(new FloatQuad(FloatRect(x, y, width, height)));
-  InnerHighlightQuad(std::move(quad), std::move(color),
-                     std::move(outline_color));
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::highlightQuad(
-    std::unique_ptr<protocol::Array<double>> quad_array,
-    Maybe<protocol::DOM::RGBA> color,
-    Maybe<protocol::DOM::RGBA> outline_color) {
-  std::unique_ptr<FloatQuad> quad = WTF::MakeUnique<FloatQuad>();
-  if (!ParseQuad(std::move(quad_array), quad.get()))
-    return Response::Error("Invalid Quad format");
-  InnerHighlightQuad(std::move(quad), std::move(color),
-                     std::move(outline_color));
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::highlightNode(
-    std::unique_ptr<protocol::Overlay::HighlightConfig>
-        highlight_inspector_object,
-    Maybe<int> node_id,
-    Maybe<int> backend_node_id,
-    Maybe<String> object_id) {
-  Node* node = nullptr;
-  Response response;
-  if (node_id.isJust()) {
-    response = dom_agent_->AssertNode(node_id.fromJust(), node);
-  } else if (backend_node_id.isJust()) {
-    node = DOMNodeIds::NodeForId(backend_node_id.fromJust());
-    response = !node ? Response::Error("No node found for given backend id")
-                     : Response::OK();
-  } else if (object_id.isJust()) {
-    response = dom_agent_->NodeForRemoteObjectId(object_id.fromJust(), node);
-  } else {
-    response = Response::Error(
-        "Either nodeId, backendNodeId or objectId must be specified");
-  }
-
-  if (!response.isSuccess())
-    return response;
-
-  std::unique_ptr<InspectorHighlightConfig> highlight_config;
-  response = HighlightConfigFromInspectorObject(
-      std::move(highlight_inspector_object), &highlight_config);
-  if (!response.isSuccess())
-    return response;
-
-  InnerHighlightNode(node, nullptr, *highlight_config, false);
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::highlightFrame(
-    const String& frame_id,
-    Maybe<protocol::DOM::RGBA> color,
-    Maybe<protocol::DOM::RGBA> outline_color) {
-  LocalFrame* frame =
-      IdentifiersFactory::FrameById(inspected_frames_, frame_id);
-  // FIXME: Inspector doesn't currently work cross process.
-  if (frame && frame->DeprecatedLocalOwner()) {
-    std::unique_ptr<InspectorHighlightConfig> highlight_config =
-        WTF::MakeUnique<InspectorHighlightConfig>();
-    highlight_config->show_info = true;  // Always show tooltips for frames.
-    highlight_config->content =
-        InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr));
-    highlight_config->content_outline =
-        InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr));
-    InnerHighlightNode(frame->DeprecatedLocalOwner(), nullptr,
-                       *highlight_config, false);
-  }
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::hideHighlight() {
-  InnerHideHighlight();
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::getHighlightObjectForTest(
-    int node_id,
-    std::unique_ptr<protocol::DictionaryValue>* result) {
-  Node* node = nullptr;
-  Response response = dom_agent_->AssertNode(node_id, node);
-  if (!response.isSuccess())
-    return response;
-  InspectorHighlight highlight(node, InspectorHighlight::DefaultConfig(), true);
-  *result = highlight.AsProtocolValue();
-  return Response::OK();
-}
-
-void InspectorOverlayAgent::Invalidate() {
-  if (!page_overlay_) {
-    page_overlay_ = PageOverlay::Create(
-        frame_impl_, WTF::WrapUnique(new InspectorPageOverlayDelegate(*this)));
-  }
-
-  page_overlay_->Update();
-}
-
-void InspectorOverlayAgent::UpdateAllLifecyclePhases() {
-  if (IsEmpty())
-    return;
-
-  AutoReset<bool> scoped(&in_layout_, true);
-  if (needs_update_) {
-    needs_update_ = false;
-    RebuildOverlayPage();
-  }
-  OverlayMainFrame()->View()->UpdateAllLifecyclePhases();
-}
-
-bool InspectorOverlayAgent::HandleInputEvent(const WebInputEvent& input_event) {
-  bool handled = false;
-
-  if (IsEmpty())
-    return false;
-
-  if (input_event.GetType() == WebInputEvent::kGestureTap) {
-    // We only have a use for gesture tap.
-    WebGestureEvent transformed_event = TransformWebGestureEvent(
-        frame_impl_->GetFrameView(),
-        static_cast<const WebGestureEvent&>(input_event));
-    handled = HandleGestureEvent(transformed_event);
-    if (handled)
-      return true;
-
-    OverlayMainFrame()->GetEventHandler().HandleGestureEvent(transformed_event);
-  }
-  if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
-    WebMouseEvent mouse_event =
-        TransformWebMouseEvent(frame_impl_->GetFrameView(),
-                               static_cast<const WebMouseEvent&>(input_event));
-
-    if (mouse_event.GetType() == WebInputEvent::kMouseMove)
-      handled = HandleMouseMove(mouse_event);
-    else if (mouse_event.GetType() == WebInputEvent::kMouseDown)
-      handled = HandleMouseDown();
-    else if (mouse_event.GetType() == WebInputEvent::kMouseUp)
-      handled = HandleMouseUp();
-
-    if (handled)
-      return true;
-
-    if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
-      handled = OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
-                    mouse_event, TransformWebMouseEventVector(
-                                     frame_impl_->GetFrameView(),
-                                     std::vector<const WebInputEvent*>())) !=
-                WebInputEventResult::kNotHandled;
-    }
-    if (mouse_event.GetType() == WebInputEvent::kMouseDown) {
-      handled = OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
-                    mouse_event) != WebInputEventResult::kNotHandled;
-    }
-    if (mouse_event.GetType() == WebInputEvent::kMouseUp) {
-      handled = OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
-                    mouse_event) != WebInputEventResult::kNotHandled;
-    }
-  }
-
-  if (WebInputEvent::IsTouchEventType(input_event.GetType())) {
-    WebTouchEvent transformed_event =
-        TransformWebTouchEvent(frame_impl_->GetFrameView(),
-                               static_cast<const WebTouchEvent&>(input_event));
-    handled = HandleTouchEvent(transformed_event);
-    if (handled)
-      return true;
-    OverlayMainFrame()->GetEventHandler().HandleTouchEvent(
-        transformed_event, Vector<WebTouchEvent>());
-  }
-  if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
-    OverlayMainFrame()->GetEventHandler().KeyEvent(
-        static_cast<const WebKeyboardEvent&>(input_event));
-  }
-
-  if (input_event.GetType() == WebInputEvent::kMouseWheel) {
-    WebMouseWheelEvent transformed_event = TransformWebMouseWheelEvent(
-        frame_impl_->GetFrameView(),
-        static_cast<const WebMouseWheelEvent&>(input_event));
-    handled = OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
-                  transformed_event) != WebInputEventResult::kNotHandled;
-  }
-
-  return handled;
-}
-
-void InspectorOverlayAgent::ShowReloadingBlanket() {
-  show_reloading_blanket_ = true;
-  ScheduleUpdate();
-}
-
-void InspectorOverlayAgent::HideReloadingBlanket() {
-  if (!show_reloading_blanket_)
-    return;
-  show_reloading_blanket_ = false;
-  if (suspended_)
-    ClearInternal();
-  else
-    ScheduleUpdate();
-}
-
-void InspectorOverlayAgent::InnerHideHighlight() {
-  highlight_node_.Clear();
-  event_target_node_.Clear();
-  highlight_quad_.reset();
-  ScheduleUpdate();
-}
-
-void InspectorOverlayAgent::InnerHighlightNode(
-    Node* node,
-    Node* event_target,
-    const InspectorHighlightConfig& highlight_config,
-    bool omit_tooltip) {
-  node_highlight_config_ = highlight_config;
-  highlight_node_ = node;
-  event_target_node_ = event_target;
-  omit_tooltip_ = omit_tooltip;
-  ScheduleUpdate();
-}
-
-void InspectorOverlayAgent::InnerHighlightQuad(
-    std::unique_ptr<FloatQuad> quad,
-    Maybe<protocol::DOM::RGBA> color,
-    Maybe<protocol::DOM::RGBA> outline_color) {
-  quad_content_color_ = InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr));
-  quad_content_outline_color_ =
-      InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr));
-  highlight_quad_ = std::move(quad);
-  omit_tooltip_ = false;
-  ScheduleUpdate();
-}
-
-bool InspectorOverlayAgent::IsEmpty() {
-  if (show_reloading_blanket_)
-    return false;
-  if (suspended_)
-    return true;
-  bool has_visible_elements = highlight_node_ || event_target_node_ ||
-                              highlight_quad_ ||
-                              (resize_timer_active_ && draw_view_size_) ||
-                              !paused_in_debugger_message_.IsNull();
-  return !has_visible_elements && inspect_mode_ == kNotSearching;
-}
-
-void InspectorOverlayAgent::ScheduleUpdate() {
-  if (IsEmpty()) {
-    if (page_overlay_)
-      page_overlay_.reset();
-    return;
-  }
-  needs_update_ = true;
-  LocalFrame* frame = frame_impl_->GetFrame();
-  if (frame) {
-    frame->GetPage()->GetChromeClient().ScheduleAnimation(frame);
-  }
-}
-
-void InspectorOverlayAgent::RebuildOverlayPage() {
-  FrameView* view = frame_impl_->GetFrameView();
-  LocalFrame* frame = frame_impl_->GetFrame();
-  if (!view || !frame)
-    return;
-
-  IntRect visible_rect_in_document =
-      view->GetScrollableArea()->VisibleContentRect();
-  IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
-  OverlayMainFrame()->View()->Resize(viewport_size);
-  OverlayPage()->GetVisualViewport().SetSize(viewport_size);
-  OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale());
-
-  Reset(viewport_size, visible_rect_in_document.Location());
-
-  if (show_reloading_blanket_) {
-    EvaluateInOverlay("showReloadingBlanket", "");
-    return;
-  }
-  DrawNodeHighlight();
-  DrawQuadHighlight();
-  DrawPausedInDebuggerMessage();
-  DrawViewSize();
-}
-
-static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
-    const IntSize& size) {
-  std::unique_ptr<protocol::DictionaryValue> result =
-      protocol::DictionaryValue::create();
-  result->setInteger("width", size.Width());
-  result->setInteger("height", size.Height());
-  return result;
-}
-
-void InspectorOverlayAgent::DrawNodeHighlight() {
-  if (!highlight_node_)
-    return;
-
-  String selectors = node_highlight_config_.selector_list;
-  StaticElementList* elements = nullptr;
-  DummyExceptionStateForTesting exception_state;
-  ContainerNode* query_base = highlight_node_->ContainingShadowRoot();
-  if (!query_base)
-    query_base = highlight_node_->ownerDocument();
-  if (selectors.length()) {
-    elements =
-        query_base->QuerySelectorAll(AtomicString(selectors), exception_state);
-  }
-  if (elements && !exception_state.HadException()) {
-    for (unsigned i = 0; i < elements->length(); ++i) {
-      Element* element = elements->item(i);
-      InspectorHighlight highlight(element, node_highlight_config_, false);
-      std::unique_ptr<protocol::DictionaryValue> highlight_json =
-          highlight.AsProtocolValue();
-      EvaluateInOverlay("drawHighlight", std::move(highlight_json));
-    }
-  }
-
-  bool append_element_info =
-      highlight_node_->IsElementNode() && !omit_tooltip_ &&
-      node_highlight_config_.show_info && highlight_node_->GetLayoutObject() &&
-      highlight_node_->GetDocument().GetFrame();
-  InspectorHighlight highlight(highlight_node_.Get(), node_highlight_config_,
-                               append_element_info);
-  if (event_target_node_) {
-    highlight.AppendEventTargetQuads(event_target_node_.Get(),
-                                     node_highlight_config_);
-  }
-
-  std::unique_ptr<protocol::DictionaryValue> highlight_json =
-      highlight.AsProtocolValue();
-  EvaluateInOverlay("drawHighlight", std::move(highlight_json));
-}
-
-void InspectorOverlayAgent::DrawQuadHighlight() {
-  if (!highlight_quad_)
-    return;
-
-  InspectorHighlight highlight(WindowToViewportScale());
-  highlight.AppendQuad(*highlight_quad_, quad_content_color_,
-                       quad_content_outline_color_);
-  EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue());
-}
-
-void InspectorOverlayAgent::DrawPausedInDebuggerMessage() {
-  if (inspect_mode_ == kNotSearching && !paused_in_debugger_message_.IsNull()) {
-    EvaluateInOverlay("drawPausedInDebuggerMessage",
-                      paused_in_debugger_message_);
-  }
-}
-
-void InspectorOverlayAgent::DrawViewSize() {
-  if (resize_timer_active_ && draw_view_size_)
-    EvaluateInOverlay("drawViewSize", "");
-}
-
-float InspectorOverlayAgent::WindowToViewportScale() const {
-  LocalFrame* frame = frame_impl_->GetFrame();
-  if (!frame)
-    return 1.0f;
-  return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f);
-}
-
-Page* InspectorOverlayAgent::OverlayPage() {
-  if (overlay_page_)
-    return overlay_page_.Get();
-
-  ScriptForbiddenScope::AllowUserAgentScript allow_script;
-
-  DEFINE_STATIC_LOCAL(LocalFrameClient, dummy_local_frame_client,
-                      (EmptyLocalFrameClient::Create()));
-  Page::PageClients page_clients;
-  FillWithEmptyClients(page_clients);
-  DCHECK(!overlay_chrome_client_);
-  overlay_chrome_client_ = InspectorOverlayChromeClient::Create(
-      frame_impl_->GetFrame()->GetPage()->GetChromeClient(), *this);
-  page_clients.chrome_client = overlay_chrome_client_.Get();
-  overlay_page_ = Page::Create(page_clients);
-
-  Settings& settings = frame_impl_->GetFrame()->GetPage()->GetSettings();
-  Settings& overlay_settings = overlay_page_->GetSettings();
-
-  overlay_settings.GetGenericFontFamilySettings().UpdateStandard(
-      settings.GetGenericFontFamilySettings().Standard());
-  overlay_settings.GetGenericFontFamilySettings().UpdateSerif(
-      settings.GetGenericFontFamilySettings().Serif());
-  overlay_settings.GetGenericFontFamilySettings().UpdateSansSerif(
-      settings.GetGenericFontFamilySettings().SansSerif());
-  overlay_settings.GetGenericFontFamilySettings().UpdateCursive(
-      settings.GetGenericFontFamilySettings().Cursive());
-  overlay_settings.GetGenericFontFamilySettings().UpdateFantasy(
-      settings.GetGenericFontFamilySettings().Fantasy());
-  overlay_settings.GetGenericFontFamilySettings().UpdatePictograph(
-      settings.GetGenericFontFamilySettings().Pictograph());
-  overlay_settings.SetMinimumFontSize(settings.GetMinimumFontSize());
-  overlay_settings.SetMinimumLogicalFontSize(
-      settings.GetMinimumLogicalFontSize());
-  overlay_settings.SetScriptEnabled(true);
-  overlay_settings.SetPluginsEnabled(false);
-  overlay_settings.SetLoadsImagesAutomatically(true);
-  // FIXME: http://crbug.com/363843. Inspector should probably create its
-  // own graphics layers and attach them to the tree rather than going
-  // through some non-composited paint function.
-  overlay_settings.SetAcceleratedCompositingEnabled(false);
-
-  LocalFrame* frame =
-      LocalFrame::Create(&dummy_local_frame_client, *overlay_page_, 0);
-  frame->SetView(FrameView::Create(*frame));
-  frame->Init();
-  FrameLoader& loader = frame->Loader();
-  frame->View()->SetCanHaveScrollbars(false);
-  frame->View()->SetBaseBackgroundColor(Color::kTransparent);
-
-  const WebData& overlay_page_html_resource =
-      Platform::Current()->LoadResource("InspectorOverlayPage.html");
-  loader.Load(
-      FrameLoadRequest(0, ResourceRequest(BlankURL()),
-                       SubstituteData(overlay_page_html_resource, "text/html",
-                                      "UTF-8", KURL(), kForceSynchronousLoad)));
-  v8::Isolate* isolate = ToIsolate(frame);
-  ScriptState* script_state = ToScriptStateForMainWorld(frame);
-  DCHECK(script_state);
-  ScriptState::Scope scope(script_state);
-  v8::Local<v8::Object> global = script_state->GetContext()->Global();
-  v8::Local<v8::Value> overlay_host_obj =
-      ToV8(overlay_host_.Get(), global, isolate);
-  DCHECK(!overlay_host_obj.IsEmpty());
-  global
-      ->Set(script_state->GetContext(),
-            V8AtomicString(isolate, "InspectorOverlayHost"), overlay_host_obj)
-      .ToChecked();
-
-#if OS(WIN)
-  EvaluateInOverlay("setPlatform", "windows");
-#elif OS(MACOSX)
-  EvaluateInOverlay("setPlatform", "mac");
-#elif OS(POSIX)
-  EvaluateInOverlay("setPlatform", "linux");
-#endif
-
-  return overlay_page_.Get();
-}
-
-LocalFrame* InspectorOverlayAgent::OverlayMainFrame() {
-  return ToLocalFrame(OverlayPage()->MainFrame());
-}
-
-void InspectorOverlayAgent::Reset(const IntSize& viewport_size,
-                                  const IntPoint& document_scroll_offset) {
-  std::unique_ptr<protocol::DictionaryValue> reset_data =
-      protocol::DictionaryValue::create();
-  reset_data->setDouble(
-      "deviceScaleFactor",
-      frame_impl_->GetFrame()->GetPage()->DeviceScaleFactorDeprecated());
-  reset_data->setDouble(
-      "pageScaleFactor",
-      frame_impl_->GetFrame()->GetPage()->GetVisualViewport().Scale());
-
-  IntRect viewport_in_screen =
-      frame_impl_->GetFrame()->GetPage()->GetChromeClient().ViewportToScreen(
-          IntRect(IntPoint(), viewport_size), frame_impl_->GetFrame()->View());
-  reset_data->setObject("viewportSize",
-                        BuildObjectForSize(viewport_in_screen.Size()));
-
-  // The zoom factor in the overlay frame already has been multiplied by the
-  // window to viewport scale (aka device scale factor), so cancel it.
-  reset_data->setDouble(
-      "pageZoomFactor",
-      frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale());
-
-  reset_data->setInteger("scrollX", document_scroll_offset.X());
-  reset_data->setInteger("scrollY", document_scroll_offset.Y());
-  EvaluateInOverlay("reset", std::move(reset_data));
-}
-
-void InspectorOverlayAgent::EvaluateInOverlay(const String& method,
-                                              const String& argument) {
-  ScriptForbiddenScope::AllowUserAgentScript allow_script;
-  std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
-  command->pushValue(protocol::StringValue::create(method));
-  command->pushValue(protocol::StringValue::create(argument));
-  ToLocalFrame(OverlayPage()->MainFrame())
-      ->GetScriptController()
-      .ExecuteScriptInMainWorld(
-          "dispatch(" + command->serialize() + ")",
-          ScriptController::kExecuteScriptWhenScriptsDisabled);
-}
-
-void InspectorOverlayAgent::EvaluateInOverlay(
-    const String& method,
-    std::unique_ptr<protocol::Value> argument) {
-  ScriptForbiddenScope::AllowUserAgentScript allow_script;
-  std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
-  command->pushValue(protocol::StringValue::create(method));
-  command->pushValue(std::move(argument));
-  ToLocalFrame(OverlayPage()->MainFrame())
-      ->GetScriptController()
-      .ExecuteScriptInMainWorld(
-          "dispatch(" + command->serialize() + ")",
-          ScriptController::kExecuteScriptWhenScriptsDisabled);
-}
-
-String InspectorOverlayAgent::EvaluateInOverlayForTest(const String& script) {
-  ScriptForbiddenScope::AllowUserAgentScript allow_script;
-  v8::HandleScope handle_scope(ToIsolate(OverlayMainFrame()));
-  v8::Local<v8::Value> string =
-      ToLocalFrame(OverlayPage()->MainFrame())
-          ->GetScriptController()
-          .ExecuteScriptInMainWorldAndReturnValue(
-              ScriptSourceCode(script),
-              ScriptController::kExecuteScriptWhenScriptsDisabled);
-  return ToCoreStringWithUndefinedOrNullCheck(string);
-}
-
-void InspectorOverlayAgent::OnTimer(TimerBase*) {
-  resize_timer_active_ = false;
-  ScheduleUpdate();
-}
-
-void InspectorOverlayAgent::ClearInternal() {
-  if (overlay_page_) {
-    overlay_page_->WillBeDestroyed();
-    overlay_page_.Clear();
-    overlay_chrome_client_.Clear();
-  }
-  resize_timer_active_ = false;
-  paused_in_debugger_message_ = String();
-  inspect_mode_ = kNotSearching;
-  timer_.Stop();
-  InnerHideHighlight();
-}
-
-void InspectorOverlayAgent::OverlayResumed() {
-  if (v8_session_)
-    v8_session_->resume();
-}
-
-void InspectorOverlayAgent::OverlaySteppedOver() {
-  if (v8_session_)
-    v8_session_->stepOver();
-}
-
-void InspectorOverlayAgent::PageLayoutInvalidated(bool resized) {
-  if (resized && draw_view_size_) {
-    resize_timer_active_ = true;
-    timer_.StartOneShot(1, BLINK_FROM_HERE);
-  }
-  ScheduleUpdate();
-}
-
-bool InspectorOverlayAgent::HandleMouseMove(const WebMouseEvent& event) {
-  if (!ShouldSearchForNode())
-    return false;
-
-  LocalFrame* frame = frame_impl_->GetFrame();
-  if (!frame || !frame->View() || frame->ContentLayoutItem().IsNull())
-    return false;
-  Node* node = HoveredNodeForEvent(
-      frame, event, event.GetModifiers() & WebInputEvent::kShiftKey);
-
-  // Do not highlight within user agent shadow root unless requested.
-  if (inspect_mode_ != kSearchingForUAShadow) {
-    ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node);
-    if (shadow_root)
-      node = &shadow_root->host();
-  }
-
-  // Shadow roots don't have boxes - use host element instead.
-  if (node && node->IsShadowRoot())
-    node = node->ParentOrShadowHostNode();
-
-  if (!node)
-    return true;
-
-  if (node->IsFrameOwnerElement()) {
-    HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(node);
-    if (frame_owner->ContentFrame() &&
-        !frame_owner->ContentFrame()->IsLocalFrame()) {
-      // Do not consume event so that remote frame can handle it.
-      InnerHideHighlight();
-      hovered_node_for_inspect_mode_.Clear();
-      return false;
-    }
-  }
-
-  Node* event_target = (event.GetModifiers() & WebInputEvent::kShiftKey)
-                           ? HoveredNodeForEvent(frame, event, false)
-                           : nullptr;
-  if (event_target == node)
-    event_target = nullptr;
-
-  if (node && inspect_mode_highlight_config_) {
-    hovered_node_for_inspect_mode_ = node;
-    NodeHighlightRequested(node);
-    bool omit_tooltip = event.GetModifiers() &
-                        (WebInputEvent::kControlKey | WebInputEvent::kMetaKey);
-    InnerHighlightNode(node, event_target, *inspect_mode_highlight_config_,
-                       omit_tooltip);
-  }
-  return true;
-}
-
-bool InspectorOverlayAgent::HandleMouseDown() {
-  swallow_next_mouse_up_ = false;
-  if (!ShouldSearchForNode())
-    return false;
-
-  if (hovered_node_for_inspect_mode_) {
-    swallow_next_mouse_up_ = true;
-    Inspect(hovered_node_for_inspect_mode_.Get());
-    hovered_node_for_inspect_mode_.Clear();
-    return true;
-  }
-  return false;
-}
-
-bool InspectorOverlayAgent::HandleMouseUp() {
-  if (swallow_next_mouse_up_) {
-    swallow_next_mouse_up_ = false;
-    return true;
-  }
-  return false;
-}
-
-bool InspectorOverlayAgent::HandleGestureEvent(const WebGestureEvent& event) {
-  if (!ShouldSearchForNode() || event.GetType() != WebInputEvent::kGestureTap)
-    return false;
-  Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
-  if (node && inspect_mode_highlight_config_) {
-    InnerHighlightNode(node, nullptr, *inspect_mode_highlight_config_, false);
-    Inspect(node);
-    return true;
-  }
-  return false;
-}
-
-bool InspectorOverlayAgent::HandleTouchEvent(const WebTouchEvent& event) {
-  if (!ShouldSearchForNode())
-    return false;
-  Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
-  if (node && inspect_mode_highlight_config_) {
-    InnerHighlightNode(node, nullptr, *inspect_mode_highlight_config_, false);
-    Inspect(node);
-    return true;
-  }
-  return false;
-}
-
-Response InspectorOverlayAgent::CompositingEnabled() {
-  bool main_frame = frame_impl_->ViewImpl() && !frame_impl_->Parent();
-  if (!main_frame || !frame_impl_->ViewImpl()
-                          ->GetPage()
-                          ->GetSettings()
-                          .GetAcceleratedCompositingEnabled())
-    return Response::Error("Compositing mode is not supported");
-  return Response::OK();
-}
-
-bool InspectorOverlayAgent::ShouldSearchForNode() {
-  return inspect_mode_ != kNotSearching;
-}
-
-void InspectorOverlayAgent::Inspect(Node* inspected_node) {
-  if (!inspected_node)
-    return;
-
-  Node* node = inspected_node;
-  while (node && !node->IsElementNode() && !node->IsDocumentNode() &&
-         !node->IsDocumentFragment())
-    node = node->ParentOrShadowHostNode();
-  if (!node)
-    return;
-
-  int backend_node_id = DOMNodeIds::IdForNode(node);
-  if (!enabled_) {
-    backend_node_id_to_inspect_ = backend_node_id;
-    return;
-  }
-
-  GetFrontend()->inspectNodeRequested(backend_node_id);
-}
-
-void InspectorOverlayAgent::NodeHighlightRequested(Node* node) {
-  if (!enabled_)
-    return;
-
-  while (node && !node->IsElementNode() && !node->IsDocumentNode() &&
-         !node->IsDocumentFragment())
-    node = node->ParentOrShadowHostNode();
-
-  if (!node)
-    return;
-
-  int node_id = dom_agent_->PushNodePathToFrontend(node);
-  GetFrontend()->nodeHighlightRequested(node_id);
-}
-
-Response InspectorOverlayAgent::SetSearchingForNode(
-    SearchMode search_mode,
-    Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object) {
-  if (search_mode == kNotSearching) {
-    inspect_mode_ = search_mode;
-    ScheduleUpdate();
-    hovered_node_for_inspect_mode_.Clear();
-    InnerHideHighlight();
-    return Response::OK();
-  }
-
-  std::unique_ptr<InspectorHighlightConfig> config;
-  Response response = HighlightConfigFromInspectorObject(
-      std::move(highlight_inspector_object), &config);
-  if (!response.isSuccess())
-    return response;
-  inspect_mode_ = search_mode;
-  inspect_mode_highlight_config_ = std::move(config);
-  ScheduleUpdate();
-  return Response::OK();
-}
-
-Response InspectorOverlayAgent::HighlightConfigFromInspectorObject(
-    Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object,
-    std::unique_ptr<InspectorHighlightConfig>* out_config) {
-  if (!highlight_inspector_object.isJust()) {
-    return Response::Error(
-        "Internal error: highlight configuration parameter is missing");
-  }
-
-  protocol::Overlay::HighlightConfig* config =
-      highlight_inspector_object.fromJust();
-  std::unique_ptr<InspectorHighlightConfig> highlight_config =
-      WTF::MakeUnique<InspectorHighlightConfig>();
-  highlight_config->show_info = config->getShowInfo(false);
-  highlight_config->show_rulers = config->getShowRulers(false);
-  highlight_config->show_extension_lines = config->getShowExtensionLines(false);
-  highlight_config->display_as_material = config->getDisplayAsMaterial(false);
-  highlight_config->content =
-      InspectorDOMAgent::ParseColor(config->getContentColor(nullptr));
-  highlight_config->padding =
-      InspectorDOMAgent::ParseColor(config->getPaddingColor(nullptr));
-  highlight_config->border =
-      InspectorDOMAgent::ParseColor(config->getBorderColor(nullptr));
-  highlight_config->margin =
-      InspectorDOMAgent::ParseColor(config->getMarginColor(nullptr));
-  highlight_config->event_target =
-      InspectorDOMAgent::ParseColor(config->getEventTargetColor(nullptr));
-  highlight_config->shape =
-      InspectorDOMAgent::ParseColor(config->getShapeColor(nullptr));
-  highlight_config->shape_margin =
-      InspectorDOMAgent::ParseColor(config->getShapeMarginColor(nullptr));
-  highlight_config->selector_list = config->getSelectorList("");
-
-  *out_config = std::move(highlight_config);
-  return Response::OK();
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/web/InspectorOverlayAgent.h b/third_party/WebKit/Source/web/InspectorOverlayAgent.h
deleted file mode 100644
index 9662583..0000000
--- a/third_party/WebKit/Source/web/InspectorOverlayAgent.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef InspectorOverlayAgent_h
-#define InspectorOverlayAgent_h
-
-#include <v8-inspector.h>
-#include <memory>
-#include "core/inspector/InspectorBaseAgent.h"
-#include "core/inspector/InspectorHighlight.h"
-#include "core/inspector/InspectorOverlayHost.h"
-#include "core/inspector/protocol/Overlay.h"
-#include "platform/Timer.h"
-#include "platform/geometry/FloatQuad.h"
-#include "platform/geometry/LayoutRect.h"
-#include "platform/graphics/Color.h"
-#include "platform/heap/Handle.h"
-#include "platform/wtf/RefPtr.h"
-#include "platform/wtf/text/WTFString.h"
-#include "public/platform/WebInputEvent.h"
-
-namespace blink {
-
-class Color;
-class InspectedFrames;
-class InspectorDOMAgent;
-class LocalFrame;
-class Node;
-class Page;
-class PageOverlay;
-class WebGestureEvent;
-class WebMouseEvent;
-class WebLocalFrameImpl;
-class WebTouchEvent;
-
-class InspectorOverlayAgent final
-    : public InspectorBaseAgent<protocol::Overlay::Metainfo>,
-      public InspectorOverlayHost::Listener {
-  USING_GARBAGE_COLLECTED_MIXIN(InspectorOverlayAgent);
-
- public:
-  InspectorOverlayAgent(WebLocalFrameImpl*,
-                        InspectedFrames*,
-                        v8_inspector::V8InspectorSession*,
-                        InspectorDOMAgent*);
-  ~InspectorOverlayAgent() override;
-  DECLARE_TRACE();
-
-  // protocol::Dispatcher::OverlayCommandHandler implementation.
-  protocol::Response enable() override;
-  protocol::Response disable() override;
-  protocol::Response setShowPaintRects(bool) override;
-  protocol::Response setShowDebugBorders(bool) override;
-  protocol::Response setShowFPSCounter(bool) override;
-  protocol::Response setShowScrollBottleneckRects(bool) override;
-  protocol::Response setShowViewportSizeOnResize(bool) override;
-  protocol::Response setPausedInDebuggerMessage(
-      protocol::Maybe<String>) override;
-  protocol::Response setSuspended(bool) override;
-  protocol::Response setInspectMode(
-      const String& mode,
-      protocol::Maybe<protocol::Overlay::HighlightConfig>) override;
-  protocol::Response highlightRect(
-      int x,
-      int y,
-      int width,
-      int height,
-      protocol::Maybe<protocol::DOM::RGBA> color,
-      protocol::Maybe<protocol::DOM::RGBA> outline_color) override;
-  protocol::Response highlightQuad(
-      std::unique_ptr<protocol::Array<double>> quad,
-      protocol::Maybe<protocol::DOM::RGBA> color,
-      protocol::Maybe<protocol::DOM::RGBA> outline_color) override;
-  protocol::Response highlightNode(
-      std::unique_ptr<protocol::Overlay::HighlightConfig>,
-      protocol::Maybe<int> node_id,
-      protocol::Maybe<int> backend_node_id,
-      protocol::Maybe<String> object_id) override;
-  protocol::Response hideHighlight() override;
-  protocol::Response highlightFrame(
-      const String& frame_id,
-      protocol::Maybe<protocol::DOM::RGBA> content_color,
-      protocol::Maybe<protocol::DOM::RGBA> content_outline_color) override;
-  protocol::Response getHighlightObjectForTest(
-      int node_id,
-      std::unique_ptr<protocol::DictionaryValue>* highlight) override;
-
-  // InspectorBaseAgent overrides.
-  void Restore() override;
-
-  void Inspect(Node*);
-  bool HandleInputEvent(const WebInputEvent&);
-  void PageLayoutInvalidated(bool resized);
-  void ShowReloadingBlanket();
-  void HideReloadingBlanket();
-  // Does not yet include paint.
-  void UpdateAllLifecyclePhases();
-  PageOverlay* GetPageOverlay() { return page_overlay_.get(); };
-  String EvaluateInOverlayForTest(const String&);
-
- private:
-  class InspectorOverlayChromeClient;
-  class InspectorPageOverlayDelegate;
-
-  enum SearchMode {
-    kNotSearching,
-    kSearchingForNormal,
-    kSearchingForUAShadow,
-  };
-
-  // InspectorOverlayHost::Listener implementation.
-  void OverlayResumed() override;
-  void OverlaySteppedOver() override;
-
-  bool IsEmpty();
-  void DrawNodeHighlight();
-  void DrawQuadHighlight();
-  void DrawPausedInDebuggerMessage();
-  void DrawViewSize();
-
-  float WindowToViewportScale() const;
-
-  Page* OverlayPage();
-  LocalFrame* OverlayMainFrame();
-  void Reset(const IntSize& viewport_size,
-             const IntPoint& document_scroll_offset);
-  void EvaluateInOverlay(const String& method, const String& argument);
-  void EvaluateInOverlay(const String& method,
-                         std::unique_ptr<protocol::Value> argument);
-  void OnTimer(TimerBase*);
-  void RebuildOverlayPage();
-  void Invalidate();
-  void ScheduleUpdate();
-  void ClearInternal();
-
-  bool HandleMouseDown();
-  bool HandleMouseUp();
-  bool HandleGestureEvent(const WebGestureEvent&);
-  bool HandleTouchEvent(const WebTouchEvent&);
-  bool HandleMouseMove(const WebMouseEvent&);
-
-  protocol::Response CompositingEnabled();
-
-  bool ShouldSearchForNode();
-  void NodeHighlightRequested(Node*);
-  protocol::Response SetSearchingForNode(
-      SearchMode,
-      protocol::Maybe<protocol::Overlay::HighlightConfig>);
-  protocol::Response HighlightConfigFromInspectorObject(
-      protocol::Maybe<protocol::Overlay::HighlightConfig>
-          highlight_inspector_object,
-      std::unique_ptr<InspectorHighlightConfig>*);
-  void InnerHighlightQuad(std::unique_ptr<FloatQuad>,
-                          protocol::Maybe<protocol::DOM::RGBA> color,
-                          protocol::Maybe<protocol::DOM::RGBA> outline_color);
-  void InnerHighlightNode(Node*,
-                          Node* event_target,
-                          const InspectorHighlightConfig&,
-                          bool omit_tooltip);
-  void InnerHideHighlight();
-
-  Member<WebLocalFrameImpl> frame_impl_;
-  Member<InspectedFrames> inspected_frames_;
-  bool enabled_;
-  String paused_in_debugger_message_;
-  Member<Node> highlight_node_;
-  Member<Node> event_target_node_;
-  InspectorHighlightConfig node_highlight_config_;
-  std::unique_ptr<FloatQuad> highlight_quad_;
-  Member<Page> overlay_page_;
-  Member<InspectorOverlayChromeClient> overlay_chrome_client_;
-  Member<InspectorOverlayHost> overlay_host_;
-  Color quad_content_color_;
-  Color quad_content_outline_color_;
-  bool draw_view_size_;
-  bool resize_timer_active_;
-  bool omit_tooltip_;
-  TaskRunnerTimer<InspectorOverlayAgent> timer_;
-  bool suspended_;
-  bool show_reloading_blanket_;
-  bool in_layout_;
-  bool needs_update_;
-  v8_inspector::V8InspectorSession* v8_session_;
-  Member<InspectorDOMAgent> dom_agent_;
-  std::unique_ptr<PageOverlay> page_overlay_;
-  Member<Node> hovered_node_for_inspect_mode_;
-  bool swallow_next_mouse_up_;
-  SearchMode inspect_mode_;
-  std::unique_ptr<InspectorHighlightConfig> inspect_mode_highlight_config_;
-  int backend_node_id_to_inspect_;
-};
-
-}  // namespace blink
-
-#endif  // InspectorOverlayAgent_h
diff --git a/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp b/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp
new file mode 100644
index 0000000..75ef216
--- /dev/null
+++ b/third_party/WebKit/Source/web/InspectorRenderingAgent.cpp
@@ -0,0 +1,126 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "web/InspectorRenderingAgent.h"
+
+#include "core/frame/FrameView.h"
+#include "core/frame/Settings.h"
+#include "core/page/Page.h"
+#include "web/InspectorOverlay.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/WebViewImpl.h"
+
+namespace blink {
+
+using protocol::Response;
+
+namespace RenderingAgentState {
+static const char kShowDebugBorders[] = "showDebugBorders";
+static const char kShowFPSCounter[] = "showFPSCounter";
+static const char kShowPaintRects[] = "showPaintRects";
+static const char kShowScrollBottleneckRects[] = "showScrollBottleneckRects";
+static const char kShowSizeOnResize[] = "showSizeOnResize";
+}
+
+InspectorRenderingAgent* InspectorRenderingAgent::Create(
+    WebLocalFrameImpl* web_local_frame_impl,
+    InspectorOverlay* overlay) {
+  return new InspectorRenderingAgent(web_local_frame_impl, overlay);
+}
+
+InspectorRenderingAgent::InspectorRenderingAgent(
+    WebLocalFrameImpl* web_local_frame_impl,
+    InspectorOverlay* overlay)
+    : web_local_frame_impl_(web_local_frame_impl), overlay_(overlay) {}
+
+WebViewImpl* InspectorRenderingAgent::GetWebViewImpl() {
+  return web_local_frame_impl_->ViewImpl();
+}
+
+void InspectorRenderingAgent::Restore() {
+  setShowDebugBorders(
+      state_->booleanProperty(RenderingAgentState::kShowDebugBorders, false));
+  setShowFPSCounter(
+      state_->booleanProperty(RenderingAgentState::kShowFPSCounter, false));
+  setShowPaintRects(
+      state_->booleanProperty(RenderingAgentState::kShowPaintRects, false));
+  setShowScrollBottleneckRects(state_->booleanProperty(
+      RenderingAgentState::kShowScrollBottleneckRects, false));
+  setShowViewportSizeOnResize(
+      state_->booleanProperty(RenderingAgentState::kShowSizeOnResize, false));
+}
+
+Response InspectorRenderingAgent::disable() {
+  setShowDebugBorders(false);
+  setShowFPSCounter(false);
+  setShowPaintRects(false);
+  setShowScrollBottleneckRects(false);
+  setShowViewportSizeOnResize(false);
+  return Response::OK();
+}
+
+Response InspectorRenderingAgent::setShowDebugBorders(bool show) {
+  state_->setBoolean(RenderingAgentState::kShowDebugBorders, show);
+  if (show) {
+    Response response = CompositingEnabled();
+    if (!response.isSuccess())
+      return response;
+  }
+  GetWebViewImpl()->SetShowDebugBorders(show);
+  return Response::OK();
+}
+
+Response InspectorRenderingAgent::setShowFPSCounter(bool show) {
+  state_->setBoolean(RenderingAgentState::kShowFPSCounter, show);
+  if (show) {
+    Response response = CompositingEnabled();
+    if (!response.isSuccess())
+      return response;
+  }
+  GetWebViewImpl()->SetShowFPSCounter(show);
+  return Response::OK();
+}
+
+Response InspectorRenderingAgent::setShowPaintRects(bool show) {
+  state_->setBoolean(RenderingAgentState::kShowPaintRects, show);
+  GetWebViewImpl()->SetShowPaintRects(show);
+  if (!show && web_local_frame_impl_->GetFrameView())
+    web_local_frame_impl_->GetFrameView()->Invalidate();
+  return Response::OK();
+}
+
+Response InspectorRenderingAgent::setShowScrollBottleneckRects(bool show) {
+  state_->setBoolean(RenderingAgentState::kShowScrollBottleneckRects, show);
+  if (show) {
+    Response response = CompositingEnabled();
+    if (!response.isSuccess())
+      return response;
+  }
+  GetWebViewImpl()->SetShowScrollBottleneckRects(show);
+  return Response::OK();
+}
+
+Response InspectorRenderingAgent::setShowViewportSizeOnResize(bool show) {
+  state_->setBoolean(RenderingAgentState::kShowSizeOnResize, show);
+  if (overlay_)
+    overlay_->SetShowViewportSizeOnResize(show);
+  return Response::OK();
+}
+
+Response InspectorRenderingAgent::CompositingEnabled() {
+  if (!GetWebViewImpl()
+           ->GetPage()
+           ->GetSettings()
+           .GetAcceleratedCompositingEnabled())
+    return Response::Error("Compositing mode is not supported");
+  return Response::OK();
+}
+
+DEFINE_TRACE(InspectorRenderingAgent) {
+  visitor->Trace(web_local_frame_impl_);
+  visitor->Trace(overlay_);
+  InspectorBaseAgent::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/web/InspectorRenderingAgent.h b/third_party/WebKit/Source/web/InspectorRenderingAgent.h
new file mode 100644
index 0000000..a22ba79
--- /dev/null
+++ b/third_party/WebKit/Source/web/InspectorRenderingAgent.h
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef InspectorRenderingAgent_h
+#define InspectorRenderingAgent_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/protocol/Rendering.h"
+
+namespace blink {
+
+class InspectorOverlay;
+class WebLocalFrameImpl;
+class WebViewImpl;
+
+class InspectorRenderingAgent final
+    : public InspectorBaseAgent<protocol::Rendering::Metainfo> {
+  WTF_MAKE_NONCOPYABLE(InspectorRenderingAgent);
+
+ public:
+  static InspectorRenderingAgent* Create(WebLocalFrameImpl*, InspectorOverlay*);
+
+  // protocol::Dispatcher::PageCommandHandler implementation.
+  protocol::Response setShowPaintRects(bool) override;
+  protocol::Response setShowDebugBorders(bool) override;
+  protocol::Response setShowFPSCounter(bool) override;
+  protocol::Response setShowScrollBottleneckRects(bool) override;
+  protocol::Response setShowViewportSizeOnResize(bool) override;
+
+  // InspectorBaseAgent overrides.
+  protocol::Response disable() override;
+  void Restore() override;
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  InspectorRenderingAgent(WebLocalFrameImpl*, InspectorOverlay*);
+  protocol::Response CompositingEnabled();
+  WebViewImpl* GetWebViewImpl();
+
+  Member<WebLocalFrameImpl> web_local_frame_impl_;
+  Member<InspectorOverlay> overlay_;
+};
+
+}  // namespace blink
+
+#endif  // !defined(InspectorRenderingAgent_h)
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
index b2577a4..3609203 100644
--- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
+++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
@@ -84,7 +84,8 @@
 #include "public/web/WebSettings.h"
 #include "web/DevToolsEmulator.h"
 #include "web/InspectorEmulationAgent.h"
-#include "web/InspectorOverlayAgent.h"
+#include "web/InspectorOverlay.h"
+#include "web/InspectorRenderingAgent.h"
 #include "web/WebFrameWidgetImpl.h"
 #include "web/WebInputEventConversion.h"
 #include "web/WebLocalFrameImpl.h"
@@ -232,9 +233,11 @@
 WebDevToolsAgentImpl* WebDevToolsAgentImpl::Create(
     WebLocalFrameImpl* frame,
     WebDevToolsAgentClient* client) {
+  InspectorOverlay* overlay = new InspectorOverlay(frame);
+
   if (!IsMainFrame(frame)) {
     WebDevToolsAgentImpl* agent =
-        new WebDevToolsAgentImpl(frame, client, false);
+        new WebDevToolsAgentImpl(frame, client, overlay, false);
     if (frame->FrameWidget())
       agent->LayerTreeViewChanged(
           ToWebFrameWidgetImpl(frame->FrameWidget())->LayerTreeView());
@@ -242,7 +245,8 @@
   }
 
   WebViewImpl* view = frame->ViewImpl();
-  WebDevToolsAgentImpl* agent = new WebDevToolsAgentImpl(frame, client, true);
+  WebDevToolsAgentImpl* agent =
+      new WebDevToolsAgentImpl(frame, client, overlay, true);
   agent->LayerTreeViewChanged(view->LayerTreeView());
   return agent;
 }
@@ -250,6 +254,7 @@
 WebDevToolsAgentImpl::WebDevToolsAgentImpl(
     WebLocalFrameImpl* web_local_frame_impl,
     WebDevToolsAgentClient* client,
+    InspectorOverlay* overlay,
     bool include_view_agents)
     : client_(client),
       web_local_frame_impl_(web_local_frame_impl),
@@ -257,15 +262,16 @@
           web_local_frame_impl_->GetFrame()->InstrumentingAgents()),
       resource_content_loader_(InspectorResourceContentLoader::Create(
           web_local_frame_impl_->GetFrame())),
+      overlay_(overlay),
       inspected_frames_(
           InspectedFrames::Create(web_local_frame_impl_->GetFrame())),
       resource_container_(new InspectorResourceContainer(inspected_frames_)),
+      dom_agent_(nullptr),
       page_agent_(nullptr),
       network_agent_(nullptr),
       layer_tree_agent_(nullptr),
       tracing_agent_(nullptr),
       trace_events_agent_(new InspectorTraceEvents()),
-      overlay_agent_(nullptr),
       include_view_agents_(include_view_agents),
       layer_tree_id_(0) {
   DCHECK(IsMainThread());
@@ -281,14 +287,15 @@
   visitor->Trace(web_local_frame_impl_);
   visitor->Trace(instrumenting_agents_);
   visitor->Trace(resource_content_loader_);
+  visitor->Trace(overlay_);
   visitor->Trace(inspected_frames_);
   visitor->Trace(resource_container_);
+  visitor->Trace(dom_agent_);
   visitor->Trace(page_agent_);
   visitor->Trace(network_agent_);
   visitor->Trace(layer_tree_agent_);
   visitor->Trace(tracing_agent_);
   visitor->Trace(trace_events_agent_);
-  visitor->Trace(overlay_agent_);
   visitor->Trace(session_);
 }
 
@@ -316,7 +323,8 @@
       main_thread_debugger->ContextGroupId(inspected_frames_->Root()), state);
 
   InspectorDOMAgent* dom_agent = new InspectorDOMAgent(
-      isolate, inspected_frames_.Get(), session_->V8Session());
+      isolate, inspected_frames_.Get(), session_->V8Session(), overlay_.Get());
+  dom_agent_ = dom_agent;
   session_->Append(dom_agent);
 
   InspectorLayerTreeAgent* layer_tree_agent =
@@ -330,7 +338,7 @@
   session_->Append(network_agent);
 
   InspectorCSSAgent* css_agent = InspectorCSSAgent::Create(
-      dom_agent, inspected_frames_.Get(), network_agent_,
+      dom_agent_, inspected_frames_.Get(), network_agent_,
       resource_content_loader_.Get(), resource_container_.Get());
   session_->Append(css_agent);
 
@@ -354,8 +362,8 @@
   tracing_agent_ = tracing_agent;
   session_->Append(tracing_agent);
 
-  session_->Append(
-      new InspectorDOMDebuggerAgent(isolate, dom_agent, session_->V8Session()));
+  session_->Append(new InspectorDOMDebuggerAgent(isolate, dom_agent_,
+                                                 session_->V8Session()));
 
   session_->Append(InspectorInputAgent::Create(inspected_frames_.Get()));
 
@@ -372,12 +380,6 @@
   session_->Append(
       new DeviceOrientationInspectorAgent(inspected_frames_.Get()));
 
-  InspectorOverlayAgent* overlay_agent =
-      new InspectorOverlayAgent(web_local_frame_impl_, inspected_frames_.Get(),
-                                session_->V8Session(), dom_agent);
-  overlay_agent_ = overlay_agent;
-  session_->Append(overlay_agent);
-
   tracing_agent_->SetLayerTreeId(layer_tree_id_);
   network_agent_->SetHostId(host_id);
 
@@ -386,25 +388,33 @@
     // during remote->local transition we cannot access mainFrameImpl() yet, so
     // we have to store the frame which will become the main frame later.
     session_->Append(
+        InspectorRenderingAgent::Create(web_local_frame_impl_, overlay_.Get()));
+    session_->Append(
         InspectorEmulationAgent::Create(web_local_frame_impl_, this));
     // TODO(dgozman): migrate each of the following agents to frame once module
     // is ready.
     Page* page = web_local_frame_impl_->ViewImpl()->GetPage();
     session_->Append(InspectorDatabaseAgent::Create(page));
-    session_->Append(new InspectorAccessibilityAgent(page, dom_agent));
+    session_->Append(new InspectorAccessibilityAgent(page, dom_agent_));
     session_->Append(InspectorDOMStorageAgent::Create(page));
     session_->Append(InspectorCacheStorageAgent::Create());
   }
 
+  if (overlay_)
+    overlay_->Init(session_->V8Session(), dom_agent_);
+
   Platform::Current()->CurrentThread()->AddTaskObserver(this);
 }
 
 void WebDevToolsAgentImpl::DestroySession() {
-  overlay_agent_.Clear();
+  if (overlay_)
+    overlay_->Clear();
+
   tracing_agent_.Clear();
   layer_tree_agent_.Clear();
   network_agent_.Clear();
   page_agent_.Clear();
+  dom_agent_.Clear();
 
   session_->Dispose();
   session_.Clear();
@@ -487,13 +497,13 @@
 }
 
 void WebDevToolsAgentImpl::ShowReloadingBlanket() {
-  if (overlay_agent_)
-    overlay_agent_->ShowReloadingBlanket();
+  if (overlay_)
+    overlay_->ShowReloadingBlanket();
 }
 
 void WebDevToolsAgentImpl::HideReloadingBlanket() {
-  if (overlay_agent_)
-    overlay_agent_->HideReloadingBlanket();
+  if (overlay_)
+    overlay_->HideReloadingBlanket();
 }
 
 void WebDevToolsAgentImpl::SetCPUThrottlingRate(double rate) {
@@ -527,7 +537,7 @@
 void WebDevToolsAgentImpl::InspectElementAt(
     int session_id,
     const WebPoint& point_in_root_frame) {
-  if (!overlay_agent_ || !session_ || session_->SessionId() != session_id)
+  if (!dom_agent_ || !session_ || session_->SessionId() != session_id)
     return;
   HitTestRequest::HitTestRequestType hit_type =
       HitTestRequest::kMove | HitTestRequest::kReadOnly |
@@ -547,7 +557,7 @@
   Node* node = result.InnerNode();
   if (!node && web_local_frame_impl_->GetFrame()->GetDocument())
     node = web_local_frame_impl_->GetFrame()->GetDocument()->documentElement();
-  overlay_agent_->Inspect(node);
+  dom_agent_->Inspect(node);
 }
 
 void WebDevToolsAgentImpl::FailedToRequestDevTools() {
@@ -564,8 +574,19 @@
 }
 
 void WebDevToolsAgentImpl::PageLayoutInvalidated(bool resized) {
-  if (overlay_agent_)
-    overlay_agent_->PageLayoutInvalidated(resized);
+  if (overlay_)
+    overlay_->PageLayoutInvalidated(resized);
+}
+
+void WebDevToolsAgentImpl::ConfigureOverlay(bool suspended,
+                                            const String& message) {
+  if (!overlay_)
+    return;
+  overlay_->SetPausedInDebuggerMessage(message);
+  if (suspended)
+    overlay_->Suspend();
+  else
+    overlay_->Resume();
 }
 
 void WebDevToolsAgentImpl::WaitForCreateWindow(LocalFrame* frame) {
@@ -578,10 +599,10 @@
 
 WebString WebDevToolsAgentImpl::EvaluateInWebInspectorOverlay(
     const WebString& script) {
-  if (!overlay_agent_)
+  if (!overlay_)
     return WebString();
 
-  return overlay_agent_->EvaluateInOverlayForTest(script);
+  return overlay_->EvaluateInOverlayForTest(script);
 }
 
 bool WebDevToolsAgentImpl::CacheDisabled() {
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
index a42daf4..d37a8e413 100644
--- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
+++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
@@ -48,7 +48,7 @@
 
 class GraphicsLayer;
 class InspectedFrames;
-class InspectorOverlayAgent;
+class InspectorOverlay;
 class InspectorResourceContainer;
 class InspectorResourceContentLoader;
 class InspectorTraceEvents;
@@ -74,7 +74,7 @@
 
   void WillBeDestroyed();
   WebDevToolsAgentClient* Client() { return client_; }
-  InspectorOverlayAgent* OverlayAgent() const { return overlay_agent_.Get(); }
+  InspectorOverlay* Overlay() const { return overlay_.Get(); }
   void FlushProtocolNotifications();
 
   // Instrumentation from web/ layer.
@@ -105,6 +105,7 @@
  private:
   WebDevToolsAgentImpl(WebLocalFrameImpl*,
                        WebDevToolsAgentClient*,
+                       InspectorOverlay*,
                        bool include_view_agents);
 
   // InspectorTracingAgent::Client implementation.
@@ -118,6 +119,7 @@
 
   // InspectorPageAgent::Client implementation.
   void PageLayoutInvalidated(bool resized) override;
+  void ConfigureOverlay(bool suspended, const String& message) override;
   void WaitForCreateWindow(LocalFrame*) override;
 
   // InspectorSession::Client implementation.
@@ -148,15 +150,16 @@
 
   Member<CoreProbeSink> instrumenting_agents_;
   Member<InspectorResourceContentLoader> resource_content_loader_;
+  Member<InspectorOverlay> overlay_;
   Member<InspectedFrames> inspected_frames_;
   Member<InspectorResourceContainer> resource_container_;
 
+  Member<InspectorDOMAgent> dom_agent_;
   Member<InspectorPageAgent> page_agent_;
   Member<InspectorNetworkAgent> network_agent_;
   Member<InspectorLayerTreeAgent> layer_tree_agent_;
   Member<InspectorTracingAgent> tracing_agent_;
   Member<InspectorTraceEvents> trace_events_agent_;
-  Member<InspectorOverlayAgent> overlay_agent_;
 
   Member<InspectorSession> session_;
   bool include_view_agents_;
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index d902bc9..fe1b404c 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -67,7 +67,7 @@
 #include "web/CompositorMutatorImpl.h"
 #include "web/CompositorWorkerProxyClientImpl.h"
 #include "web/ContextMenuAllowedScope.h"
-#include "web/InspectorOverlayAgent.h"
+#include "web/InspectorOverlay.h"
 #include "web/PageOverlay.h"
 #include "web/WebDevToolsAgentImpl.h"
 #include "web/WebInputEventConversion.h"
@@ -250,7 +250,7 @@
   if (!local_root_)
     return;
 
-  if (InspectorOverlayAgent* overlay = GetInspectorOverlay()) {
+  if (InspectorOverlay* overlay = GetInspectorOverlay()) {
     overlay->UpdateAllLifecyclePhases();
     // TODO(chrishtr): integrate paint into the overlay's lifecycle.
     if (overlay->GetPageOverlay() &&
@@ -362,7 +362,7 @@
   if (!GetPage())
     return WebInputEventResult::kNotHandled;
 
-  if (InspectorOverlayAgent* overlay = GetInspectorOverlay()) {
+  if (InspectorOverlay* overlay = GetInspectorOverlay()) {
     if (overlay->HandleInputEvent(input_event))
       return WebInputEventResult::kHandledSuppressed;
   }
@@ -1154,11 +1154,11 @@
   return result;
 }
 
-InspectorOverlayAgent* WebFrameWidgetImpl::GetInspectorOverlay() {
+InspectorOverlay* WebFrameWidgetImpl::GetInspectorOverlay() {
   if (!local_root_)
     return nullptr;
   if (WebDevToolsAgentImpl* devtools = local_root_->DevToolsAgentImpl())
-    return devtools->OverlayAgent();
+    return devtools->Overlay();
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
index 3bd30608..ac28f742 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -51,7 +51,7 @@
 class CompositorAnimationHost;
 class Frame;
 class Element;
-class InspectorOverlayAgent;
+class InspectorOverlay;
 class LocalFrame;
 class PaintLayerCompositor;
 class UserGestureToken;
@@ -184,7 +184,7 @@
   WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
   WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
 
-  InspectorOverlayAgent* GetInspectorOverlay();
+  InspectorOverlay* GetInspectorOverlay();
 
   // This method returns the focused frame belonging to this WebWidget, that
   // is, a focused frame with the same local root as the one corresponding
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index 2195c5c..a2d5180 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1115,16 +1115,6 @@
   GetFrame()->GetSpellChecker().RemoveSpellingMarkers();
 }
 
-void WebLocalFrameImpl::SpellingMarkerOffsetsForTest(
-    WebVector<unsigned>* offsets) {
-  Vector<unsigned> result;
-  const DocumentMarkerVector& document_markers =
-      GetFrame()->GetDocument()->Markers().Markers();
-  for (size_t i = 0; i < document_markers.size(); ++i)
-    result.push_back(document_markers[i]->StartOffset());
-  offsets->Assign(result);
-}
-
 void WebLocalFrameImpl::RemoveSpellingMarkersUnderWords(
     const WebVector<WebString>& words) {
   Vector<String> converted_words;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
index f92b9fc7..cf1f229 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -185,7 +185,6 @@
   bool IsSpellCheckingEnabled() const override;
   void ReplaceMisspelledRange(const WebString&) override;
   void RemoveSpellingMarkers() override;
-  void SpellingMarkerOffsetsForTest(WebVector<unsigned>* offsets) override;
   void RemoveSpellingMarkersUnderWords(
       const WebVector<WebString>& words) override;
   void SetContentSettingsClient(WebContentSettingsClient*) override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 52d580f..1b96494 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -160,7 +160,7 @@
 #include "web/DedicatedWorkerMessagingProxyProviderImpl.h"
 #include "web/DevToolsEmulator.h"
 #include "web/FullscreenController.h"
-#include "web/InspectorOverlayAgent.h"
+#include "web/InspectorOverlay.h"
 #include "web/LinkHighlightImpl.h"
 #include "web/PageOverlay.h"
 #include "web/PrerendererClientImpl.h"
@@ -433,9 +433,9 @@
   return main_frame ? main_frame->DevToolsAgentImpl() : nullptr;
 }
 
-InspectorOverlayAgent* WebViewImpl::GetInspectorOverlay() {
+InspectorOverlay* WebViewImpl::GetInspectorOverlay() {
   if (WebDevToolsAgentImpl* devtools = MainFrameDevToolsAgentImpl())
-    return devtools->OverlayAgent();
+    return devtools->Overlay();
   return nullptr;
 }
 
@@ -2032,7 +2032,7 @@
   PageWidgetDelegate::UpdateAllLifecyclePhases(*page_,
                                                *MainFrameImpl()->GetFrame());
 
-  if (InspectorOverlayAgent* overlay = GetInspectorOverlay()) {
+  if (InspectorOverlay* overlay = GetInspectorOverlay()) {
     overlay->UpdateAllLifecyclePhases();
     // TODO(chrishtr): integrate paint into the overlay's lifecycle.
     if (overlay->GetPageOverlay() &&
@@ -2175,7 +2175,7 @@
   if (dev_tools_emulator_->HandleInputEvent(input_event))
     return WebInputEventResult::kHandledSuppressed;
 
-  if (InspectorOverlayAgent* overlay = GetInspectorOverlay()) {
+  if (InspectorOverlay* overlay = GetInspectorOverlay()) {
     if (overlay->HandleInputEvent(input_event))
       return WebInputEventResult::kHandledSuppressed;
   }
@@ -4138,7 +4138,7 @@
 void WebViewImpl::UpdatePageOverlays() {
   if (page_color_overlay_)
     page_color_overlay_->Update();
-  if (InspectorOverlayAgent* overlay = GetInspectorOverlay()) {
+  if (InspectorOverlay* overlay = GetInspectorOverlay()) {
     PageOverlay* inspector_page_overlay = overlay->GetPageOverlay();
     if (inspector_page_overlay)
       inspector_page_overlay->Update();
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index b2795a92..4b2a880 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -76,7 +76,7 @@
 class DevToolsEmulator;
 class Frame;
 class FullscreenController;
-class InspectorOverlayAgent;
+class InspectorOverlay;
 class LinkHighlightImpl;
 class PageOverlay;
 class PageScaleConstraintsSet;
@@ -500,7 +500,7 @@
   WebInputMethodControllerImpl* GetActiveWebInputMethodController() const;
 
  private:
-  InspectorOverlayAgent* GetInspectorOverlay();
+  InspectorOverlay* GetInspectorOverlay();
 
   void SetPageScaleFactorAndLocation(float, const FloatPoint&);
   void PropagateZoomFactorToLocalFrameRoots(Frame*, float);
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index f1ac2847..cb87e9a3 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -6558,6 +6558,15 @@
                     .size());
 }
 
+static void GetSpellingMarkerOffsets(WebVector<unsigned>* offsets,
+                                     const Document& document) {
+  Vector<unsigned> result;
+  const DocumentMarkerVector& document_markers = document.Markers().Markers();
+  for (size_t i = 0; i < document_markers.size(); ++i)
+    result.push_back(document_markers[i]->StartOffset());
+  offsets->Assign(result);
+}
+
 TEST_P(ParameterizedWebFrameTest, RemoveSpellingMarkersUnderWords) {
   RegisterMockedHttpURLLoad("spell.html");
   FrameTestHelpers::WebViewHelper web_view_helper;
@@ -6585,7 +6594,7 @@
         .ForceInvocationForTesting();
 
   WebVector<unsigned> offsets1;
-  web_frame->SpellingMarkerOffsetsForTest(&offsets1);
+  GetSpellingMarkerOffsets(&offsets1, *frame->GetDocument());
   EXPECT_EQ(1U, offsets1.size());
 
   Vector<String> words;
@@ -6593,7 +6602,7 @@
   frame->RemoveSpellingMarkersUnderWords(words);
 
   WebVector<unsigned> offsets2;
-  web_frame->SpellingMarkerOffsetsForTest(&offsets2);
+  GetSpellingMarkerOffsets(&offsets2, *frame->GetDocument());
   EXPECT_EQ(0U, offsets2.size());
 }
 
@@ -6670,7 +6679,7 @@
   textcheck.Kick();
 
   WebVector<unsigned> offsets;
-  frame->SpellingMarkerOffsetsForTest(&offsets);
+  GetSpellingMarkerOffsets(&offsets, *frame->GetFrame()->GetDocument());
   EXPECT_EQ(0U, offsets.size());
 }
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results.py
index cbfcae5..b806719 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results.py
@@ -28,6 +28,7 @@
 objects work together is to look at the unit tests.
 """
 
+import collections
 import json
 import logging
 import pprint
@@ -65,7 +66,7 @@
         return isinstance(obj, self.types)
 
 
-class NameMatch(Match):
+class NameRegexMatch(Match):
     """Match based on regex being found in name.
 
     Use start line (^) and end of line ($) anchors if you want to match on
@@ -94,22 +95,23 @@
 class MergeFailure(Exception):
     """Base exception for merge failing."""
 
-    def __init__(self, msg, name, obj_a, obj_b):
+    def __init__(self, msg, name, objs):
         emsg = (
             "Failure merging {name}: "
-            " {msg}\nTrying to merge {a} and {b}."
+            " {msg}\nTrying to merge {objs}."
         ).format(
             name=name,
             msg=msg,
-            a=obj_a,
-            b=obj_b,
+            objs=objs,
         )
         Exception.__init__(self, emsg)
 
     @classmethod
-    def assert_type_eq(cls, name, obj_a, obj_b):
-        if type(obj_a) != type(obj_b):
-            raise cls("Types don't match", name, obj_a, obj_b)
+    def assert_type_eq(cls, name, objs):
+        obj_0 = objs[0]
+        for obj_n in objs[1:]:
+            if type(obj_0) != type(obj_n):
+                raise cls("Types don't match", name, (obj_0, obj_n))
 
 
 class Merger(object):
@@ -131,7 +133,7 @@
 
 
 class JSONMerger(Merger):
-    """Merge two JSON-like objects.
+    """Merge JSON-like objects.
 
     For adding helpers;
 
@@ -140,7 +142,7 @@
         When the function returns true, the merge_func will be called.
 
         merge_func is a function of the form
-            def f(obj_a, obj_b, name=None) -> obj_merged
+            def f(list_of_objs, name=None) -> obj_merged
         Merge functions should *never* modify the input arguments.
     """
 
@@ -152,46 +154,60 @@
         self.add_helper(
             TypeMatch(types.DictType), self.merge_dictlike)
 
-    def fallback_matcher(self, obj_a, obj_b, name=None):
+    def fallback_matcher(self, objs, name=None):
         raise MergeFailure(
-            "No merge helper found!", name, obj_a, obj_b)
+            "No merge helper found!", name, objs)
 
-    def merge_equal(self, obj_a, obj_b, name=None):
-        """Merge two equal objects together."""
-        if obj_a != obj_b:
-            raise MergeFailure(
-                "Unable to merge!", name, obj_a, obj_b)
-        return obj_a
+    def merge_equal(self, objs, name=None):
+        """Merge equal objects together."""
+        obj_0 = objs[0]
+        for obj_n in objs[1:]:
+            if obj_0 != obj_n:
+                raise MergeFailure(
+                    "Unable to merge!", name, (obj_0, obj_n))
+        return obj_0
 
-    def merge_listlike(self, list_a, list_b, name=None):  # pylint: disable=unused-argument
-        """Merge two things which are "list like" (tuples, lists, sets)."""
-        assert type(list_a) == type(list_b), (
-            "Types of %r and %r don't match, refusing to merge." % (
-                list_a, list_b))
-        output = list(list_a)
-        output.extend(list_b)
-        return list_a.__class__(output)
+    def merge_listlike(self, lists, name=None):  # pylint: disable=unused-argument
+        """Merge things which are "list like" (tuples, lists, sets)."""
+        MergeFailure.assert_type_eq(name, lists)
+        output = list(lists[0])
+        for list_n in lists[1:]:
+            output.extend(list_n)
+        return lists[0].__class__(output)
 
-    def merge_dictlike(self, dict_a, dict_b, name=None):
-        """Merge two things which are dictionaries."""
-        assert type(dict_a) == type(dict_b), (
-            "Types of %r and %r don't match, refusing to merge." % (
-                dict_a, dict_b))
-        dict_out = dict_a.__class__({})
-        for key in dict_a.keys() + dict_b.keys():
-            if key in dict_a and key in dict_b:
-                dict_out[key] = self.merge(
-                    dict_a[key], dict_b[key],
-                    name=join_name(name, key))
-            elif key in dict_a:
-                dict_out[key] = dict_a[key]
-            elif key in dict_b:
-                dict_out[key] = dict_b[key]
-            else:
-                assert False
+    def merge_dictlike(self, dicts, name=None, order_cls=collections.OrderedDict):
+        """Merge things which are dictionaries.
+
+        Args:
+            dicts (list of dict): Dictionary like objects to merge (should all
+                be the same type).
+            name (str): Name of the objects being merged (used for error
+                messages).
+            order_cls: Dict like object class used to produce key ordering.
+                Defaults to collections.OrderedDict which means all keys in
+                dicts[0] come before all keys in dicts[1], etc.
+
+        Returns:
+            dict: Merged dictionary object of same type as the objects in
+            dicts.
+        """
+        MergeFailure.assert_type_eq(name, dicts)
+
+        dict_mid = order_cls()
+        for dobj in dicts:
+            for key in dobj:
+                dict_mid.setdefault(key, []).append(dobj[key])
+
+        dict_out = dicts[0].__class__({})
+        for k, v in dict_mid.iteritems():
+            assert v
+            if len(v) == 1:
+                dict_out[k] = v[0]
+            elif len(v) > 1:
+                dict_out[k] = self.merge(v, name=join_name(name, k))
         return dict_out
 
-    def merge(self, obj_a, obj_b, name=""):
+    def merge(self, objs, name=""):
         """Generic merge function.
 
         name is a string representing the current key value separated by
@@ -201,30 +217,27 @@
 
         Then the name of the value 3 is 'file.json:key1:key2'
         """
-        if obj_a is None and obj_b is None:
-            return None
-        elif obj_b is None:
-            return obj_a
-        elif obj_a is None:
-            return obj_b
+        objs = [o for o in objs if o is not None]
 
-        MergeFailure.assert_type_eq(name, obj_a, obj_b)
+        if not objs:
+            return None
+
+        MergeFailure.assert_type_eq(name, objs)
 
         # Try the merge helpers.
         for match_func, merge_func in reversed(self.helpers):
-            if match_func(obj_a, name):
-                return merge_func(obj_a, obj_b, name=name)
-            if match_func(obj_b, name):
-                return merge_func(obj_a, obj_b, name=name)
+            for obj in objs:
+                if match_func(obj, name):
+                    return merge_func(objs, name=name)
 
-        return self.fallback_matcher(obj_a, obj_b, name=name)
+        return self.fallback_matcher(objs, name=name)
 
 
 # Classes for recursively merging a directory together.
 # ------------------------------------------------------------------------
 
 
-class FilenameMatch(object):
+class FilenameRegexMatch(object):
     """Match based on name matching a regex."""
 
     def __init__(self, regex):
@@ -234,7 +247,7 @@
         return self.regex.search(filename) is not None
 
     def __str__(self):
-        return "FilenameMatch(%r)" % self.regex.pattern
+        return "FilenameRegexMatch(%r)" % self.regex.pattern
 
     __repr__ = __str__
 
@@ -275,7 +288,7 @@
                 '\n'.join(
                     ['File contents don\'t match:'] + nonmatching),
                 out_filename,
-                to_merge[0], to_merge[1:])
+                to_merge)
 
         self.filesystem.write_binary_file(out_filename, data)
 
@@ -322,37 +335,39 @@
 
     def __call__(self, out_filename, to_merge):
         try:
-            before_a, output_data, after_a = self.load_jsonp(
+            before_0, new_json_data_0, after_0 = self.load_jsonp(
                 self.filesystem.open_binary_file_for_reading(to_merge[0]))
         except ValueError as e:
-            raise MergeFailure(e.message, to_merge[0], None, None)
+            raise MergeFailure(e.message, to_merge[0], None)
 
-        for filename in to_merge[1:]:
+        input_data = [new_json_data_0]
+        for filename_n in to_merge[1:]:
             try:
-                before_b, new_json_data, after_b = self.load_jsonp(
-                    self.filesystem.open_binary_file_for_reading(filename))
+                before_n, new_json_data_n, after_n = self.load_jsonp(
+                    self.filesystem.open_binary_file_for_reading(filename_n))
             except ValueError as e:
-                raise MergeFailure(e.message, filename, None, None)
+                raise MergeFailure(e.message, filename_n, None)
 
-            if before_a != before_b:
+            if before_0 != before_n:
                 raise MergeFailure(
-                    "jsonp starting data from %s doesn't match." % filename,
+                    "jsonp starting data from %s doesn't match." % filename_n,
                     out_filename,
-                    before_a, before_b)
+                    [before_0, before_n])
 
-            if after_a != after_b:
+            if after_0 != after_n:
                 raise MergeFailure(
-                    "jsonp ending data from %s doesn't match." % filename,
+                    "jsonp ending data from %s doesn't match." % filename_n,
                     out_filename,
-                    after_a, after_b)
+                    [after_0, after_n])
 
-            output_data = self._json_data_merger.merge(output_data, new_json_data, filename)
+            input_data.append(new_json_data_n)
 
+        output_data = self._json_data_merger.merge(input_data, name=out_filename)
         output_data.update(self._json_data_value_overrides)
 
         self.dump_jsonp(
             self.filesystem.open_binary_file_for_writing(out_filename),
-            before_a, output_data, after_a)
+            before_0, output_data, after_0)
 
     @staticmethod
     def load_jsonp(fd):
@@ -465,7 +480,7 @@
             out_path = self.filesystem.join(output_dir, partial_file_path)
             if self.filesystem.exists(out_path):
                 raise MergeFailure(
-                    'File %s already exist in output.', out_path, None, None)
+                    'File %s already exist in output.', out_path, None)
 
             dirname = self.filesystem.dirname(out_path)
             if not self.filesystem.exists(dirname):
@@ -519,7 +534,7 @@
         ]
         for match_name in matching:
             self.add_helper(
-                NameMatch(match_name),
+                NameRegexMatch(match_name),
                 self.merge_equal)
 
         # These keys are accumulated sums we want to add together.
@@ -535,31 +550,31 @@
         ]
         for match_name in addable:
             self.add_helper(
-                NameMatch(match_name),
-                lambda a, b, name=None: a + b)
+                NameRegexMatch(match_name),
+                lambda o, name=None: sum(o))
 
         # If any shard is interrupted, mark the whole thing as interrupted.
         self.add_helper(
-            NameMatch(':interrupted$'),
-            lambda a, b, name=None: a or b)
+            NameRegexMatch(':interrupted$'),
+            lambda o, name=None: bool(sum(o)))
 
         # Layout test directory value is randomly created on each shard, so
         # clear it.
         self.add_helper(
-            NameMatch(':layout_tests_dir$'),
-            lambda a, b, name=None: None)
+            NameRegexMatch(':layout_tests_dir$'),
+            lambda o, name=None: None)
 
         # seconds_since_epoch is the start time, so we just take the earliest.
         self.add_helper(
-            NameMatch(':seconds_since_epoch$'),
-            lambda a, b, name=None: min(a, b))
+            NameRegexMatch(':seconds_since_epoch$'),
+            lambda o, name=None: min(*o))
 
-    def fallback_matcher(self, obj_a, obj_b, name=None):
+    def fallback_matcher(self, objs, name=None):
         if self.allow_unknown_if_matching:
-            result = self.merge_equal(obj_a, obj_b, name)
+            result = self.merge_equal(objs, name)
             _log.warning('Unknown value %s, accepting anyway as it matches.', name)
             return result
-        return JSONMerger.fallback_matcher(self, obj_a, obj_b, name)
+        return JSONMerger.fallback_matcher(self, objs, name)
 
 
 class LayoutTestDirMerger(DirMerger):
@@ -574,20 +589,20 @@
         basic_json_data_merger = JSONMerger()
         basic_json_data_merger.fallback_matcher = basic_json_data_merger.merge_equal
         self.add_helper(
-            FilenameMatch('\\.json'),
+            FilenameRegexMatch(r'\.json$'),
             MergeFilesJSONP(self.filesystem, basic_json_data_merger))
 
         # access_log and error_log are httpd log files which are sortable.
         self.add_helper(
-            FilenameMatch('access_log\\.txt'),
+            FilenameRegexMatch(r'access_log\.txt$'),
             MergeFilesLinesSorted(self.filesystem))
         self.add_helper(
-            FilenameMatch('error_log\\.txt'),
+            FilenameRegexMatch(r'error_log\.txt$'),
             MergeFilesLinesSorted(self.filesystem))
 
         # pywebsocket files aren't particularly useful, so just save them.
         self.add_helper(
-            FilenameMatch('pywebsocket\\.ws\\.log-.*-err.txt'),
+            FilenameRegexMatch(r'pywebsocket\.ws\.log-.*-err\.txt$'),
             MergeFilesKeepFiles(self.filesystem))
 
         # These JSON files have "result style" JSON in them.
@@ -598,11 +613,11 @@
             json_data_value_overrides=results_json_value_overrides or {})
 
         self.add_helper(
-            FilenameMatch('failing_results.json'),
+            FilenameRegexMatch(r'failing_results\.json$'),
             results_json_file_merger)
         self.add_helper(
-            FilenameMatch('full_results.json'),
+            FilenameRegexMatch(r'full_results\.json$'),
             results_json_file_merger)
         self.add_helper(
-            FilenameMatch('output.json'),
+            FilenameRegexMatch(r'output\.json$'),
             results_json_file_merger)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results_unittest.py
index 71d814a..d6a0a03 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/merge_results_unittest.py
@@ -44,16 +44,16 @@
 
         for expected, (inputa, inputb) in tests:
             self.assertListEqual(
-                expected, m.merge_listlike(inputa, inputb))
+                expected, m.merge_listlike([inputa, inputb]))
             self.assertListEqual(
-                expected, m.merge(inputa, inputb))
+                expected, m.merge([inputa, inputb]))
             self.assertSequenceEqual(
                 expected,
-                m.merge_listlike(tuple(inputa), tuple(inputb)),
+                m.merge_listlike([tuple(inputa), tuple(inputb)]),
                 types.TupleType)
             self.assertSequenceEqual(
                 expected,
-                m.merge(tuple(inputa), tuple(inputb)),
+                m.merge([tuple(inputa), tuple(inputb)]),
                 types.TupleType)
 
     def test_merge_simple_dict(self):
@@ -75,10 +75,10 @@
         ]
 
         for expected, (inputa, inputb) in tests:
-            self.assertDictEqual(expected, m.merge_dictlike(inputa, inputb))
+            self.assertDictEqual(expected, m.merge_dictlike([inputa, inputb]))
 
         self.assertRaises(
-            merge_results.MergeFailure, m.merge_dictlike, {'a': 1}, {'a': 2})
+            merge_results.MergeFailure, m.merge_dictlike, [{'a': 1}, {'a': 2}])
 
     def test_merge_compound_dict(self):
         m = merge_results.JSONMerger()
@@ -91,7 +91,7 @@
             ({'a': {'b': 1, 'c': 2}}, ({'a': {'b': 1}}, {'a': {'c': 2}})),
         ]
         for expected, (inputa, inputb) in tests:
-            self.assertDictEqual(expected, m.merge_dictlike(inputa, inputb))
+            self.assertDictEqual(expected, m.merge_dictlike([inputa, inputb]))
 
     def test_merge(self):
         m = merge_results.JSONMerger()
@@ -143,10 +143,10 @@
         ]
 
         for expected, (inputa, inputb) in tests:
-            self.assertEqual(expected, m.merge(inputa, inputb))
+            self.assertEqual(expected, m.merge([inputa, inputb]))
 
         self.assertRaises(
-            merge_results.MergeFailure, m.merge, {'a': 1}, {'a': 2})
+            merge_results.MergeFailure, m.merge, [{'a': 1}, {'a': 2}])
 
         # Ordered values
         a = OrderedDict({'a': 1})
@@ -160,49 +160,49 @@
         b_before_a['b'] = 2
         b_before_a['a'] = 1
 
-        r1 = m.merge(a, b)
+        r1 = m.merge([a, b])
         self.assertSequenceEqual(a_before_b.items(), r1.items())
         self.assertIsInstance(r1, OrderedDict)
 
-        r2 = m.merge(b, a)
+        r2 = m.merge([b, a])
         self.assertSequenceEqual(b_before_a.items(), r2.items())
         self.assertIsInstance(r2, OrderedDict)
 
     def test_custom_match_on_name(self):
         m = merge_results.JSONMerger()
         m.add_helper(
-            merge_results.NameMatch('a'),
-            lambda a, b, name=None: a + b)
+            merge_results.NameRegexMatch('a'),
+            lambda o, name=None: sum(o))
 
-        self.assertDictEqual({'a': 3}, m.merge({'a': 1}, {'a': 2}))
+        self.assertDictEqual({'a': 3}, m.merge([{'a': 1}, {'a': 2}]))
         self.assertRaises(
-            merge_results.MergeFailure, m.merge, {'b': 1}, {'b': 2})
+            merge_results.MergeFailure, m.merge, [{'b': 1}, {'b': 2}])
 
         # Test that helpers that are added later have precedence.
         m.add_helper(
-            merge_results.NameMatch('b'),
-            lambda a, b, name=None: a + b)
+            merge_results.NameRegexMatch('b'),
+            lambda o, name=None: sum(o))
         m.add_helper(
-            merge_results.NameMatch('b'),
-            lambda a, b, name=None: a - b)
-        self.assertDictEqual({'b': -1}, m.merge({'b': 1}, {'b': 2}))
+            merge_results.NameRegexMatch('b'),
+            lambda o, name=None: o[0] - o[1])
+        self.assertDictEqual({'b': -1}, m.merge([{'b': 1}, {'b': 2}]))
 
     def test_custom_match_on_obj_type(self):
         m = merge_results.JSONMerger()
         m.add_helper(
             merge_results.TypeMatch(int),
-            lambda a, b, name=None: a + b)
-        self.assertDictEqual({'a': 3}, m.merge({'a': 1}, {'a': 2}))
-        self.assertDictEqual({'b': 3}, m.merge({'b': 1}, {'b': 2}))
+            lambda o, name=None: sum(o))
+        self.assertDictEqual({'a': 3}, m.merge([{'a': 1}, {'a': 2}]))
+        self.assertDictEqual({'b': 3}, m.merge([{'b': 1}, {'b': 2}]))
 
     def test_custom_match_on_obj_value(self):
         m = merge_results.JSONMerger()
         m.add_helper(
             merge_results.ValueMatch(3),
-            lambda a, b, name=None: a + b)
-        self.assertDictEqual({'a': 6}, m.merge({'a': 3}, {'a': 3}))
-        self.assertDictEqual({'a': 5}, m.merge({'a': 2}, {'a': 3}))
-        self.assertDictEqual({'a': 7}, m.merge({'a': 3}, {'a': 4}))
+            lambda o, name=None: sum(o))
+        self.assertDictEqual({'a': 6}, m.merge([{'a': 3}, {'a': 3}]))
+        self.assertDictEqual({'a': 5}, m.merge([{'a': 2}, {'a': 3}]))
+        self.assertDictEqual({'a': 7}, m.merge([{'a': 3}, {'a': 4}]))
         self.assertRaises(
             merge_results.MergeFailure, m.merge, {'a': 1}, {'a': 2})
 
@@ -494,50 +494,51 @@
         merger = merge_results.JSONTestResultsMerger(allow_unknown_if_matching=False)
         self.assertEqual(
             {'version': 3.0},
-            merger.merge({'version': 3.0}, {'version': 3.0}))
+            merger.merge([{'version': 3.0}, {'version': 3.0}]))
 
         with self.assertRaises(merge_results.MergeFailure):
-            merger.merge({'random': 'hello'}, {'random': 'hello'})
+            merger.merge([{'random': 'hello'}, {'random': 'hello'}])
 
         merger = merge_results.JSONTestResultsMerger(allow_unknown_if_matching=True)
         self.assertEqual(
             {'random': 'hello'},
-            merger.merge({'random': 'hello'}, {'random': 'hello'}))
+            merger.merge([{'random': 'hello'}, {'random': 'hello'}]))
 
     def test_summable(self):
         merger = merge_results.JSONTestResultsMerger()
         self.assertEqual(
             {'fixable': 5},
-            merger.merge({'fixable': 2}, {'fixable': 3}))
+            merger.merge([{'fixable': 2}, {'fixable': 3}]))
         self.assertEqual(
             {'num_failures_by_type': {'A': 4, 'B': 3, 'C': 2}},
-            merger.merge(
+            merger.merge([
                 {'num_failures_by_type': {'A': 3, 'B': 1}},
-                {'num_failures_by_type': {'A': 1, 'B': 2, 'C': 2}}))
+                {'num_failures_by_type': {'A': 1, 'B': 2, 'C': 2}},
+            ]))
 
     def test_interrupted(self):
         merger = merge_results.JSONTestResultsMerger()
         self.assertEqual(
             {'interrupted': False},
-            merger.merge({'interrupted': False}, {'interrupted': False}))
+            merger.merge([{'interrupted': False}, {'interrupted': False}]))
         self.assertEqual(
             {'interrupted': True},
-            merger.merge({'interrupted': True}, {'interrupted': False}))
+            merger.merge([{'interrupted': True}, {'interrupted': False}]))
         self.assertEqual(
             {'interrupted': True},
-            merger.merge({'interrupted': False}, {'interrupted': True}))
+            merger.merge([{'interrupted': False}, {'interrupted': True}]))
 
     def test_seconds_since_epoch(self):
         merger = merge_results.JSONTestResultsMerger()
         self.assertEqual(
             {'seconds_since_epoch': 2},
-            merger.merge({'seconds_since_epoch': 3}, {'seconds_since_epoch': 2}))
+            merger.merge([{'seconds_since_epoch': 3}, {'seconds_since_epoch': 2}]))
         self.assertEqual(
             {'seconds_since_epoch': 2},
-            merger.merge({'seconds_since_epoch': 2}, {'seconds_since_epoch': 3}))
+            merger.merge([{'seconds_since_epoch': 2}, {'seconds_since_epoch': 3}]))
         self.assertEqual(
             {'seconds_since_epoch': 12},
-            merger.merge({'seconds_since_epoch': 12}, {}))
+            merger.merge([{'seconds_since_epoch': 12}, {}]))
 
 
 class LayoutTestDirMergerTests(unittest.TestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
index ba162bf8..d701aac 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
@@ -30,6 +30,8 @@
             if owners:
                 current_owners = owners
             directory = self.extract_directory(line)
+            if not owners and not directory:
+                current_owners = []
             if current_owners and directory:
                 owner_map[directory] = current_owners
         return owner_map
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
index 213e436b..bf6ee43 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor_unittest.py
@@ -26,7 +26,6 @@
             '# external/wpt/webstorage [ Pass ]',
             'external/wpt/webvtt [ Skip ]',
         ]
-
         self.assertEqual(
             self.extractor.lines_to_owner_map(lines),
             {
@@ -35,6 +34,20 @@
                 'external/wpt/webstorage': ['michaeln@chromium.org', 'jsbell@chromium.org'],
             })
 
+    def test_lines_to_owner_map_no_owners(self):
+        lines = [
+            '## Owners: someone@chromium.org',
+            '# external/wpt/something [ Pass ]',
+            '## Owners: explicitly no owners but still enabled',
+            '# external/wpt/common [ Pass ]',
+        ]
+        self.assertEqual(
+            self.extractor.lines_to_owner_map(lines),
+            {
+                'external/wpt/something': ['someone@chromium.org'],
+            })
+
+
     def test_list_owners(self):
         self.extractor.owner_map = {
             'external/wpt/foo': ['a@chromium.org', 'c@chromium.org'],
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h
index 2a45bee2..239facb 100644
--- a/third_party/WebKit/public/web/WebLocalFrame.h
+++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -388,9 +388,6 @@
   virtual void EnableSpellChecking(bool) = 0;
   virtual bool IsSpellCheckingEnabled() const = 0;
   virtual void RemoveSpellingMarkers() = 0;
-
-  // Retrieves a list of spelling markers.
-  virtual void SpellingMarkerOffsetsForTest(WebVector<unsigned>* offsets) = 0;
   virtual void RemoveSpellingMarkersUnderWords(
       const WebVector<WebString>& words) = 0;
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 8331861..2322d5c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -9199,6 +9199,13 @@
   <summary>For each cookie added to the store, record it's type(s).</summary>
 </histogram>
 
+<histogram name="CopylessPaste.CacheHit" enum="CopylessCacheHit">
+  <owner>wychen@chromium.org</owner>
+  <summary>
+    The cache hit status of metadata extraction for AppIndexing.
+  </summary>
+</histogram>
+
 <histogram name="CopylessPaste.ExtractionFailedUs" units="microseconds">
   <owner>wychen@chromium.org</owner>
   <summary>
@@ -87954,6 +87961,12 @@
   <int value="7" label="First-Party-Only, HttpOnly, Secure"/>
 </enum>
 
+<enum name="CopylessCacheHit" type="int">
+  <int value="0" label="Cache hit with entity"/>
+  <int value="1" label="Cache hit without entity"/>
+  <int value="2" label="Cache miss"/>
+</enum>
+
 <enum name="CorePageTransition" type="int">
   <summary>
     The core value of PageTransition. See ui/base/page_transition_types.h.
@@ -102945,6 +102958,7 @@
   <int value="-1478876902" label="disable-permission-action-reporting"/>
   <int value="-1473668019" label="token-binding:disabled"/>
   <int value="-1473136627" label="enable-web-payments"/>
+  <int value="-1469228683" label="QuickUnlockPinSignin:disabled"/>
   <int value="-1467332609" label="tab-management-experiment-type-anise"/>
   <int value="-1466990325" label="CrosCompUpdates:enabled"/>
   <int value="-1463410070" label="IPH_DemoMode:enabled"/>
@@ -103248,6 +103262,7 @@
   <int value="-279493876" label="WebVRExperimentalRendering:enabled"/>
   <int value="-278347667" label="default-tile-height"/>
   <int value="-277144896" label="enable-viewport-meta"/>
+  <int value="-275164173" label="QuickUnlockPinSignin:enabled"/>
   <int value="-268357961" label="enable-feature-policy"/>
   <int value="-254887599" label="google-profile-info"/>
   <int value="-250721831" label="AndroidAutofillAccessibility:disabled"/>
@@ -103728,6 +103743,7 @@
   <int value="1694854500" label="disable-save-password-bubble"/>
   <int value="1696139514" label="enable-ble-advertising-in-apps"/>
   <int value="1697189972" label="WebPaymentsSingleAppUiSkip:disabled"/>
+  <int value="1700394127" label="OverlayScrollbar:disabled"/>
   <int value="1701972870" label="NTPSnippetsIncreasedVisibility:enabled"/>
   <int value="1702821235" label="WebAssembly:enabled"/>
   <int value="1705724232" label="use-android-midi-api"/>
@@ -103788,6 +103804,7 @@
   <int value="1900529524" label="disable-touch-drag-drop"/>
   <int value="1905465678" label="ContextualSearchSingleActions:enabled"/>
   <int value="1906942630" label="enable-easy-unlock"/>
+  <int value="1913298816" label="OverlayScrollbar:enabled"/>
   <int value="1915178511" label="disable-blink-features"/>
   <int value="1927259098" label="TranslateLanguageByULP:enabled"/>
   <int value="1928407249" label="NewPhotoPicker:enabled"/>
diff --git a/ui/base/webui/web_ui_util.cc b/ui/base/webui/web_ui_util.cc
index 85670e7..8b04a37c 100644
--- a/ui/base/webui/web_ui_util.cc
+++ b/ui/base/webui/web_ui_util.cc
@@ -123,6 +123,14 @@
   localized_strings->SetString("textdirection", GetTextDirection());
 }
 
+void SetLoadTimeDataDefaults(const std::string& app_locale,
+                             ui::TemplateReplacements* replacements) {
+  (*replacements)["fontfamily"] = GetFontFamily();
+  (*replacements)["fontsize"] = GetFontSize();
+  (*replacements)["language"] = l10n_util::GetLanguage(app_locale);
+  (*replacements)["textdirection"] = GetTextDirection();
+}
+
 std::string GetWebUiCssTextDefaults(base::StringPiece css_template) {
   ui::TemplateReplacements placeholders;
   placeholders["textDirection"] = GetTextDirection();
diff --git a/ui/base/webui/web_ui_util.h b/ui/base/webui/web_ui_util.h
index dc24839..7416ea7 100644
--- a/ui/base/webui/web_ui_util.h
+++ b/ui/base/webui/web_ui_util.h
@@ -11,6 +11,7 @@
 
 #include "base/strings/string_piece.h"
 #include "base/values.h"
+#include "ui/base/template_expressions.h"
 #include "ui/base/ui_base_export.h"
 #include "ui/base/window_open_disposition.h"
 
@@ -49,6 +50,9 @@
 UI_BASE_EXPORT void SetLoadTimeDataDefaults(
     const std::string& app_locale,
     base::DictionaryValue* localized_strings);
+UI_BASE_EXPORT void SetLoadTimeDataDefaults(
+    const std::string& app_locale,
+    ui::TemplateReplacements* replacements);
 
 // Get a CSS declaration for common text styles using provided template.
 UI_BASE_EXPORT std::string GetWebUiCssTextDefaults(
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index 794f74c..08a0c78b 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -44,17 +44,9 @@
   canceled_ = true;
 }
 
-GLContext::GLContext(GLShareGroup* share_group)
-    : static_bindings_initialized_(false),
-      dynamic_bindings_initialized_(false),
-      share_group_(share_group),
-      current_virtual_context_(nullptr),
-      state_dirtied_externally_(false),
-      swap_interval_(1),
-      force_swap_interval_zero_(false) {
+GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
   if (!share_group_.get())
     share_group_ = new gl::GLShareGroup();
-
   share_group_->AddContext(this);
 }
 
@@ -223,11 +215,15 @@
 }
 
 void GLContext::SetSwapInterval(int interval) {
+  if (swap_interval_ == interval)
+    return;
   swap_interval_ = interval;
   OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
 }
 
 void GLContext::ForceSwapIntervalZero(bool force) {
+  if (force_swap_interval_zero_ == force)
+    return;
   force_swap_interval_zero_ = force;
   OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_);
 }
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index 12ac9c37..fc1192af 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -197,8 +197,8 @@
 
   std::unique_ptr<GLVersionInfo> GenerateGLVersionInfo();
 
-  bool static_bindings_initialized_;
-  bool dynamic_bindings_initialized_;
+  bool static_bindings_initialized_ = false;
+  bool dynamic_bindings_initialized_ = false;
   std::unique_ptr<DriverGL> driver_gl_;
   std::unique_ptr<GLApi> gl_api_;
   std::unique_ptr<TraceGLApi> trace_gl_api_;
@@ -209,13 +209,14 @@
   RealGLApi* real_gl_api_ = nullptr;
 
   scoped_refptr<GLShareGroup> share_group_;
-  GLContext* current_virtual_context_;
-  bool state_dirtied_externally_;
+  GLContext* current_virtual_context_ = nullptr;
+  bool state_dirtied_externally_ = false;
   std::unique_ptr<GLStateRestorer> state_restorer_;
   std::unique_ptr<GLVersionInfo> version_info_;
 
-  int swap_interval_;
-  bool force_swap_interval_zero_;
+  // Start with an invalid value so that the first SetSwapInterval isn't a nop.
+  int swap_interval_ = -1;
+  bool force_swap_interval_zero_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(GLContext);
 };
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
index 4642b70..d9c15e7d 100644
--- a/ui/gl/gl_context_egl.cc
+++ b/ui/gl/gl_context_egl.cc
@@ -51,9 +51,7 @@
       context_(nullptr),
       display_(nullptr),
       config_(nullptr),
-      unbind_fbo_on_makecurrent_(false),
-      swap_interval_(1) {
-}
+      unbind_fbo_on_makecurrent_(false) {}
 
 bool GLContextEGL::Initialize(GLSurface* compatible_surface,
                               const GLContextAttribs& attribs) {
@@ -211,8 +209,6 @@
     return false;
   }
 
-  surface->OnSetSwapInterval(swap_interval_);
-
   release_current.Cancel();
   return true;
 }
@@ -271,9 +267,6 @@
   if (!eglSwapInterval(display_, interval)) {
     LOG(ERROR) << "eglSwapInterval failed with error "
                << GetLastEGLErrorString();
-  } else {
-    swap_interval_ = interval;
-    GLSurface::GetCurrent()->OnSetSwapInterval(interval);
   }
 }
 
diff --git a/ui/gl/gl_context_egl.h b/ui/gl/gl_context_egl.h
index f14c1c4e..6a436dc 100644
--- a/ui/gl/gl_context_egl.h
+++ b/ui/gl/gl_context_egl.h
@@ -47,7 +47,6 @@
   EGLDisplay display_;
   EGLConfig config_;
   bool unbind_fbo_on_makecurrent_;
-  int swap_interval_;
 
   DISALLOW_COPY_AND_ASSIGN(GLContextEGL);
 };
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc
index 145162d..a4493a2 100644
--- a/ui/gl/gl_context_glx.cc
+++ b/ui/gl/gl_context_glx.cc
@@ -294,20 +294,13 @@
 
 void GLContextGLX::OnSetSwapInterval(int interval) {
   DCHECK(IsCurrent(nullptr));
-  if (HasExtension("GLX_EXT_swap_control") &&
-      g_driver_glx.fn.glXSwapIntervalEXTFn) {
-    glXSwapIntervalEXT(
-        display_,
-        glXGetCurrentDrawable(),
-        interval);
-  } else if (HasExtension("GLX_MESA_swap_control") &&
-             g_driver_glx.fn.glXSwapIntervalMESAFn) {
+  if (GLSurfaceGLX::IsEXTSwapControlSupported()) {
+    glXSwapIntervalEXT(display_, glXGetCurrentDrawable(), interval);
+  } else if (GLSurfaceGLX::IsMESASwapControlSupported()) {
     glXSwapIntervalMESA(interval);
-  } else {
-    if(interval == 0)
-      LOG(WARNING) <<
-          "Could not disable vsync: driver does not "
-          "support GLX_EXT_swap_control";
+  } else if (interval == 0) {
+    LOG(WARNING)
+        << "Could not disable vsync: driver does not support swap control";
   }
 }
 
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index edb2346..f16d498 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -216,9 +216,6 @@
   return extensions.find(delimited_name) != std::string::npos;
 }
 
-void GLSurface::OnSetSwapInterval(int interval) {
-}
-
 GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {}
 
 bool GLSurfaceAdapter::Initialize(GLSurfaceFormat format) {
@@ -392,10 +389,6 @@
   return surface_->GetDrawOffset();
 }
 
-void GLSurfaceAdapter::OnSetSwapInterval(int interval) {
-  surface_->OnSetSwapInterval(interval);
-}
-
 GLSurfaceAdapter::~GLSurfaceAdapter() {}
 
 scoped_refptr<GLSurface> InitializeGLSurfaceWithFormat(
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index 4287ad2..d70379a 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -222,9 +222,6 @@
 
   static GLSurface* GetCurrent();
 
-  // Called when the swap interval for the associated context changes.
-  virtual void OnSetSwapInterval(int interval);
-
  protected:
   virtual ~GLSurface();
 
@@ -295,7 +292,6 @@
   bool SupportsDCLayers() const override;
   bool SetDrawRectangle(const gfx::Rect& rect) override;
   gfx::Vector2d GetDrawOffset() const override;
-  void OnSetSwapInterval(int interval) override;
 
   GLSurface* surface() const { return surface_.get(); }
 
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 5a6d887..fe37725 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -115,14 +115,6 @@
 
 bool GLSurfaceEGL::initialized_ = false;
 
-#if defined(OS_WIN)
-unsigned int NativeViewGLSurfaceEGL::current_swap_generation_ = 0;
-unsigned int NativeViewGLSurfaceEGL::swaps_this_generation_ = 0;
-unsigned int NativeViewGLSurfaceEGL::last_multiswap_generation_ = 0;
-
-const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD = 60;
-#endif
-
 namespace {
 
 EGLDisplay g_display = EGL_NO_DISPLAY;
@@ -719,16 +711,13 @@
       supports_post_sub_buffer_(false),
       supports_swap_buffer_with_damage_(false),
       flips_vertically_(false),
-      vsync_provider_external_(std::move(vsync_provider)),
-      swap_interval_(1) {
+      vsync_provider_external_(std::move(vsync_provider)) {
 #if defined(OS_ANDROID)
   if (window)
     ANativeWindow_acquire(window);
 #endif
 
 #if defined(OS_WIN)
-  vsync_override_ = false;
-  swap_generation_ = 0;
   RECT windowRect;
   if (GetClientRect(window_, &windowRect))
     size_ = gfx::Rect(windowRect).size();
@@ -836,52 +825,11 @@
   return false;
 }
 
-void NativeViewGLSurfaceEGL::UpdateSwapInterval() {
-#if defined(OS_WIN)
-  if (!g_use_direct_composition && (swap_interval_ != 0)) {
-    // This code is a simple way of enforcing that we only vsync if one surface
-    // is swapping per frame. This provides single window cases a stable refresh
-    // while allowing multi-window cases to not slow down due to multiple syncs
-    // on a single thread. A better way to fix this problem would be to have
-    // each surface present on its own thread. This is unnecessary with
-    // DirectComposition because that doesn't block swaps, but instead blocks
-    // the first draw into a surface during the next frame.
-
-    if (current_swap_generation_ == swap_generation_) {
-      if (swaps_this_generation_ > 1)
-        last_multiswap_generation_ = current_swap_generation_;
-      swaps_this_generation_ = 0;
-      current_swap_generation_++;
-    }
-
-    swap_generation_ = current_swap_generation_;
-
-    if (swaps_this_generation_ != 0 ||
-        (current_swap_generation_ - last_multiswap_generation_ <
-            MULTISWAP_FRAME_VSYNC_THRESHOLD)) {
-      // Override vsync settings and switch it off
-      if (!vsync_override_) {
-        eglSwapInterval(GetDisplay(), 0);
-        vsync_override_ = true;
-      }
-    } else if (vsync_override_) {
-      // Only one window swapping, so let the normal vsync setting take over
-      eglSwapInterval(GetDisplay(), swap_interval_);
-      vsync_override_ = false;
-    }
-
-    swaps_this_generation_++;
-  }
-#endif
-}
-
 gfx::SwapResult NativeViewGLSurfaceEGL::SwapBuffers() {
   TRACE_EVENT2("gpu", "NativeViewGLSurfaceEGL:RealSwapBuffers",
       "width", GetSize().width(),
       "height", GetSize().height());
 
-  UpdateSwapInterval();
-
   if (!CommitAndClearPendingOverlays()) {
     DVLOG(1) << "Failed to commit pending overlay planes.";
     return gfx::SwapResult::SWAP_FAILED;
@@ -965,7 +913,6 @@
 gfx::SwapResult NativeViewGLSurfaceEGL::SwapBuffersWithDamage(
     const std::vector<int>& rects) {
   DCHECK(supports_swap_buffer_with_damage_);
-  UpdateSwapInterval();
   if (!CommitAndClearPendingOverlays()) {
     DVLOG(1) << "Failed to commit pending overlay planes.";
     return gfx::SwapResult::SWAP_FAILED;
@@ -986,7 +933,6 @@
                                                       int width,
                                                       int height) {
   DCHECK(supports_post_sub_buffer_);
-  UpdateSwapInterval();
   if (!CommitAndClearPendingOverlays()) {
     DVLOG(1) << "Failed to commit pending overlay planes.";
     return gfx::SwapResult::SWAP_FAILED;
@@ -1043,10 +989,6 @@
 #endif
 }
 
-void NativeViewGLSurfaceEGL::OnSetSwapInterval(int interval) {
-  swap_interval_ = interval;
-}
-
 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
   Destroy();
 #if defined(OS_ANDROID)
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index ad51451..78754eb 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -126,14 +126,12 @@
   gfx::Size size_;
   bool enable_fixed_size_angle_;
 
-  void OnSetSwapInterval(int interval) override;
   gfx::SwapResult SwapBuffersWithDamage(const std::vector<int>& rects);
 
  private:
   // Commit the |pending_overlays_| and clear the vector. Returns false if any
   // fail to be committed.
   bool CommitAndClearPendingOverlays();
-  void UpdateSwapInterval();
 
   EGLSurface surface_;
   bool supports_post_sub_buffer_;
@@ -143,19 +141,8 @@
   std::unique_ptr<gfx::VSyncProvider> vsync_provider_external_;
   std::unique_ptr<gfx::VSyncProvider> vsync_provider_internal_;
 
-  int swap_interval_;
-
   std::vector<GLSurfaceOverlay> pending_overlays_;
 
-#if defined(OS_WIN)
-  bool vsync_override_;
-
-  unsigned int swap_generation_;
-  static unsigned int current_swap_generation_;
-  static unsigned int swaps_this_generation_;
-  static unsigned int last_multiswap_generation_;
-#endif
-
   DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceEGL);
 };
 
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
index d5f282da..2543994 100644
--- a/ui/gl/gl_surface_glx.cc
+++ b/ui/gl/gl_surface_glx.cc
@@ -48,7 +48,8 @@
 // whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML
 // always fails even though GLX_OML_sync_control is reported as being supported.
 bool g_glx_get_msc_rate_oml_supported = false;
-
+bool g_glx_ext_swap_control_supported = false;
+bool g_glx_mesa_swap_control_supported = false;
 bool g_glx_sgi_video_sync_supported = false;
 
 // A 24-bit RGB visual and colormap to use when creating offscreen surfaces.
@@ -423,6 +424,8 @@
       HasGLXExtension("GLX_EXT_texture_from_pixmap");
   g_glx_oml_sync_control_supported = HasGLXExtension("GLX_OML_sync_control");
   g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
+  g_glx_ext_swap_control_supported = HasGLXExtension("GLX_EXT_swap_control");
+  g_glx_mesa_swap_control_supported = HasGLXExtension("GLX_MESA_swap_control");
   g_glx_sgi_video_sync_supported = HasGLXExtension("GLX_SGI_video_sync");
 
   const XVisualInfo& visual_info =
@@ -492,6 +495,16 @@
 }
 
 // static
+bool GLSurfaceGLX::IsEXTSwapControlSupported() {
+  return g_glx_ext_swap_control_supported;
+}
+
+// static
+bool GLSurfaceGLX::IsMESASwapControlSupported() {
+  return g_glx_mesa_swap_control_supported;
+}
+
+// static
 bool GLSurfaceGLX::IsOMLSyncControlSupported() {
   return g_glx_oml_sync_control_supported;
 }
@@ -593,7 +606,6 @@
 gfx::SwapResult NativeViewGLSurfaceGLX::SwapBuffers() {
   TRACE_EVENT2("gpu", "NativeViewGLSurfaceGLX:RealSwapBuffers", "width",
                GetSize().width(), "height", GetSize().height());
-
   glXSwapBuffers(g_display, GetDrawableHandle());
   return gfx::SwapResult::SWAP_ACK;
 }
diff --git a/ui/gl/gl_surface_glx.h b/ui/gl/gl_surface_glx.h
index 7ab6b0a..10a213c9 100644
--- a/ui/gl/gl_surface_glx.h
+++ b/ui/gl/gl_surface_glx.h
@@ -39,6 +39,8 @@
   static bool IsCreateContextES2ProfileSupported();
   static bool IsTextureFromPixmapSupported();
   static bool IsOMLSyncControlSupported();
+  static bool IsEXTSwapControlSupported();
+  static bool IsMESASwapControlSupported();
 
   void* GetDisplay() override;
 
@@ -76,6 +78,7 @@
   unsigned long GetCompatibilityKey() override;
   gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
   gfx::VSyncProvider* GetVSyncProvider() override;
+
   VisualID GetVisualID() const { return visual_id_; }
 
  protected:
@@ -92,7 +95,6 @@
   bool CanHandleEvent(XEvent* xevent);
 
   gfx::AcceleratedWidget window() const { return window_; }
-
  private:
   // The handle for the drawable to make current or swap.
   GLXDrawable GetDrawableHandle() const;
diff --git a/ui/native_theme/BUILD.gn b/ui/native_theme/BUILD.gn
index 174e477..5f436ac4 100644
--- a/ui/native_theme/BUILD.gn
+++ b/ui/native_theme/BUILD.gn
@@ -15,12 +15,12 @@
     "native_theme_android.h",
     "native_theme_base.cc",
     "native_theme_base.h",
+    "native_theme_features.cc",
+    "native_theme_features.h",
     "native_theme_mac.h",
     "native_theme_mac.mm",
     "native_theme_observer.cc",
     "native_theme_observer.h",
-    "native_theme_switches.cc",
-    "native_theme_switches.h",
   ]
 
   if (use_aura) {
diff --git a/ui/native_theme/native_theme_aura.cc b/ui/native_theme/native_theme_aura.cc
index d2cfc1fb..31d5186f 100644
--- a/ui/native_theme/native_theme_aura.cc
+++ b/ui/native_theme/native_theme_aura.cc
@@ -24,7 +24,7 @@
 #include "ui/gfx/path.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/native_theme/common_theme.h"
-#include "ui/native_theme/native_theme_switches.h"
+#include "ui/native_theme/native_theme_features.h"
 #include "ui/native_theme/overlay_scrollbar_constants_aura.h"
 
 namespace ui {
diff --git a/ui/native_theme/native_theme_features.cc b/ui/native_theme/native_theme_features.cc
new file mode 100644
index 0000000..25cf50a4
--- /dev/null
+++ b/ui/native_theme/native_theme_features.cc
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/native_theme/native_theme_features.h"
+
+namespace features {
+
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+constexpr base::FeatureState kOverlayScrollbarFeatureState =
+    base::FEATURE_ENABLED_BY_DEFAULT;
+#else
+constexpr base::FeatureState kOverlayScrollbarFeatureState =
+    base::FEATURE_DISABLED_BY_DEFAULT;
+#endif
+
+// Enables or disables overlay scrollbars in Blink (i.e. web content) on Aura
+// or Linux.  The status of native UI overlay scrollbars is determined in
+// PlatformStyle::CreateScrollBar. Does nothing on Mac.
+const base::Feature kOverlayScrollbar{"OverlayScrollbar",
+                                      kOverlayScrollbarFeatureState};
+
+}  // namespace features
+
+namespace ui {
+
+bool IsOverlayScrollbarEnabled() {
+  return base::FeatureList::IsEnabled(features::kOverlayScrollbar);
+}
+
+}  // namespace ui
diff --git a/ui/native_theme/native_theme_features.h b/ui/native_theme/native_theme_features.h
new file mode 100644
index 0000000..85e8985
--- /dev/null
+++ b/ui/native_theme/native_theme_features.h
@@ -0,0 +1,25 @@
+// 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.
+
+// Defines all the command-line switches used by native theme
+
+#ifndef UI_NATIVE_THEME_NATIVE_THEME_FEATURES_H_
+#define UI_NATIVE_THEME_NATIVE_THEME_FEATURES_H_
+
+#include "base/feature_list.h"
+#include "ui/native_theme/native_theme_export.h"
+
+namespace features {
+
+NATIVE_THEME_EXPORT extern const base::Feature kOverlayScrollbar;
+
+}  // namespace features
+
+namespace ui {
+
+NATIVE_THEME_EXPORT bool IsOverlayScrollbarEnabled();
+
+}  // namespace ui
+
+#endif  // UI_NATIVE_THEME_NATIVE_THEME_FEATURES_H_
diff --git a/ui/native_theme/native_theme_switches.cc b/ui/native_theme/native_theme_switches.cc
deleted file mode 100644
index 1d8f8b3..0000000
--- a/ui/native_theme/native_theme_switches.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "ui/native_theme/native_theme_switches.h"
-
-namespace switches {
-
-// Enables or disables overlay scrollbars in Blink (i.e. web content) on Aura
-// or Linux.  The status of native UI overlay scrollbars are determined in
-// PlatformStyle::CreateScrollBar. Does nothing on Mac.
-const char kEnableOverlayScrollbar[] = "enable-overlay-scrollbar";
-const char kDisableOverlayScrollbar[] = "disable-overlay-scrollbar";
-
-}  // namespace switches
-
-namespace ui {
-
-bool IsOverlayScrollbarEnabled() {
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-
-  if (command_line.HasSwitch(switches::kDisableOverlayScrollbar))
-    return false;
-
-#if defined(OS_CHROMEOS)
-  return true;
-#else
-  return command_line.HasSwitch(switches::kEnableOverlayScrollbar);
-#endif
-}
-
-}  // namespace ui
diff --git a/ui/native_theme/native_theme_switches.h b/ui/native_theme/native_theme_switches.h
deleted file mode 100644
index 026ee70..0000000
--- a/ui/native_theme/native_theme_switches.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Defines all the command-line switches used by native theme
-
-#ifndef UI_NATIVE_THEME_NATIVE_THEME_SWITCHES_H_
-#define UI_NATIVE_THEME_NATIVE_THEME_SWITCHES_H_
-
-#include "ui/native_theme/native_theme_export.h"
-
-namespace switches {
-
-NATIVE_THEME_EXPORT extern const char kDisableOverlayScrollbar[];
-NATIVE_THEME_EXPORT extern const char kEnableOverlayScrollbar[];
-
-}  // namespace switches
-
-namespace ui {
-
-NATIVE_THEME_EXPORT bool IsOverlayScrollbarEnabled();
-
-}  // namespace ui
-
-#endif  // UI_NATIVE_THEME_NATIVE_THEME_SWITCHES_H_