diff --git a/DEPS b/DEPS
index fd7f2d9..371b5b4 100644
--- a/DEPS
+++ b/DEPS
@@ -129,7 +129,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '78e6a4c1ff67cb207102dc2839fb02dc1bcaab1e',
+  'skia_revision': '7b49eeb4960b43d0eba7875201dea5fd4aedf363',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -141,15 +141,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '4bcba62aba7b4e57283a78054e5647dd6840b74a',
+  'angle_revision': '6ce1be5a5a53eb0213075dd7591a7dd4a3708614',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '0e712410582f85d3388c939b6c0da6b3e1d761f0',
+  'swiftshader_revision': 'f2564656e7affc5c5c856186277b9bfc8a100928',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '3d3dcdff38a692c7dfc0a064e37cdf44c0fa34a7',
+  'pdfium_revision': 'f79e15b85174760e78a2fb0cd9f7b251eb19e6a2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -192,7 +192,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': '93bbf937f83835ceb3d858e383a165afdeeae802',
+  'catapult_revision': 'ec795debc5c195658e95f5e750f6c0895c8171f2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -801,7 +801,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '4dd012f7e9a92807c5cae84706d9b366b5e6f231',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c75272708a801769f6b0f3c2a83b28d4a10295e8',
       'condition': 'checkout_linux',
   },
 
@@ -826,7 +826,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2d29261e94edb6870b8c2575a335545c0f4f670f',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3580425baa288b482c1fe2155c005736b7abc372',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1168,7 +1168,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'f7104562e5e40419d95f3d5a3f08e71572f6e648',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'e065d4ecc45179cfc63eeb932717138be9e5f7f8',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1367,7 +1367,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/${{platform}}',
-          'version': 'git_revision:8536f8d120c172dba4ceee64c20aa51f2efe4fc7',
+          'version': 'git_revision:1c5d71e846840d56aa37758548789d987a0515bc',
         },
       ],
       'dep_type': 'cipd',
@@ -1380,7 +1380,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b69b09d2ceaff2e57fc2cc52018573ba8fe76839',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0861b5e50a7f205395e9535013ae5f60e59ad274',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 285c0f4..627dd9ac 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2124,7 +2124,8 @@
                       'stevenjb+watch@chromium.org'],
     'chromeos_login': ['achuith+watch@chromium.org',
                        'alemate+watch@chromium.org',
-                       'jdufault+watch@chromium.org'],
+                       'jdufault+watch@chromium.org',
+                       'tbarzic+watch@chromium.org'],
     'chromeos_net': ['stevenjb+watch@chromium.org'],
     'chromeos_power': ['derat+watch@chromium.org'],
     'chromeos_timezone': ['alemate+watch@chromium.org'],
diff --git a/ash/accessibility/accessibility_focus_ring_controller.cc b/ash/accessibility/accessibility_focus_ring_controller.cc
index abc3a496..1f051fd3 100644
--- a/ash/accessibility/accessibility_focus_ring_controller.cc
+++ b/ash/accessibility/accessibility_focus_ring_controller.cc
@@ -62,38 +62,24 @@
   binding_.Bind(std::move(request));
 }
 
-void AccessibilityFocusRingController::SetFocusRingColor(
-    SkColor color,
-    const std::string& caller_id) {
-  AccessibilityFocusRingGroup* focus_ring_group =
-      GetFocusRingGroupForCallerId(caller_id, true /* Create if missing */);
-  focus_ring_group->SetColor(color, this);
-}
-
-void AccessibilityFocusRingController::ResetFocusRingColor(
-    const std::string& caller_id) {
-  AccessibilityFocusRingGroup* focus_ring_group =
-      GetFocusRingGroupForCallerId(caller_id, false /* Do not create */);
-  if (!focus_ring_group)
-    return;
-  focus_ring_group->ResetColor(this);
-}
-
 void AccessibilityFocusRingController::SetFocusRing(
-    const std::vector<gfx::Rect>& rects,
-    mojom::FocusRingBehavior focus_ring_behavior,
-    const std::string& caller_id) {
+    const std::string& focus_ring_id,
+    mojom::FocusRingPtr focus_ring) {
   AccessibilityFocusRingGroup* focus_ring_group =
-      GetFocusRingGroupForCallerId(caller_id, true /* Create if missing */);
-  if (focus_ring_group->SetFocusRectsAndBehavior(rects, focus_ring_behavior,
-                                                 this))
+      GetFocusRingGroupForId(focus_ring_id, true /* Create if missing */);
+
+  focus_ring_group->SetColor(focus_ring->color, this);
+
+  if (focus_ring_group->SetFocusRectsAndBehavior(focus_ring->rects_in_screen,
+                                                 focus_ring->behavior, this)) {
     OnLayerChange(focus_ring_group->focus_animation_info());
+  }
 }
 
 void AccessibilityFocusRingController::HideFocusRing(
-    const std::string& caller_id) {
+    const std::string& focus_ring_id) {
   AccessibilityFocusRingGroup* focus_ring_group =
-      GetFocusRingGroupForCallerId(caller_id, false /* Do not create */);
+      GetFocusRingGroupForId(focus_ring_id, false /* Do not create */);
   if (!focus_ring_group)
     return;
   focus_ring_group->ClearFocusRects(this);
@@ -114,23 +100,6 @@
   UpdateHighlightFromHighlightRects();
 }
 
-void AccessibilityFocusRingController::EnableDoubleFocusRing(
-    SkColor color,
-    const std::string& caller_id) {
-  AccessibilityFocusRingGroup* focus_ring_group =
-      GetFocusRingGroupForCallerId(caller_id, true /* Create if missing */);
-  focus_ring_group->EnableDoubleFocusRing(color, this);
-}
-
-void AccessibilityFocusRingController::DisableDoubleFocusRing(
-    const std::string& caller_id) {
-  AccessibilityFocusRingGroup* focus_ring_group =
-      GetFocusRingGroupForCallerId(caller_id, false /* Do not create */);
-  if (!focus_ring_group)
-    return;
-  focus_ring_group->DisableDoubleFocusRing(this);
-}
-
 void AccessibilityFocusRingController::UpdateHighlightFromHighlightRects() {
   if (!highlight_layer_)
     highlight_layer_ = std::make_unique<AccessibilityHighlightLayer>(this);
@@ -195,8 +164,8 @@
 
 const AccessibilityFocusRingGroup*
 AccessibilityFocusRingController::GetFocusRingGroupForTesting(
-    std::string caller_id) {
-  return GetFocusRingGroupForCallerId(caller_id, /* create if missing */ false);
+    const std::string& focus_ring_id) {
+  return GetFocusRingGroupForId(focus_ring_id, false /* create if missing */);
 }
 
 void AccessibilityFocusRingController::GetColorAndOpacityFromColor(
@@ -259,10 +228,10 @@
 }
 
 AccessibilityFocusRingGroup*
-AccessibilityFocusRingController::GetFocusRingGroupForCallerId(
-    std::string caller_id_to_focus_ring_group_,
+AccessibilityFocusRingController::GetFocusRingGroupForId(
+    const std::string& focus_ring_id,
     bool create) {
-  auto iter = focus_ring_groups_.find(caller_id_to_focus_ring_group_);
+  auto iter = focus_ring_groups_.find(focus_ring_id);
   if (iter != focus_ring_groups_.end())
     return iter->second.get();
 
@@ -270,12 +239,12 @@
     return nullptr;
 
   // Add it and then return it.
-  focus_ring_groups_[caller_id_to_focus_ring_group_] =
+  focus_ring_groups_[focus_ring_id] =
       std::make_unique<AccessibilityFocusRingGroup>();
-  if (no_fade_for_testing_) {
+  if (no_fade_for_testing_)
     SetNoFadeForTesting();
-  }
-  return focus_ring_groups_[caller_id_to_focus_ring_group_].get();
+
+  return focus_ring_groups_[focus_ring_id].get();
 }
 
 }  // namespace ash
diff --git a/ash/accessibility/accessibility_focus_ring_controller.h b/ash/accessibility/accessibility_focus_ring_controller.h
index a7464bf..973b1ca 100644
--- a/ash/accessibility/accessibility_focus_ring_controller.h
+++ b/ash/accessibility/accessibility_focus_ring_controller.h
@@ -40,18 +40,12 @@
   void BindRequest(mojom::AccessibilityFocusRingControllerRequest request);
 
   // mojom::AccessibilityFocusRingController overrides:
-  void SetFocusRingColor(SkColor color, const std::string& caller_id) override;
-  void ResetFocusRingColor(const std::string& caller_id) override;
-  void SetFocusRing(const std::vector<gfx::Rect>& rects,
-                    mojom::FocusRingBehavior focus_ring_behavior,
-                    const std::string& caller_id) override;
-  void HideFocusRing(const std::string& caller_id) override;
+  void SetFocusRing(const std::string& focus_ring_id,
+                    mojom::FocusRingPtr focus_ring) override;
+  void HideFocusRing(const std::string& focus_ring_id) override;
   void SetHighlights(const std::vector<gfx::Rect>& rects,
                      SkColor color) override;
   void HideHighlights() override;
-  void EnableDoubleFocusRing(SkColor color,
-                             const std::string& caller_id) override;
-  void DisableDoubleFocusRing(const std::string& caller_id) override;
 
   // Draw a ring around the mouse cursor. It fades out automatically.
   void SetCursorRing(const gfx::Point& location);
@@ -72,7 +66,7 @@
     return caret_layer_.get();
   }
   const AccessibilityFocusRingGroup* GetFocusRingGroupForTesting(
-      std::string caller_id);
+      const std::string& focus_ring_id);
 
  protected:
   // Breaks an SkColor into its opacity and color. If the opacity is
@@ -100,8 +94,8 @@
   // Binding for mojom::AccessibilityFocusRingController interface.
   mojo::Binding<mojom::AccessibilityFocusRingController> binding_;
 
-  AccessibilityFocusRingGroup* GetFocusRingGroupForCallerId(
-      std::string caller_id,
+  AccessibilityFocusRingGroup* GetFocusRingGroupForId(
+      const std::string& focus_ring_id,
       bool create);
   std::map<std::string, std::unique_ptr<AccessibilityFocusRingGroup>>
       focus_ring_groups_;
diff --git a/ash/accessibility/accessibility_focus_ring_controller_unittest.cc b/ash/accessibility/accessibility_focus_ring_controller_unittest.cc
index fdf1b82..9d79522 100644
--- a/ash/accessibility/accessibility_focus_ring_controller_unittest.cc
+++ b/ash/accessibility/accessibility_focus_ring_controller_unittest.cc
@@ -37,40 +37,43 @@
   TestableAccessibilityFocusRingController controller_;
 };
 
-TEST_F(AccessibilityFocusRingControllerTest, CallingSetOrResetWhenEmpty) {
-  // Ensure that calling reset does not crash the controller if there are
+TEST_F(AccessibilityFocusRingControllerTest, CallingHideWhenEmpty) {
+  // Ensure that calling hide does not crash the controller if there are
   // no focus rings yet for a given ID.
-  controller_.ResetFocusRingColor("catsRCute");
   controller_.HideFocusRing("catsRCute");
 }
 
-TEST_F(AccessibilityFocusRingControllerTest,
-       SetFocusRingOrColorUpdatesCorrectRingGroup) {
+TEST_F(AccessibilityFocusRingControllerTest, SetFocusRingCorrectRingGroup) {
   EXPECT_EQ(nullptr, controller_.GetFocusRingGroupForTesting("catsRCute"));
-  controller_.SetFocusRingColor(SkColorSetARGB(0xFF, 0x42, 0x42, 0x42),
-                                "catsRCute");
-  // A focus ring group was created, but it has no layers yet.
+  SkColor cat_color = SkColorSetARGB(0xFF, 0x42, 0x42, 0x42);
+
+  mojom::FocusRingPtr cat_focus_ring = mojom::FocusRing::New();
+  cat_focus_ring->color = cat_color;
+  cat_focus_ring->rects_in_screen.push_back(gfx::Rect(0, 0, 10, 10));
+  controller_.SetFocusRing("catsRCute", std::move(cat_focus_ring));
+
+  // A focus ring group was created.
   ASSERT_NE(nullptr, controller_.GetFocusRingGroupForTesting("catsRCute"));
-  int size = controller_.GetFocusRingGroupForTesting("catsRCute")
-                 ->focus_layers_for_testing()
-                 .size();
-  EXPECT_EQ(0, size);
+  EXPECT_EQ(1u, controller_.GetFocusRingGroupForTesting("catsRCute")
+                    ->focus_layers_for_testing()
+                    .size());
 
   EXPECT_EQ(nullptr, controller_.GetFocusRingGroupForTesting("dogsRCool"));
-  std::vector<gfx::Rect> rects;
-  rects.push_back(gfx::Rect(10, 30, 70, 150));
-  controller_.SetFocusRing(rects, mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING,
-                           "dogsRCool");
+  mojom::FocusRingPtr dog_focus_ring = mojom::FocusRing::New();
+  dog_focus_ring->rects_in_screen.push_back(gfx::Rect(10, 30, 70, 150));
+  controller_.SetFocusRing("dogsRCool", std::move(dog_focus_ring));
+
   ASSERT_NE(nullptr, controller_.GetFocusRingGroupForTesting("dogsRCool"));
-  size = controller_.GetFocusRingGroupForTesting("dogsRCool")
-             ->focus_layers_for_testing()
-             .size();
+  int size = controller_.GetFocusRingGroupForTesting("dogsRCool")
+                 ->focus_layers_for_testing()
+                 .size();
   EXPECT_EQ(1, size);
   // The first focus ring group was not updated.
-  size = controller_.GetFocusRingGroupForTesting("catsRCute")
-             ->focus_layers_for_testing()
-             .size();
-  EXPECT_EQ(0, size);
+  const std::vector<std::unique_ptr<AccessibilityFocusRingLayer>>& layers =
+      controller_.GetFocusRingGroupForTesting("catsRCute")
+          ->focus_layers_for_testing();
+  EXPECT_EQ(1u, layers.size());
+  EXPECT_EQ(cat_color, layers[0]->color_for_testing());
 }
 
 TEST_F(AccessibilityFocusRingControllerTest, CursorWorksOnMultipleDisplays) {
diff --git a/ash/accessibility/accessibility_focus_ring_layer.h b/ash/accessibility/accessibility_focus_ring_layer.h
index b1f0b9b78..5e586cf0 100644
--- a/ash/accessibility/accessibility_focus_ring_layer.h
+++ b/ash/accessibility/accessibility_focus_ring_layer.h
@@ -27,6 +27,8 @@
   void EnableDoubleFocusRing(SkColor secondary_color);
   void DisableDoubleFocusRing();
 
+  SkColor color_for_testing() { return custom_color(); }
+
  private:
   // ui::LayerDelegate overrides:
   void OnPaintLayer(const ui::PaintContext& context) override;
diff --git a/ash/accessibility/accessibility_highlight_controller.cc b/ash/accessibility/accessibility_highlight_controller.cc
index e8b1372..b64422c 100644
--- a/ash/accessibility/accessibility_highlight_controller.cc
+++ b/ash/accessibility/accessibility_highlight_controller.cc
@@ -22,13 +22,26 @@
 
 namespace {
 
+constexpr char kHighlightCallerId[] = "HighlightController";
+// The color for the keyboard focus ring. (The same orange color as ChromeVox.)
+const SkColor kFocusColor = SkColorSetRGB(247, 152, 58);
+
 // Returns the input method shared between ash and the browser for in-process
 // ash. Returns null for out-of-process ash.
 ui::InputMethod* GetSharedInputMethod() {
   return Shell::Get()->window_tree_host_manager()->input_method();
 }
 
-constexpr char kHighlightCallerId[] = "HighlightController";
+void SetFocusRing(AccessibilityFocusRingController* controller,
+                  std::vector<gfx::Rect> rects) {
+  mojom::FocusRingPtr focus_ring = mojom::FocusRing::New();
+  focus_ring->rects_in_screen = rects;
+  focus_ring->behavior = mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING;
+  focus_ring->type = mojom::FocusRingType::GLOW;
+  focus_ring->color = kFocusColor;
+
+  controller->SetFocusRing(kHighlightCallerId, std::move(focus_ring));
+}
 
 }  // namespace
 
@@ -45,9 +58,7 @@
 AccessibilityHighlightController::~AccessibilityHighlightController() {
   AccessibilityFocusRingController* controller =
       Shell::Get()->accessibility_focus_ring_controller();
-  controller->SetFocusRing(std::vector<gfx::Rect>(),
-                           mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING,
-                           kHighlightCallerId);
+  SetFocusRing(controller, std::vector<gfx::Rect>());
   controller->HideCaretRing();
   controller->HideCursorRing();
 
@@ -158,22 +169,16 @@
   // both are visible.
   if (caret_ && caret_visible_) {
     controller->SetCaretRing(caret_point_);
-    controller->SetFocusRing(std::vector<gfx::Rect>(),
-                             mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING,
-                             kHighlightCallerId);
+    SetFocusRing(controller, std::vector<gfx::Rect>());
   } else if (focus_) {
     controller->HideCaretRing();
     std::vector<gfx::Rect> rects;
     if (!focus_rect_.IsEmpty())
       rects.push_back(focus_rect_);
-    controller->SetFocusRing(rects,
-                             mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING,
-                             kHighlightCallerId);
+    SetFocusRing(controller, rects);
   } else {
     controller->HideCaretRing();
-    controller->SetFocusRing(std::vector<gfx::Rect>(),
-                             mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING,
-                             kHighlightCallerId);
+    SetFocusRing(controller, std::vector<gfx::Rect>());
   }
 }
 
diff --git a/ash/accessibility/touch_exploration_manager.cc b/ash/accessibility/touch_exploration_manager.cc
index 303b542..c3d9ba7 100644
--- a/ash/accessibility/touch_exploration_manager.cc
+++ b/ash/accessibility/touch_exploration_manager.cc
@@ -230,9 +230,7 @@
       SilenceSpokenFeedback();
       // Clear the focus highlight.
       Shell::Get()->accessibility_focus_ring_controller()->SetFocusRing(
-          std::vector<gfx::Rect>(),
-          mojom::FocusRingBehavior::PERSIST_FOCUS_RING,
-          extension_misc::kChromeVoxExtensionId);
+          extension_misc::kChromeVoxExtensionId, mojom::FocusRing::New());
     } else {
       touch_exploration_controller_->SetExcludeBounds(gfx::Rect());
     }
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index 9bf7881d..241b63f 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -665,7 +665,7 @@
             GetViewDisplayedAtSlotOnCurrentPage(drop_target_.slot);
       } else if (IsValidReorderTargetIndex(drop_target_)) {
         // Ensure reorder event has already been announced by the end of drag.
-        MaybeCreateReorderAccessibilityEvent();
+        MaybeCreateDragReorderAccessibilityEvent();
         MoveItemInModel(drag_view_, drop_target_);
         RecordAppMovingTypeMetrics(folder_delegate_ ? kReorderByDragInFolder
                                                     : kReorderByDragInTopLevel);
@@ -1505,7 +1505,7 @@
 
 void AppsGridView::OnReorderTimer() {
   reorder_placeholder_ = drop_target_;
-  MaybeCreateReorderAccessibilityEvent();
+  MaybeCreateDragReorderAccessibilityEvent();
   AnimateToIdealBounds();
   CreateGhostImageView();
 }
@@ -1609,6 +1609,7 @@
   handling_keyboard_move_ = true;
 
   MoveAppListItemViewForKeyboardMove(target_index);
+  AnnounceReorder(target_index);
 }
 
 bool AppsGridView::HandleVerticalFocusMovement(bool arrow_up) {
@@ -1734,7 +1735,7 @@
       ReparentItemForReorder(drag_view_, drop_target_);
       // Announce accessibility event before the end of drag for reparented
       // item.
-      MaybeCreateReorderAccessibilityEvent();
+      MaybeCreateDragReorderAccessibilityEvent();
     } else {
       NOTREACHED();
     }
@@ -2967,7 +2968,7 @@
   announcement_view->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
 }
 
-void AppsGridView::MaybeCreateReorderAccessibilityEvent() {
+void AppsGridView::MaybeCreateDragReorderAccessibilityEvent() {
   if (drop_target_region_ == ON_ITEM && !IsFolderItem(drag_view_->item()))
     return;
 
@@ -2987,19 +2988,23 @@
   last_folder_dropping_a11y_event_location_ = GridIndex();
   last_reorder_a11y_event_location_ = drop_target_;
 
-  const int row_number =
-      ((drop_target_.slot - (drop_target_.slot % cols_)) / cols_) + 1;
-  const int col_number = (drop_target_.slot % cols_) + 1;
+  AnnounceReorder(last_reorder_a11y_event_location_);
+}
 
-  // Set accessible name to announce drop target location by row and column.
+void AppsGridView::AnnounceReorder(const GridIndex& target_index) {
+  const int row =
+      ((target_index.slot - (target_index.slot % cols_)) / cols_) + 1;
+  const int col = (target_index.slot % cols_) + 1;
+  const int page = target_index.page + 1;
+
+  // Set the accessible name of the announcement view.
   auto* announcement_view =
       contents_view_->app_list_view()->announcement_view();
   announcement_view->GetViewAccessibility().OverrideName(
       l10n_util::GetStringFUTF16(
           IDS_APP_LIST_APP_DRAG_LOCATION_ACCESSIBILE_NAME,
-          base::NumberToString16(drop_target_.page + 1),
-          base::NumberToString16(row_number),
-          base::NumberToString16(col_number)));
+          base::NumberToString16(page), base::NumberToString16(row),
+          base::NumberToString16(col)));
   announcement_view->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
 }
 
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h
index bd7cdc9583..56a8c76d 100644
--- a/ash/app_list/views/apps_grid_view.h
+++ b/ash/app_list/views/apps_grid_view.h
@@ -617,7 +617,10 @@
 
   // During an app drag, creates an a11y event to verbalize drop target
   // location.
-  void MaybeCreateReorderAccessibilityEvent();
+  void MaybeCreateDragReorderAccessibilityEvent();
+
+  // Modifies the announcement view to verbalize |target_index|.
+  void AnnounceReorder(const GridIndex& target_index);
 
   // Creates a new GhostImageView at |reorder_placeholder_| and initializes
   // |current_ghost_view_| and |last_ghost_view_|.
diff --git a/ash/login/OWNERS b/ash/login/OWNERS
index 509d547..b206edc6 100644
--- a/ash/login/OWNERS
+++ b/ash/login/OWNERS
@@ -1,4 +1,5 @@
 jdufault@chromium.org
+tbarzic@chromium.org
 xiyuan@chromium.org
 
 # For login-screen issues use component UI>Shell>StartScreen
diff --git a/ash/public/interfaces/accessibility_focus_ring_controller.mojom b/ash/public/interfaces/accessibility_focus_ring_controller.mojom
index ae4ff29..91cf8e0b 100644
--- a/ash/public/interfaces/accessibility_focus_ring_controller.mojom
+++ b/ash/public/interfaces/accessibility_focus_ring_controller.mojom
@@ -8,24 +8,33 @@
 
 enum FocusRingBehavior { FADE_OUT_FOCUS_RING, PERSIST_FOCUS_RING };
 
+enum FocusRingType { GLOW, SOLID, DASHED };
+
+// Defines a specific focus ring by specifying:
+// - |rects_in_screen| the regions around which to draw the focus ring (in
+//       screen coordinates).
+// - |focus_ring_behavior| whether it should persist or fade.
+// - |focus_ring_type| the visual style of the focus ring.
+// - |color| the color of the focus ring.
+// - |secondary_color| a secondary color, used by some visual styles. The
+//       default value is SK_ColorTRANSPARENT.
+struct FocusRing {
+  array<gfx.mojom.Rect> rects_in_screen;
+  FocusRingBehavior behavior;
+  FocusRingType type;
+  uint32 color;
+  uint32 secondary_color = 0; // SK_ColorTRANSPARENT
+};
+
+
 // Interface for ash client (e.g. Chrome) to control and query accessibility
 // focus ring features.
 interface AccessibilityFocusRingController {
-  // Sets the focus ring color for the given caller.
-  SetFocusRingColor(uint32 skcolor, string caller_id);
+  // Sets the focus ring with the given ID to the specifications of focus_ring.
+  SetFocusRing(string focus_ring_id, FocusRing focus_ring);
 
-  // Resets the focus ring color back to the default for the given caller.
-  ResetFocusRingColor(string caller_id);
-
-  // Draws a focus ring around the given set of rects in screen coordinates. Use
-  // |focus_ring_behavior| to specify whether the focus ring should persist or
-  // fade out for the given caller.
-  SetFocusRing(array<gfx.mojom.Rect> rects_in_screen,
-               FocusRingBehavior focus_ring_behavior,
-               string caller_id);
-
-  // Hides focus ring on screen for the given caller.
-  HideFocusRing(string caller_id);
+  // Hides focus ring on screen with the given ID.
+  HideFocusRing(string focus_ring_id);
 
   // Draws a highlight at the given rects in screen coordinates. Rects may be
   // overlapping and will be merged into one layer. This looks similar to
@@ -38,10 +47,4 @@
   // Hides highlight on screen.
   // TODO(katie): Add |caller_id| to highlights as well.
   HideHighlights();
-
-  // Enables double focus rings and sets the second color for the given caller.
-  EnableDoubleFocusRing(uint32 skcolor, string caller_id);
-
-  // Disables double focus rings for the given caller.
-  DisableDoubleFocusRing(string caller_id);
 };
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc
index 3d37e025..28af351 100644
--- a/ash/shelf/app_list_button.cc
+++ b/ash/shelf/app_list_button.cc
@@ -188,19 +188,6 @@
   return kViewClassName;
 }
 
-std::unique_ptr<views::InkDropRipple> AppListButton::CreateInkDropRipple()
-    const {
-  const int app_list_button_radius = ShelfConstants::control_border_radius();
-  gfx::Point center = GetCenterPoint();
-  gfx::Rect bounds(center.x() - app_list_button_radius,
-                   center.y() - app_list_button_radius,
-                   2 * app_list_button_radius, 2 * app_list_button_radius);
-  return std::make_unique<views::FloodFillInkDropRipple>(
-      size(), GetLocalBounds().InsetsFrom(bounds),
-      GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(),
-      ink_drop_visible_opacity());
-}
-
 void AppListButton::PaintButtonContents(gfx::Canvas* canvas) {
   gfx::PointF circle_center(GetCenterPoint());
 
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h
index c92b86c..c698120 100644
--- a/ash/shelf/app_list_button.h
+++ b/ash/shelf/app_list_button.h
@@ -50,7 +50,6 @@
 
  protected:
   // views::Button:
-  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
  private:
diff --git a/ash/shelf/app_list_button_unittest.cc b/ash/shelf/app_list_button_unittest.cc
index fa0bbb0..f94e57c 100644
--- a/ash/shelf/app_list_button_unittest.cc
+++ b/ash/shelf/app_list_button_unittest.cc
@@ -16,6 +16,7 @@
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
 #include "ash/shelf/shelf.h"
+#include "ash/shelf/shelf_constants.h"
 #include "ash/shelf/shelf_view.h"
 #include "ash/shelf/shelf_view_test_api.h"
 #include "ash/shell.h"
@@ -153,7 +154,7 @@
 
   Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
   test_api.RunMessageLoopUntilAnimationsDone();
-  EXPECT_EQ(0, app_list_button()->bounds().x());
+  EXPECT_EQ(ShelfConstants::button_spacing(), app_list_button()->bounds().x());
 }
 
 class VoiceInteractionAppListButtonTest : public AppListButtonTest {
diff --git a/ash/shelf/overflow_bubble_view.cc b/ash/shelf/overflow_bubble_view.cc
index d7c242f..487773d 100644
--- a/ash/shelf/overflow_bubble_view.cc
+++ b/ash/shelf/overflow_bubble_view.cc
@@ -179,6 +179,8 @@
 gfx::Rect OverflowBubbleView::GetBubbleBounds() {
   const gfx::Size content_size = GetPreferredSize();
   const gfx::Rect anchor_rect = GetAnchorRect();
+  const int distance_to_overflow_button =
+      kDistanceToMainShelf + (kShelfSize - kShelfControlSize) / 2;
   gfx::Rect monitor_rect =
       display::Screen::GetScreen()
           ->GetDisplayNearestPoint(anchor_rect.CenterPoint())
@@ -191,7 +193,7 @@
         base::i18n::IsRTL()
             ? anchor_rect.x() - kEndPadding
             : anchor_rect.right() - content_size.width() - kEndPadding,
-        anchor_rect.y() - kDistanceToMainShelf - content_size.height(),
+        anchor_rect.y() - distance_to_overflow_button - content_size.height(),
         content_size.width() + 2 * kEndPadding, content_size.height());
     if (bounds.x() < monitor_rect.x())
       bounds.Offset(monitor_rect.x() - bounds.x(), 0);
@@ -203,9 +205,10 @@
       0, anchor_rect.bottom() - content_size.height() - kEndPadding,
       content_size.width(), content_size.height() + 2 * kEndPadding);
   if (shelf_->alignment() == SHELF_ALIGNMENT_LEFT)
-    bounds.set_x(anchor_rect.right() + kDistanceToMainShelf);
+    bounds.set_x(anchor_rect.right() + distance_to_overflow_button);
   else
-    bounds.set_x(anchor_rect.x() - kDistanceToMainShelf - content_size.width());
+    bounds.set_x(anchor_rect.x() - distance_to_overflow_button -
+                 content_size.width());
   if (bounds.y() < monitor_rect.y())
     bounds.Offset(0, monitor_rect.y() - bounds.y());
   if (bounds.bottom() > monitor_rect.bottom())
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc
index 0143fb8..e5a867ff 100644
--- a/ash/shelf/shelf_control_button.cc
+++ b/ash/shelf/shelf_control_button.cc
@@ -22,21 +22,22 @@
 ShelfControlButton::ShelfControlButton(ShelfView* shelf_view)
     : ShelfButton(shelf_view), shelf_(shelf_view->shelf()) {
   set_has_ink_drop_action_on_click(true);
-  SetSize(gfx::Size(kShelfControlSize, kShelfControlSize));
 }
 
 ShelfControlButton::~ShelfControlButton() = default;
 
 gfx::Point ShelfControlButton::GetCenterPoint() const {
-  return gfx::Point(width() / 2.f, width() / 2.f);
+  return gfx::Point(width() / 2.f, height() / 2.f);
 }
 
 std::unique_ptr<views::InkDropRipple> ShelfControlButton::CreateInkDropRipple()
     const {
+  const int button_radius = ShelfConstants::control_border_radius();
+  gfx::Point center = GetCenterPoint();
+  gfx::Rect bounds(center.x() - button_radius, center.y() - button_radius,
+                   2 * button_radius, 2 * button_radius);
   return std::make_unique<views::FloodFillInkDropRipple>(
-      size(),
-      gfx::Insets(ShelfConstants::button_size() / 2 -
-                  ShelfConstants::control_border_radius()),
+      size(), GetLocalBounds().InsetsFrom(bounds),
       GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(),
       ink_drop_visible_opacity());
 }
@@ -51,21 +52,8 @@
   return "ash/ShelfControlButton";
 }
 
-gfx::Rect ShelfControlButton::CalculateButtonBounds() const {
-  ShelfAlignment alignment = shelf_->alignment();
-  gfx::Rect content_bounds = GetContentsBounds();
-  // Align the button to the top of a bottom-aligned shelf, to the right edge
-  // a left-aligned shelf, and to the left edge of a right-aligned shelf.
-  const int inset = (ShelfConstants::shelf_size() - kShelfControlSize) / 2;
-  const int x = alignment == SHELF_ALIGNMENT_LEFT
-                    ? content_bounds.right() - inset - kShelfControlSize
-                    : content_bounds.x() + inset;
-  return gfx::Rect(x, content_bounds.y() + inset, kShelfControlSize,
-                   kShelfControlSize);
-}
-
 void ShelfControlButton::PaintButtonContents(gfx::Canvas* canvas) {
-  PaintBackground(canvas, CalculateButtonBounds());
+  PaintBackground(canvas, GetContentsBounds());
 }
 
 void ShelfControlButton::PaintBackground(gfx::Canvas* canvas,
diff --git a/ash/shelf/shelf_control_button.h b/ash/shelf/shelf_control_button.h
index ed1055c..1b10a4e 100644
--- a/ash/shelf/shelf_control_button.h
+++ b/ash/shelf/shelf_control_button.h
@@ -37,9 +37,6 @@
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
  private:
-  // Calculates the bounds of the control button based on the shelf alignment.
-  gfx::Rect CalculateButtonBounds() const;
-
   Shelf* shelf_;
 
   DISALLOW_COPY_AND_ASSIGN(ShelfControlButton);
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index c8b1dd6..87be8b8 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -89,8 +89,8 @@
 constexpr int kSeparatorSize = 20;
 constexpr int kSeparatorThickness = 1;
 
-// The margin between the app list button and the first shelf item.
-constexpr int kAppListButtonMargin = 32;
+// The margin on either side of the group of app icons.
+constexpr int kAppIconGroupMargin = 16;
 
 // White with ~20% opacity.
 constexpr SkColor kSeparatorColor = SkColorSetARGB(0x32, 0xFF, 0xFF, 0xFF);
@@ -518,8 +518,7 @@
 }
 
 gfx::Size ShelfView::CalculatePreferredSize() const {
-  gfx::Rect overflow_bounds;
-  CalculateIdealBounds(&overflow_bounds);
+  CalculateIdealBounds();
 
   int last_button_index = last_visible_index_;
   if (!is_overflow_mode() && overflow_button_ && overflow_button_->visible())
@@ -1060,12 +1059,11 @@
     return;
   }
 
-  gfx::Rect overflow_bounds;
-  CalculateIdealBounds(&overflow_bounds);
+  CalculateIdealBounds();
   views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_);
-  overflow_button_->SetBoundsRect(overflow_bounds);
   UpdateBackButton();
   LayoutAppListAndBackButtonHighlight();
+  LayoutOverflowButton();
   UpdateVisibleShelfItemBoundsUnion();
 }
 
@@ -1083,17 +1081,24 @@
   return -1;
 }
 
-int ShelfView::GetDimensionOfCenteredShelfItems() const {
+int ShelfView::GetDimensionOfAppIcons(int max_size) const {
   int size = 0;
-  int added_items = 0;
-  for (ShelfItem item : model_->items()) {
-    if (item.type == TYPE_PINNED_APP || item.type == TYPE_APP ||
-        item.type == TYPE_BROWSER_SHORTCUT) {
-      size += ShelfConstants::button_size();
-      added_items++;
+  for (int i = kAppListButtonIndex + 1; i < view_model_->view_size(); ++i) {
+    int new_size = size;
+    new_size += ShelfConstants::button_size();
+    if (i > kAppListButtonIndex + 1) {
+      // TODO(manucornet): If one of the displayed items is the overflow
+      // button, we are overestimating the dimension a tiny bit because
+      // control buttons are smaller than app buttons. But taking this into
+      // account is a little tricky because at this stage we don't know whether
+      // we are overflowing. Fix this and add tests to check for perfect
+      // centering when the overflow button is shown.
+      new_size += ShelfConstants::button_spacing();
     }
+    if (new_size > max_size)
+      return size;
+    size = new_size;
   }
-  size += (added_items - 1) * ShelfConstants::button_spacing();
   return size;
 }
 
@@ -1138,13 +1143,17 @@
                                back_and_app_list_background_size));
 }
 
-void ShelfView::CalculateIdealBounds(gfx::Rect* overflow_bounds) const {
+void ShelfView::CalculateIdealBounds() const {
   DCHECK(model_->item_count() == view_model_->view_size());
 
   const int button_spacing = ShelfConstants::button_spacing();
-  const int button_size = ShelfConstants::button_size();
-
   const int available_size = shelf_->PrimaryAxisValue(width(), height());
+  // Size occupied by the app list button and back button plus all appropriate
+  // margins is not available for actual app icons.
+  const int available_size_for_app_icons =
+      available_size - kShelfButtonSpacing -
+      (IsTabletModeEnabled() ? 2 : 1) * kShelfControlSize -
+      2 * kAppIconGroupMargin;
   const int separator_index = GetSeparatorIndex();
   const bool virtual_keyboard_visible =
       Shell::Get()->system_tray_model()->virtual_keyboard()->visible();
@@ -1155,13 +1164,17 @@
                          !virtual_keyboard_visible);
   int app_list_button_position;
 
-  int x = 0;
-  int y = 0;
-
-  int w = shelf_->PrimaryAxisValue(button_size, width());
-  int h = shelf_->PrimaryAxisValue(height(), button_size);
+  int x = shelf_->PrimaryAxisValue(button_spacing, 0);
+  int y = shelf_->PrimaryAxisValue(0, button_spacing);
 
   for (int i = 0; i < view_model_->view_size(); ++i) {
+    // "Primary" as in "same direction as the shelf's direction". The
+    // "secondary" (orthogonal) size is always the full shelf to maximize click
+    // targets even for control buttons.
+    const int size_primary =
+        (i <= kAppListButtonIndex) ? kShelfControlSize : kShelfButtonSize;
+    const int size_secondary = kShelfButtonSize;
+
     if (i < first_visible_index_) {
       // This happens for the overflow view.
       view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0));
@@ -1169,19 +1182,41 @@
     }
     if (i == kAppListButtonIndex + 1) {
       // Start centering after we've laid out the app list button.
-      // Center the shelf items on the whole shelf, including the status
-      // area widget.
-      int centered_shelf_items_size = GetDimensionOfCenteredShelfItems();
+      // Now there are two possibilities. Either all the apps fit when centered
+      // on the whole screen width, in which case we do that. Or, when space
+      // becomes a little tight (which happens especially when the status area
+      // is wider because of extra panels), we center apps according to the
+      // available space on the shelf (subtracting what's already allocated to
+      // the app list button).
+
+      int app_icons_size = GetDimensionOfAppIcons(available_size_for_app_icons);
       StatusAreaWidget* status_widget = shelf_widget_->status_area_widget();
-      int status_widget_size =
+      const int status_widget_size =
           status_widget ? shelf_->PrimaryAxisValue(
                               status_widget->GetWindowBoundsInScreen().width(),
                               status_widget->GetWindowBoundsInScreen().height())
                         : 0;
-      int padding_for_centering =
-          (available_size + status_widget_size - centered_shelf_items_size) / 2;
+      const int screen_size = available_size + status_widget_size;
+
+      int padding_for_centering = 0;
+      // An easy way to check whether the apps fit at the exact center of the
+      // screen is to imagine that we have another status widget on the
+      // other side (the status widget is always bigger than the app list
+      // button plus the back button if applicable) and see if the apps
+      // can fit in the middle.
+      if (app_icons_size + 2 * status_widget_size + 2 * kAppIconGroupMargin <
+          screen_size) {
+        padding_for_centering = (screen_size - app_icons_size) / 2;
+      } else {
+        padding_for_centering =
+            kShelfButtonSpacing +
+            (IsTabletModeEnabled() ? 2 : 1) * kShelfControlSize +
+            kAppIconGroupMargin +
+            (available_size_for_app_icons - app_icons_size) / 2;
+      }
+
       if (padding_for_centering >
-          app_list_button_position + kAppListButtonMargin) {
+          app_list_button_position + kAppIconGroupMargin) {
         // Only shift buttons to the right, never let them interfere with the
         // left-aligned system buttons.
         x = shelf_->PrimaryAxisValue(padding_for_centering, 0);
@@ -1189,30 +1224,26 @@
       }
     }
 
-    view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
+    view_model_->set_ideal_bounds(
+        i,
+        gfx::Rect(x, y, shelf_->PrimaryAxisValue(size_primary, size_secondary),
+                  shelf_->PrimaryAxisValue(size_secondary, size_primary)));
+
     // If not in tablet mode do not increase |x| or |y|. Instead just let the
     // next item (app list button) cover the back button, which will have
     // opacity 0 anyways.
     if (i == kBackButtonIndex && !IsTabletModeEnabled())
       continue;
 
-    // There is no spacing between the first two elements. Do not worry about y
-    // since the back button only appears in tablet mode, which forces the shelf
-    // to be bottom aligned.
-    x = shelf_->PrimaryAxisValue(x + w + (i == 0 ? 0 : button_spacing), x);
-    y = shelf_->PrimaryAxisValue(y, y + h + button_spacing);
-
-    // In the new UI, padding between the back & app list buttons is smaller
-    // than between all other shelf items.
-    if (i == kBackButtonIndex)
-      x -= button_spacing;
+    x = shelf_->PrimaryAxisValue(x + size_primary + button_spacing, x);
+    y = shelf_->PrimaryAxisValue(y, y + size_primary + button_spacing);
 
     if (i == kAppListButtonIndex) {
       app_list_button_position = shelf_->PrimaryAxisValue(x, y);
       // A larger minimum padding after the app list button is required:
       // increment with the necessary extra amount.
-      x += shelf_->PrimaryAxisValue(kAppListButtonMargin - button_spacing, 0);
-      y += shelf_->PrimaryAxisValue(0, kAppListButtonMargin - button_spacing);
+      x += shelf_->PrimaryAxisValue(kAppIconGroupMargin - button_spacing, 0);
+      y += shelf_->PrimaryAxisValue(0, kAppIconGroupMargin - button_spacing);
     }
 
     if (i == separator_index) {
@@ -1237,11 +1268,8 @@
     const_cast<ShelfView*>(this)->UpdateAllButtonsVisibilityInOverflowMode();
     return;
   }
-
-  overflow_bounds->set_size(gfx::Size(shelf_->PrimaryAxisValue(w, width()),
-                                      shelf_->PrimaryAxisValue(height(), h)));
   last_visible_index_ =
-      IndexOfLastItemThatFitsSize(available_size - button_spacing);
+      IndexOfLastItemThatFitsSize(available_size - kAppIconGroupMargin);
   bool show_overflow = last_visible_index_ < model_->item_count() - 1;
 
   // In the main shelf, the first visible index is either the back button (in
@@ -1263,8 +1291,8 @@
     // FinalizeRipOffDrag().
     if (dragged_off_shelf_ && view_model_->view_at(i) == drag_view_)
       continue;
-    // If virtual keyboard is visible, only back button and app list button are
-    // shown.
+    // If the virtual keyboard is visible, only the back button and the app
+    // list button are shown.
     const bool is_visible_item = !virtual_keyboard_visible ||
                                  i == kBackButtonIndex ||
                                  i == kAppListButtonIndex;
@@ -1274,28 +1302,6 @@
 
   overflow_button_->SetVisible(show_overflow);
   if (show_overflow) {
-    DCHECK_NE(0, view_model_->view_size());
-    if (last_visible_index_ == -1) {
-      x = 0;
-      y = 0;
-    } else {
-      x = shelf_->PrimaryAxisValue(
-          view_model_->ideal_bounds(last_visible_index_).right(),
-          view_model_->ideal_bounds(last_visible_index_).x());
-      y = shelf_->PrimaryAxisValue(
-          view_model_->ideal_bounds(last_visible_index_).y(),
-          view_model_->ideal_bounds(last_visible_index_).bottom());
-    }
-
-    if (last_visible_index_ >= 0) {
-      // Add more space between last visible item and overflow button.
-      // Without this, two buttons look too close compared with other items.
-      x = shelf_->PrimaryAxisValue(x + button_spacing, x);
-      y = shelf_->PrimaryAxisValue(y, y + button_spacing);
-    }
-
-    overflow_bounds->set_x(x);
-    overflow_bounds->set_y(y);
     if (overflow_bubble_.get() && overflow_bubble_->IsShowing())
       UpdateOverflowRange(overflow_bubble_->bubble_view()->shelf_view());
   } else {
@@ -1304,6 +1310,31 @@
   }
 }
 
+void ShelfView::LayoutOverflowButton() const {
+  DCHECK_NE(0, view_model_->view_size());
+  int x = 0;
+  int y = 0;
+  if (last_visible_index_ != -1) {
+    const int offset = (kShelfButtonSize - kShelfControlSize) / 2;
+    x = shelf_->PrimaryAxisValue(
+        offset + view_model_->ideal_bounds(last_visible_index_).right(),
+        offset + view_model_->ideal_bounds(last_visible_index_).x());
+    y = shelf_->PrimaryAxisValue(
+        offset + view_model_->ideal_bounds(last_visible_index_).y(),
+        offset + view_model_->ideal_bounds(last_visible_index_).bottom());
+  }
+
+  if (last_visible_index_ >= 0) {
+    // Add more space between last visible item and overflow button.
+    // Without this, two buttons look too close compared with other items.
+    x = shelf_->PrimaryAxisValue(x + ShelfConstants::button_spacing(), x);
+    y = shelf_->PrimaryAxisValue(y, y + ShelfConstants::button_spacing());
+  }
+
+  overflow_button_->SetBoundsRect(
+      gfx::Rect(x, y, kShelfControlSize, kShelfControlSize));
+}
+
 int ShelfView::IndexOfLastItemThatFitsSize(int max_value) const {
   int index = model_->item_count() - 1;
   while (index >= 0 &&
@@ -1316,8 +1347,7 @@
 }
 
 void ShelfView::AnimateToIdealBounds() {
-  gfx::Rect overflow_bounds;
-  CalculateIdealBounds(&overflow_bounds);
+  CalculateIdealBounds();
   for (int i = 0; i < view_model_->view_size(); ++i) {
     View* view = view_model_->view_at(i);
     bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i));
@@ -1326,8 +1356,8 @@
     if (i && view->border())
       view->SetBorder(views::NullBorder());
   }
-  overflow_button_->SetBoundsRect(overflow_bounds);
   LayoutAppListAndBackButtonHighlight();
+  LayoutOverflowButton();
   UpdateVisibleShelfItemBoundsUnion();
 }
 
@@ -2020,8 +2050,7 @@
   // button before this animation completes it doesn't appear at some random
   // spot (because it was in the middle of animating from 0,0 0x0 to its
   // target).
-  gfx::Rect overflow_bounds;
-  CalculateIdealBounds(&overflow_bounds);
+  CalculateIdealBounds();
   view->SetBoundsRect(view_model_->ideal_bounds(model_index));
 
   // The first animation moves all the views to their target position. |view|
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index 8af59e6..1695af0 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -247,9 +247,10 @@
   // Returns whether |item| should belong in the pinned section of the shelf.
   bool IsItemPinned(const ShelfItem& item) const;
 
-  // Enumerates the shelf items that are centered in the new UI and returns
-  // the total size they occupy.
-  int GetDimensionOfCenteredShelfItems() const;
+  // Enumerates the shelf apps and returns the total size they occupy,
+  // accounting for all apps or, if the total size is greater than |max_size|,
+  // the size of however many app can fit without exceeding |max_size|.
+  int GetDimensionOfAppIcons(int max_size) const;
 
   // Returns the index of the item after which the separator should be shown,
   // or -1 if no separator is required.
@@ -343,7 +344,9 @@
 
   // Calculates the ideal bounds. The bounds of each button corresponding to an
   // item in the model is set in |view_model_|.
-  void CalculateIdealBounds(gfx::Rect* overflow_bounds) const;
+  void CalculateIdealBounds() const;
+
+  void LayoutOverflowButton() const;
 
   // Returns the index of the last view whose max primary axis coordinate is
   // less than |max_value|. Returns -1 if nothing fits, or there are no views.
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 656b3dd..205ee78 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -12,6 +12,7 @@
 #include "ash/app_list/test/app_list_test_helper.h"
 #include "ash/app_list/views/app_list_view.h"
 #include "ash/focus_cycler.h"
+#include "ash/ime/ime_controller.h"
 #include "ash/public/cpp/shelf_item_delegate.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/public/cpp/shelf_prefs.h"
@@ -2281,6 +2282,122 @@
   EXPECT_TRUE(test_api_->CloseMenu());
 }
 
+void ExpectWithinOnePixel(int a, int b) {
+  EXPECT_TRUE(abs(a - b) <= 1) << "Values " << a << " and " << b
+                               << " should have a difference no greater than 1";
+}
+
+TEST_F(ShelfViewTest, IconCenteringTest) {
+  const display::Display display =
+      display::Screen::GetScreen()->GetPrimaryDisplay();
+  const int screen_width = display.bounds().width();
+  const int screen_center = screen_width / 2;
+
+  // Show the IME panel, to introduce for asymettry with a larger status area.
+  Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
+
+  // At the start, we have exactly one app icon for the browser. That should
+  // be centered on the screen.
+  const ShelfAppButton* button1 = GetButtonByID(model_->items()[2].id);
+  ExpectWithinOnePixel(screen_center,
+                       button1->GetBoundsInScreen().CenterPoint().x());
+  // Also check that the distance between the icon edge and the screen edge is
+  // the same on both sides.
+  ExpectWithinOnePixel(button1->GetBoundsInScreen().x(),
+                       screen_width - button1->GetBoundsInScreen().right());
+
+  const int apps_that_can_fit_at_center_of_screen = 8;
+  std::vector<ShelfAppButton*> app_buttons;
+  // Start with just the browser app button.
+  app_buttons.push_back(GetButtonByID(model_->items()[2].id));
+  int n_buttons = 1;
+
+  // Now repeat the same process by adding apps until they can't fit at the
+  // center of the screen.
+  for (int i = 1; i < apps_that_can_fit_at_center_of_screen; ++i) {
+    // Add a new app and add its button to our list.
+    app_buttons.push_back(GetButtonByID(AddApp()));
+    n_buttons = app_buttons.size();
+    if (n_buttons % 2 == 1) {
+      // Odd number of apps. Check that the middle app is exactly at the center
+      // of the screen.
+      ExpectWithinOnePixel(
+          screen_center,
+          app_buttons[n_buttons / 2]->GetBoundsInScreen().CenterPoint().x());
+    }
+    // Also check that the first icon is at the same distance from the left
+    // screen edge as the last icon is from the right screen edge.
+    ExpectWithinOnePixel(
+        app_buttons[0]->GetBoundsInScreen().x(),
+        screen_width - app_buttons[n_buttons - 1]->GetBoundsInScreen().right());
+  }
+
+  // Add one more app. Now the block of apps should be at the center of the
+  // shelf part of the shelf widget (not including the status area) as opposed
+  // to at the center of the whole screen. But we're not overflowing yet.
+  app_buttons.push_back(GetButtonByID(AddApp()));
+  n_buttons = app_buttons.size();
+  EXPECT_FALSE(shelf_view_->GetOverflowButton()->visible());
+  // Icons at either end should also be at the same distance from the app list
+  // button on the left, and the status area on the right.
+  gfx::NativeWindow window = shelf_view_->shelf_widget()->GetNativeWindow();
+  views::View* status_area_view = RootWindowController::ForWindow(window)
+                                      ->GetStatusAreaWidget()
+                                      ->GetContentsView();
+  const int status_area_left = status_area_view->GetBoundsInScreen().x();
+  const int app_list_button_right =
+      shelf_view_->GetAppListButton()->GetBoundsInScreen().right();
+  ExpectWithinOnePixel(
+      app_buttons[0]->GetBoundsInScreen().x() - app_list_button_right,
+      status_area_left -
+          app_buttons[n_buttons - 1]->GetBoundsInScreen().right());
+
+  // Add another app. The overflow button should now appear.
+  app_buttons.push_back(GetButtonByID(AddApp()));
+  n_buttons = app_buttons.size();
+  EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible());
+}
+
+TEST_F(ShelfViewTest, FirstAndLastVisibleIndex) {
+  // At the start, the only things visible on the shelf are the app list button
+  // (index 1) and the browser app button (index 2).
+  EXPECT_EQ(1, shelf_view_->first_visible_index());
+  EXPECT_EQ(2, shelf_view_->last_visible_index());
+  // By enabling tablet mode, the back button (index 0) should become visible.
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+  EXPECT_EQ(0, shelf_view_->first_visible_index());
+  EXPECT_EQ(2, shelf_view_->last_visible_index());
+  // And things should return back to the previous state once tablet mode is off
+  // again.
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
+  EXPECT_EQ(1, shelf_view_->first_visible_index());
+  EXPECT_EQ(2, shelf_view_->last_visible_index());
+  // Now let's add some apps until the overflow button shows up, each time
+  // checking the first and last visible indices are what we expect.
+  int last_visible_index = 2;
+  int last_visible_index_before_overflow;
+  ShelfID last_added_item_id;
+  while (true) {
+    last_added_item_id = AddApp();
+    if (shelf_view_->GetOverflowButton()->visible()) {
+      last_visible_index_before_overflow = last_visible_index;
+      break;
+    }
+    last_visible_index++;
+    EXPECT_EQ(1, shelf_view_->first_visible_index());
+    EXPECT_EQ(last_visible_index, shelf_view_->last_visible_index());
+  }
+  // Now remove the last item we just added. That should get rid of the
+  // overflow button, and get back to the previous state.
+  RemoveByID(last_added_item_id);
+  EXPECT_EQ(1, shelf_view_->first_visible_index());
+  EXPECT_EQ(last_visible_index_before_overflow,
+            shelf_view_->last_visible_index());
+  // Adding another app should let the overflow button appear again.
+  AddApp();
+  EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible());
+}
+
 // Test class that tests both context and application menus.
 class ShelfViewMenuTest : public ShelfViewTest,
                           public testing::WithParamInterface<bool> {
diff --git a/base/sampling_heap_profiler/poisson_allocation_sampler.cc b/base/sampling_heap_profiler/poisson_allocation_sampler.cc
index f169c7d..9fab99b 100644
--- a/base/sampling_heap_profiler/poisson_allocation_sampler.cc
+++ b/base/sampling_heap_profiler/poisson_allocation_sampler.cc
@@ -407,12 +407,21 @@
                                            size_t size,
                                            AllocatorType type,
                                            const char* context) {
-  if (UNLIKELY(!g_running.load(std::memory_order_relaxed)))
-    return;
   g_accumulated_bytes_tls += size;
   intptr_t accumulated_bytes = g_accumulated_bytes_tls;
   if (LIKELY(accumulated_bytes < 0))
     return;
+
+  if (UNLIKELY(!g_running.load(std::memory_order_relaxed))) {
+    // Sampling is in fact disabled. Put a large negative value into
+    // the accumulator. 1MB is large enough to have this code not trigger
+    // frequently, and small enough to eventually start collecting samples
+    // when the sampling is enabled.
+    constexpr intptr_t sample_size_of_1mb = 1 << 20;
+    g_accumulated_bytes_tls = -sample_size_of_1mb;
+    return;
+  }
+
   instance_->DoRecordAlloc(accumulated_bytes, size, address, type, context);
 }
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 0c26395..d75976d 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=75
 MINOR=0
-BUILD=3739
+BUILD=3740
 PATCH=0
diff --git a/chrome/android/java/res/color/menu_item_tint.xml b/chrome/android/java/res/color/tint_on_blue_bg.xml
similarity index 64%
rename from chrome/android/java/res/color/menu_item_tint.xml
rename to chrome/android/java/res/color/tint_on_blue_bg.xml
index 33b9103b..d6d0924 100644
--- a/chrome/android/java/res/color/menu_item_tint.xml
+++ b/chrome/android/java/res/color/tint_on_blue_bg.xml
@@ -5,6 +5,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/modern_blue_600_alpha_38_opaque" android:state_enabled="false" />
-    <item android:color="@android:color/white" />
+    <item android:color="@color/default_icon_color_inverse_disabled" android:state_enabled="false" />
+    <item android:color="@color/default_icon_color_inverse" />
 </selector>
diff --git a/chrome/android/java/res/layout/list_selection_handle_view.xml b/chrome/android/java/res/layout/list_selection_handle_view.xml
index 2d6525b7..af7562fd 100644
--- a/chrome/android/java/res/layout/list_selection_handle_view.xml
+++ b/chrome/android/java/res/layout/list_selection_handle_view.xml
@@ -16,7 +16,7 @@
         android:scaleType="center"
         android:background="@drawable/list_item_icon_modern_bg"
         android:visibility="gone"
-        app:tint="@color/white_mode_tint"
+        app:tint="@color/default_icon_color_inverse"
         app:layout_gravity="center"
         tools:ignore="ContentDescription" />
 
diff --git a/chrome/android/java/res/layout/number_roll_view.xml b/chrome/android/java/res/layout/number_roll_view.xml
index 018c5a1..533e38f 100644
--- a/chrome/android/java/res/layout/number_roll_view.xml
+++ b/chrome/android/java/res/layout/number_roll_view.xml
@@ -18,7 +18,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
         android:singleLine="true"
-        android:textAppearance="@style/TextAppearance.WhiteHeadline" />
+        android:textAppearance="@style/TextAppearance.Headline.Inverse" />
 
     <TextView
         android:id="@+id/down"
@@ -26,5 +26,5 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
         android:singleLine="true"
-        android:textAppearance="@style/TextAppearance.WhiteHeadline" />
+        android:textAppearance="@style/TextAppearance.Headline.Inverse" />
 </org.chromium.chrome.browser.widget.NumberRollView>
diff --git a/chrome/android/java/res/menu/bookmark_action_bar_menu.xml b/chrome/android/java/res/menu/bookmark_action_bar_menu.xml
index 33c7887..fd4831c6 100644
--- a/chrome/android/java/res/menu/bookmark_action_bar_menu.xml
+++ b/chrome/android/java/res/menu/bookmark_action_bar_menu.xml
@@ -35,17 +35,20 @@
             android:id="@+id/selection_mode_edit_menu_id"
             android:icon="@drawable/bookmark_edit_active"
             android:title="@null"
-            app:showAsAction="ifRoom" />
+            app:showAsAction="ifRoom"
+            app:iconTint="@color/default_icon_color_inverse" />
         <item
             android:id="@+id/selection_mode_move_menu_id"
             android:icon="@drawable/bookmark_move_active"
             android:title="@null"
-            app:showAsAction="ifRoom" />
+            app:showAsAction="ifRoom"
+            app:iconTint="@color/default_icon_color_inverse" />
         <item
             android:id="@+id/selection_mode_delete_menu_id"
             android:icon="@drawable/ic_delete_white_24dp"
             android:title="@null"
-            app:showAsAction="ifRoom" />
+            app:showAsAction="ifRoom"
+            app:iconTint="@color/default_icon_color_inverse" />
         <item
             android:id="@+id/selection_open_in_new_tab_id"
             android:title="@string/contextmenu_open_in_new_tab"
diff --git a/chrome/android/java/res/menu/history_manager_menu.xml b/chrome/android/java/res/menu/history_manager_menu.xml
index 6fc57318..1920aa5f 100644
--- a/chrome/android/java/res/menu/history_manager_menu.xml
+++ b/chrome/android/java/res/menu/history_manager_menu.xml
@@ -35,7 +35,8 @@
             android:id="@+id/selection_mode_delete_menu_id"
             android:icon="@drawable/ic_delete_white_24dp"
             android:title="@string/remove"
-            app:showAsAction="ifRoom" />
+            app:showAsAction="ifRoom"
+            app:iconTint="@color/default_icon_color_inverse" />
         <item
             android:id="@+id/selection_mode_open_in_new_tab"
             android:title="@string/contextmenu_open_in_new_tab"
diff --git a/chrome/android/java/res_download/menu/download_manager_menu.xml b/chrome/android/java/res_download/menu/download_manager_menu.xml
index b5696c4e..b300fab1 100644
--- a/chrome/android/java/res_download/menu/download_manager_menu.xml
+++ b/chrome/android/java/res_download/menu/download_manager_menu.xml
@@ -60,12 +60,12 @@
             android:icon="@drawable/ic_share_white_24dp"
             android:title="@string/share"
             app:showAsAction="ifRoom"
-            app:iconTint="@color/menu_item_tint" />
+            app:iconTint="@color/tint_on_blue_bg" />
         <item
             android:id="@+id/selection_mode_delete_menu_id"
             android:icon="@drawable/ic_delete_white_24dp"
             android:title="@string/delete"
             app:showAsAction="ifRoom"
-            app:iconTint="@color/menu_item_tint" />
+            app:iconTint="@color/tint_on_blue_bg" />
      </group>
 </menu>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index d0450ca..5e49b1d2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -216,6 +216,7 @@
             "ContextualSuggestionsIPHReverseScroll";
     public static final String CUSTOM_CONTEXT_MENU = "CustomContextMenu";
     public static final String DATA_SAVER_LITE_MODE_REBRANDING = "DataSaverLiteModeRebranding";
+    public static final String DELEGATE_OVERSCROLL_SWIPES = "DelegateOverscrollSwipes";
     public static final String DONT_PREFETCH_LIBRARIES = "DontPrefetchLibraries";
     public static final String DOWNLOAD_HOME_SHOW_STORAGE_INFO = "DownloadHomeShowStorageInfo";
     public static final String DOWNLOAD_PROGRESS_INFOBAR = "DownloadProgressInfoBar";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
index 41bdf85..71cf6c0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
@@ -54,7 +54,8 @@
         mEndPadding = context.getResources().getDimensionPixelSize(
                 R.dimen.selectable_list_layout_row_padding);
 
-        mIconColorList = AppCompatResources.getColorStateList(context, R.color.white_mode_tint);
+        mIconColorList =
+                AppCompatResources.getColorStateList(context, R.color.default_icon_color_inverse);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index ae67a091..3b3dbfc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -33,25 +33,19 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeActionModeCallback;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.SwipeRefreshHandler;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.content.ContentUtils;
 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchTabHelper;
-import org.chromium.chrome.browser.crypto.CipherFactory;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenOptions;
-import org.chromium.chrome.browser.infobar.InfoBarContainer;
-import org.chromium.chrome.browser.media.ui.MediaSessionTabHelper;
 import org.chromium.chrome.browser.native_page.FrozenNativePage;
 import org.chromium.chrome.browser.native_page.NativePage;
 import org.chromium.chrome.browser.native_page.NativePageAssassin;
@@ -71,17 +65,12 @@
 import org.chromium.chrome.browser.tabmodel.TabReparentingParams;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
-import org.chromium.components.content_capture.ContentCaptureFeatures;
-import org.chromium.components.content_capture.ContentCaptureReceiverManager;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.content_public.browser.ChildProcessImportance;
 import org.chromium.content_public.browser.GestureListenerManager;
-import org.chromium.content_public.browser.ImeAdapter;
-import org.chromium.content_public.browser.ImeEventObserver;
 import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.SelectionPopupController;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsAccessibility;
 import org.chromium.content_public.common.BrowserControlsState;
@@ -347,7 +336,7 @@
         mPendingLoadParams = loadUrlParams;
         if (loadUrlParams != null) mUrl = loadUrlParams.getUrl();
 
-        TabThemeColorHelper.createForTab(this);
+        TabHelpers.initTabHelpers(this, creationState);
 
         // Restore data from the TabState, if it existed.
         if (frozenState != null) {
@@ -361,18 +350,6 @@
             }
         }
 
-        TabFullscreenHandler.createForTab(this);
-        InterceptNavigationDelegateImpl.createForTab(this);
-
-        if (incognito) {
-            CipherFactory.getInstance().triggerKeyGeneration();
-        }
-
-        ContextualSearchTabHelper.createForTab(this);
-        MediaSessionTabHelper.createForTab(this);
-
-        if (creationState != null) TabUma.create(this, creationState);
-
         mAttachStateChangeListener = new OnAttachStateChangeListener() {
             @Override
             public void onViewAttachedToWindow(View view) {
@@ -1248,34 +1225,25 @@
     }
 
     /**
-     * initializes the {@link WebContents}.
-     *
-     * @param webContents The WebContents object that will initialize all the browser components.
-     */
-    protected void initWebContents(WebContents webContents) {
-        ContentView cv = ContentView.createContentView(mThemedApplicationContext, webContents);
-        cv.setContentDescription(mThemedApplicationContext.getResources().getString(
-                R.string.accessibility_content_view));
-        webContents.initialize(PRODUCT_VERSION, new TabViewAndroidDelegate(this, cv), cv,
-                getWindowAndroid(), WebContents.createDefaultInternalsHolder());
-        SelectionPopupController.fromWebContents(webContents)
-                .setActionModeCallback(new ChromeActionModeCallback(this, webContents));
-        initBrowserComponents(webContents);
-    }
-
-    /**
-     * Completes the browser content components initialization around a native WebContents
-     * pointer. {@link #getNativePage()} will still return the {@link NativePage} if there is one.
+     * Initializes the {@link WebContents}. Completes the browser content components initialization
+     * around a native WebContents pointer.
+     * <p>
+     * {@link #getNativePage()} will still return the {@link NativePage} if there is one.
      * All initialization that needs to reoccur after a web contents swap should be added here.
      * <p />
      * NOTE: If you attempt to pass a native WebContents that does not have the same incognito
      * state as this tab this call will fail.
      *
-     * @param webContents The new web contents.
+     * @param webContents The WebContents object that will initialize all the browser components.
      */
-    private void initBrowserComponents(WebContents webContents) {
+    protected void initWebContents(WebContents webContents) {
         try {
-            TraceEvent.begin("ChromeTab.initBrowserComponents");
+            TraceEvent.begin("ChromeTab.initWebContents");
+            ContentView cv = ContentView.createContentView(mThemedApplicationContext, webContents);
+            cv.setContentDescription(mThemedApplicationContext.getResources().getString(
+                    R.string.accessibility_content_view));
+            webContents.initialize(PRODUCT_VERSION, new TabViewAndroidDelegate(this, cv), cv,
+                    getWindowAndroid(), WebContents.createDefaultInternalsHolder());
             NativePage previousNativePage = mNativePage;
             mNativePage = null;
             destroyNativePageInternal(previousNativePage);
@@ -1287,18 +1255,16 @@
             }
 
             mWebContents = webContents;
-            ContentUtils.setUserAgentOverride(mWebContents);
-            mContentView = mWebContents.getViewAndroidDelegate().getContainerView();
-
             mWebContents.setImportance(mImportance);
+            ContentUtils.setUserAgentOverride(mWebContents);
+
+            mContentView = cv;
             mContentView.setOnHierarchyChangeListener(this);
             mContentView.setOnSystemUiVisibilityChangeListener(this);
-
             mContentView.addOnAttachStateChangeListener(mAttachStateChangeListener);
             updateInteractableState();
+
             mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(this);
-            TabWebContentsObserver.from(this);
-            TabFavicon.from(this);
 
             int parentId = getParentId();
             if (parentId != INVALID_TAB_ID) {
@@ -1314,46 +1280,10 @@
                     new TabContextMenuPopulator(
                             mDelegateFactory.createContextMenuPopulator(this), this));
 
-            TabGestureStateListener.from(this, this::getFullscreenManager);
-
-            // The InfoBarContainer needs to be created after the ContentView has been natively
-            // initialized.
-            // In the case where restoring a Tab or showing a prerendered one we already have a
-            // valid infobar container, no need to recreate one.
-            InfoBarContainer.from(this);
-
-            SwipeRefreshHandler.from(this);
-            TrustedCdn.from(this);
-
+            TabHelpers.initWebContentsHelpers(this);
             notifyContentChanged();
-
-            // For browser tabs, we want to set accessibility focus to the page
-            // when it loads. This is not the default behavior for embedded
-            // web views.
-            getWebContentsAccessibility(getWebContents()).setShouldFocusOnPageLoad(true);
-
-            ImeAdapter.fromWebContents(mWebContents).addEventObserver(new ImeEventObserver() {
-                @Override
-                public void onImeEvent() {
-                    // Some text was set in the page. Don't reuse it if a tab is
-                    // open from the same external application, we might lose some
-                    // user data.
-                    mAppAssociatedWith = null;
-                }
-
-                @Override
-                public void onNodeAttributeUpdated(boolean editable, boolean password) {
-                    if (getFullscreenManager() == null) return;
-                    updateFullscreenEnabledState();
-                }
-            });
-
-            if (ContentCaptureFeatures.isEnabled()) {
-                // The created object is held by native side.
-                ContentCaptureReceiverManager.create(getWebContents());
-            }
         } finally {
-            TraceEvent.end("ChromeTab.initBrowserComponents");
+            TraceEvent.end("ChromeTab.initWebContents");
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java
new file mode 100644
index 0000000..558f820
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java
@@ -0,0 +1,91 @@
+// Copyright 2019 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.browser.tab;
+
+import org.chromium.chrome.browser.ChromeActionModeCallback;
+import org.chromium.chrome.browser.SwipeRefreshHandler;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchTabHelper;
+import org.chromium.chrome.browser.crypto.CipherFactory;
+import org.chromium.chrome.browser.infobar.InfoBarContainer;
+import org.chromium.chrome.browser.media.ui.MediaSessionTabHelper;
+import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
+import org.chromium.components.content_capture.ContentCaptureFeatures;
+import org.chromium.components.content_capture.ContentCaptureReceiverManager;
+import org.chromium.content_public.browser.ImeAdapter;
+import org.chromium.content_public.browser.ImeEventObserver;
+import org.chromium.content_public.browser.SelectionPopupController;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.WebContentsAccessibility;
+
+/**
+ * Helper class that initializes various tab UserData objects.
+ */
+public final class TabHelpers {
+    private TabHelpers() {}
+
+    /**
+     * Creates Tab helper objects upon Tab creation.
+     * @param tab {@link Tab} to create helpers for.
+     * @param creationState State in which the tab is created.
+     */
+    static void initTabHelpers(Tab tab, @TabCreationState Integer creationState) {
+        if (creationState != null) TabUma.create(tab, creationState);
+        TabThemeColorHelper.createForTab(tab);
+        TabFullscreenHandler.createForTab(tab);
+        InterceptNavigationDelegateImpl.createForTab(tab);
+        ContextualSearchTabHelper.createForTab(tab);
+        MediaSessionTabHelper.createForTab(tab);
+
+        // TODO(jinsukkim): Do this by having something observe new tab creation.
+        if (tab.isIncognito()) CipherFactory.getInstance().triggerKeyGeneration();
+    }
+
+    /**
+     * Initializes {@link TabWebContentsUserData} and WebContents-related objects
+     * when a new WebContents is set to the tab.
+     * @param tab {@link Tab} to create helpers for.
+     */
+    static void initWebContentsHelpers(Tab tab) {
+        // The InfoBarContainer needs to be created after the ContentView has been natively
+        // initialized. In the case where restoring a Tab or showing a prerendered one we already
+        // have a valid infobar container, no need to recreate one.
+        InfoBarContainer.from(tab);
+
+        TabWebContentsObserver.from(tab);
+        TabGestureStateListener.from(tab, tab::getFullscreenManager);
+        SwipeRefreshHandler.from(tab);
+        TabFavicon.from(tab);
+        TrustedCdn.from(tab);
+
+        WebContents webContents = tab.getWebContents();
+
+        // Initializes WebContents objects.
+
+        // TODO(jinsukkim): Split this up into a new userdata and FullscreenHandler.
+        ImeAdapter.fromWebContents(webContents).addEventObserver(new ImeEventObserver() {
+            @Override
+            public void onImeEvent() {
+                // Some text was set in the page. Don't reuse it if a tab is open from the same
+                // external application, we might lose some user data.
+                tab.setAppAssociatedWith(null);
+            }
+
+            @Override
+            public void onNodeAttributeUpdated(boolean editable, boolean password) {
+                if (tab.getFullscreenManager() == null) return;
+                tab.updateFullscreenEnabledState();
+            }
+        });
+        SelectionPopupController.fromWebContents(webContents)
+                .setActionModeCallback(new ChromeActionModeCallback(tab, webContents));
+
+        // For browser tabs, we want to set accessibility focus to the page when it loads. This
+        // is not the default behavior for embedded web views.
+        WebContentsAccessibility.fromWebContents(webContents).setShouldFocusOnPageLoad(true);
+
+        // The created object is held by native side.
+        if (ContentCaptureFeatures.isEnabled()) ContentCaptureReceiverManager.create(webContents);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
index f901a414..65f4dff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
@@ -40,8 +40,8 @@
      */
     public SelectableItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mIconColorList =
-                AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
+        mIconColorList = AppCompatResources.getColorStateList(
+                getContext(), R.color.default_icon_color_inverse);
         mDefaultLevel = getResources().getInteger(R.integer.list_item_level_default);
         mSelectedLevel = getResources().getInteger(R.integer.list_item_level_selected);
         mCheckDrawable = AnimatedVectorDrawableCompat.create(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
index 5a8a919..f38dce6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -204,8 +204,8 @@
 
         mDarkIconColorList =
                 AppCompatResources.getColorStateList(getContext(), R.color.standard_mode_tint);
-        mLightIconColorList =
-                AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
+        mLightIconColorList = AppCompatResources.getColorStateList(
+                getContext(), R.color.default_icon_color_inverse);
 
         setTitleTextAppearance(getContext(), R.style.TextAppearance_BlackHeadline);
         if (mTitleResId != 0) setTitle(mTitleResId);
@@ -214,8 +214,8 @@
         //                    buttons.
         mNormalMenuButton = TintedDrawable.constructTintedDrawable(
                 getContext(), R.drawable.ic_more_vert_black_24dp);
-        mSelectionMenuButton = TintedDrawable.constructTintedDrawable(
-                getContext(), R.drawable.ic_more_vert_black_24dp, R.color.white_mode_tint);
+        mSelectionMenuButton = TintedDrawable.constructTintedDrawable(getContext(),
+                R.drawable.ic_more_vert_black_24dp, R.color.default_icon_color_inverse);
         mNavigationIconDrawable = TintedDrawable.constructTintedDrawable(
                 getContext(), R.drawable.ic_arrow_back_white_24dp);
 
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 5266c7f..0c82c0b 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1508,6 +1508,7 @@
   "java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java",
   "java/src/org/chromium/chrome/browser/tab/TabIdManager.java",
   "java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java",
+  "java/src/org/chromium/chrome/browser/tab/TabHelpers.java",
   "java/src/org/chromium/chrome/browser/tab/TabObserver.java",
   "java/src/org/chromium/chrome/browser/tab/TabParentIntent.java",
   "java/src/org/chromium/chrome/browser/tab/TabRedirectHandler.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 05d209a..a9d49f1d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3284,10 +3284,6 @@
      FEATURE_VALUE_TYPE(printing::features::kUsePdfCompositorServiceForPrint)},
 #endif
 
-    {"autofill-dynamic-forms", flag_descriptions::kAutofillDynamicFormsName,
-     flag_descriptions::kAutofillDynamicFormsDescription, kOsAll,
-     FEATURE_VALUE_TYPE(autofill::features::kAutofillDynamicForms)},
-
     {"autofill-prefilled-fields",
      flag_descriptions::kAutofillPrefilledFieldsName,
      flag_descriptions::kAutofillPrefilledFieldsDescription, kOsAll,
@@ -3780,6 +3776,10 @@
      flag_descriptions::kAndroidSiteSettingsUIRefreshName,
      flag_descriptions::kAndroidSiteSettingsUIRefreshDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kAndroidSiteSettingsUIRefresh)},
+    {"delegate-overscroll-swipes",
+     flag_descriptions::kDelegateOverscrollSwipesName,
+     flag_descriptions::kDelegateOverscrollSwipesDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kDelegateOverscrollSwipes)},
     {"translate-android-manual-trigger",
      flag_descriptions::kTranslateAndroidManualTriggerName,
      flag_descriptions::kTranslateAndroidManualTriggerDescription, kOsAndroid,
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api.cc
index 22257b0..02b680a 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.cc
+++ b/chrome/browser/accessibility/accessibility_extension_api.cc
@@ -84,41 +84,66 @@
 ExtensionFunction::ResponseAction
 AccessibilityPrivateSetFocusRingsFunction::Run() {
 #if defined(OS_CHROMEOS)
-
   std::unique_ptr<accessibility_private::SetFocusRings::Params> params(
       accessibility_private::SetFocusRings::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
   auto* accessibility_manager = chromeos::AccessibilityManager::Get();
 
-  for (const accessibility_private::FocusRingInfo& focus_ring :
+  for (const accessibility_private::FocusRingInfo& focus_ring_info :
        params->focus_rings) {
+    ash::mojom::FocusRingPtr focus_ring_ptr = ash::mojom::FocusRing::New();
+    focus_ring_ptr->behavior =
+        ash::mojom::FocusRingBehavior::PERSIST_FOCUS_RING;
+
     // Convert the given rects into gfx::Rect objects.
-    std::vector<gfx::Rect> rects;
-    for (const accessibility_private::ScreenRect& rect : focus_ring.rects) {
-      rects.push_back(gfx::Rect(rect.left, rect.top, rect.width, rect.height));
+    for (const accessibility_private::ScreenRect& rect :
+         focus_ring_info.rects) {
+      focus_ring_ptr->rects_in_screen.push_back(
+          gfx::Rect(rect.left, rect.top, rect.width, rect.height));
     }
 
     const std::string id = accessibility_manager->GetFocusRingId(
-        extension_id(), focus_ring.id ? *(focus_ring.id) : "");
+        extension_id(), focus_ring_info.id ? *(focus_ring_info.id) : "");
 
-    SkColor color;
-    if (!extensions::image_util::ParseHexColorString(focus_ring.color, &color))
+    if (!extensions::image_util::ParseHexColorString(
+            focus_ring_info.color, &(focus_ring_ptr->color))) {
       return RespondNow(Error("Could not parse hex color"));
-    accessibility_manager->SetFocusRingColor(color, id);
+    }
 
-    // Move the visible focus ring to cover all of these rects.
-    accessibility_manager->SetFocusRing(
-        rects, ash::mojom::FocusRingBehavior::PERSIST_FOCUS_RING, id);
+    if (focus_ring_info.secondary_color) {
+      if (!extensions::image_util::ParseHexColorString(
+              *(focus_ring_info.secondary_color),
+              &(focus_ring_ptr->secondary_color))) {
+        return RespondNow(Error("Could not parse secondary hex color"));
+      }
+    }
 
-    // Also update the touch exploration controller so that synthesized
-    // touch events are anchored within the focused object.
+    switch (focus_ring_info.type) {
+      case accessibility_private::FOCUS_TYPE_SOLID:
+        focus_ring_ptr->type = ash::mojom::FocusRingType::SOLID;
+        break;
+      case accessibility_private::FOCUS_TYPE_DASHED:
+        focus_ring_ptr->type = ash::mojom::FocusRingType::DASHED;
+        break;
+      case accessibility_private::FOCUS_TYPE_GLOW:
+        focus_ring_ptr->type = ash::mojom::FocusRingType::GLOW;
+        break;
+      default:
+        NOTREACHED();
+    }
+
+    // Update the touch exploration controller so that synthesized touch events
+    // are anchored within the focused object.
     // NOTE: The final anchor point will be determined by the first rect of the
     // final focus ring.
-    if (!rects.empty()) {
+    if (!focus_ring_ptr->rects_in_screen.empty()) {
       accessibility_manager->SetTouchAccessibilityAnchorPoint(
-          rects[0].CenterPoint());
+          focus_ring_ptr->rects_in_screen[0].CenterPoint());
     }
+
+    // Set the focus ring.
+    accessibility_manager->SetFocusRing(id, std::move(focus_ring_ptr));
   }
 
   return RespondNow(NoArguments());
@@ -291,12 +316,6 @@
   EXTENSION_FUNCTION_VALIDATE(params);
   accessibility_private::SyntheticMouseEvent* mouse_data = &params->mouse_event;
 
-  // TODO(crbug/893752) Choose correct display
-  display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
-  int x = (int)(mouse_data->x * display.device_scale_factor());
-  int y = (int)(mouse_data->y * display.device_scale_factor());
-
-  gfx::Point location(x, y);
   ui::EventType type;
   switch (mouse_data->type) {
     case accessibility_private::SYNTHETIC_MOUSE_EVENT_TYPE_PRESS:
@@ -323,6 +342,10 @@
 
   int flags = ui::EF_LEFT_MOUSE_BUTTON;
 
+  // Locations are assumed to be display relative (and in DIPs).
+  // TODO(crbug/893752) Choose correct display
+  display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
+  gfx::Point location(mouse_data->x, mouse_data->y);
   std::unique_ptr<ui::MouseEvent> synthetic_mouse_event =
       std::make_unique<ui::MouseEvent>(type, location, location,
                                        ui::EventTimeForNow(), flags,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 0d2972b..8e9f6f8 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -124,6 +124,7 @@
     &kContextualSearchTapDisableOverride,
     &kContextualSearchUnityIntegration,
     &kCustomContextMenu,
+    &kDelegateOverscrollSwipes,
     &kDontPrefetchLibraries,
     &kDownloadProgressInfoBar,
     &kDownloadHomeV2,
@@ -346,6 +347,9 @@
 const base::Feature kDontPrefetchLibraries{"DontPrefetchLibraries",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kDelegateOverscrollSwipes{
+    "DelegateOverscrollSwipes", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kDownloadAutoResumptionThrottling{
     "DownloadAutoResumptionThrottling", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index 0a8cc45..51f7467 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -52,6 +52,7 @@
 extern const base::Feature kContextualSearchTapDisableOverride;
 extern const base::Feature kContextualSearchUnityIntegration;
 extern const base::Feature kCustomContextMenu;
+extern const base::Feature kDelegateOverscrollSwipes;
 extern const base::Feature kDontPrefetchLibraries;
 extern const base::Feature kDownloadAutoResumptionThrottling;
 extern const base::Feature kDownloadProgressInfoBar;
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.cc b/chrome/browser/android/vr/arcore_device/arcore_device.cc
index 2092cdcc..9e1ac6d 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.cc
@@ -184,6 +184,9 @@
                                            int render_frame_id,
                                            bool has_user_activation,
                                            bool success) {
+  DVLOG(3) << __func__ << ": has_user_activation=" << has_user_activation
+           << ", success=" << success;
+
   if (!success) {
     CallDeferredRequestSessionCallbacks(/*success=*/false);
     return;
@@ -276,23 +279,27 @@
     // The call may request another session, which should be handled right here
     // in this loop as well.
 
-    auto callback =
-        base::BindOnce(&ArCoreDevice::OnCreateSessionCallback, GetWeakPtr());
+    if (!success) {
+      std::move(deferred_callback).Run(nullptr, nullptr);
+      continue;
+    }
 
-    PostTaskToGlThread(
-        base::BindOnce(&ArCoreGl::CreateSession,
-                       arcore_gl_thread_->GetArCoreGl()->GetWeakPtr(),
-                       display_info_->Clone(), std::move(deferred_callback),
-                       CreateMainThreadCallback(std::move(callback))));
+    auto callback = base::BindOnce(&ArCoreDevice::OnCreateSessionCallback,
+                                   GetWeakPtr(), std::move(deferred_callback));
+
+    PostTaskToGlThread(base::BindOnce(
+        &ArCoreGl::CreateSession,
+        arcore_gl_thread_->GetArCoreGl()->GetWeakPtr(), display_info_->Clone(),
+        CreateMainThreadCallback(std::move(callback))));
   }
   deferred_request_session_callbacks_.clear();
 }
 
 void ArCoreDevice::OnCreateSessionCallback(
+    mojom::XRRuntime::RequestSessionCallback deferred_callback,
     mojom::XRFrameDataProviderPtrInfo frame_data_provider_info,
     mojom::VRDisplayInfoPtr display_info,
-    mojom::XRSessionControllerPtrInfo session_controller_info,
-    mojom::XRRuntime::RequestSessionCallback deferred_callback) {
+    mojom::XRSessionControllerPtrInfo session_controller_info) {
   DCHECK(IsOnMainThread());
 
   mojom::XRSessionPtr session = mojom::XRSession::New();
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.h b/chrome/browser/android/vr/arcore_device/arcore_device.h
index 8d517a0..f62d33a1 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.h
@@ -102,10 +102,10 @@
   void OnArCoreGlInitializationComplete(bool success);
 
   void OnCreateSessionCallback(
+      mojom::XRRuntime::RequestSessionCallback deferred_callback,
       mojom::XRFrameDataProviderPtrInfo frame_data_provider_info,
       mojom::VRDisplayInfoPtr display_info,
-      mojom::XRSessionControllerPtrInfo session_controller_info,
-      mojom::XRRuntime::RequestSessionCallback deferred_callback);
+      mojom::XRSessionControllerPtrInfo session_controller_info);
 
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
   std::unique_ptr<ArCoreFactory> arcore_factory_;
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.cc b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
index 0036d66..73cc212 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
@@ -151,10 +151,8 @@
   std::move(callback).Run(true);
 }
 
-void ArCoreGl::CreateSession(
-    mojom::VRDisplayInfoPtr display_info,
-    mojom::XRRuntime::RequestSessionCallback deferred_callback,
-    ArCoreGlCreateSessionCallback callback) {
+void ArCoreGl::CreateSession(mojom::VRDisplayInfoPtr display_info,
+                             ArCoreGlCreateSessionCallback callback) {
   DVLOG(3) << __func__;
 
   DCHECK(IsOnGlThread());
@@ -173,8 +171,7 @@
       &ArCoreGl::OnBindingDisconnect, weak_ptr_factory_.GetWeakPtr()));
 
   std::move(callback).Run(std::move(frame_data_provider_info),
-                          std::move(display_info), std::move(controller_info),
-                          std::move(deferred_callback));
+                          std::move(display_info), std::move(controller_info));
 }
 
 bool ArCoreGl::InitializeGl() {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.h b/chrome/browser/android/vr/arcore_device/arcore_gl.h
index be502556..ecac0074 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.h
@@ -44,8 +44,7 @@
 using ArCoreGlCreateSessionCallback = base::OnceCallback<void(
     mojom::XRFrameDataProviderPtrInfo frame_data_provider_info,
     mojom::VRDisplayInfoPtr display_info,
-    mojom::XRSessionControllerPtrInfo session_controller_info,
-    mojom::XRRuntime::RequestSessionCallback deferred_callback)>;
+    mojom::XRSessionControllerPtrInfo session_controller_info)>;
 
 // All of this class's methods must be called on the same valid GL thread with
 // the exception of GetGlThreadTaskRunner() and GetWeakPtr().
@@ -61,7 +60,6 @@
                   base::OnceCallback<void(bool)> callback);
 
   void CreateSession(mojom::VRDisplayInfoPtr display_info,
-                     mojom::XRRuntime::RequestSessionCallback deferred_callback,
                      ArCoreGlCreateSessionCallback callback);
 
   const scoped_refptr<base::SingleThreadTaskRunner>& GetGlThreadTaskRunner() {
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc
index f312412..4bc5834 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -38,6 +38,10 @@
   extensions::ChromeAppIcon::ResizeFunction resize_function;
 #if defined(OS_CHROMEOS)
   if (icon_effects & apps::IconEffects::kResizeAndPad) {
+    // TODO(crbug.com/826982): khmel@ notes that MD post-processing is not
+    // always applied: "See legacy code:
+    // https://cs.chromium.org/search/?q=ChromeAppIconLoader&type=cs In one
+    // cases MD design is used in another not."
     resize_function =
         base::BindRepeating(&app_list::MaybeResizeAndPadIconForMd);
   }
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc
index 97388681..3e0f489 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -79,6 +79,13 @@
   if (app_service_.is_bound() && !icon_key.is_null()) {
     // TODO(crbug.com/826982): implement another IconLoader that coalesces
     // multiple in-flight calls with the same IconLoader::Key, and use it here.
+    //
+    // Possibly related to that, Mojo doesn't guarantee the order of messages,
+    // so multiple calls to this method might not resolve their callbacks in
+    // order. As per khmel@, "you may have race here, assume you publish change
+    // for the app and app requested new icon. But new icon is not delivered
+    // yet and you resolve old one instead. Now new icon arrives asynchronously
+    // but you no longer notify the app or do?"
     app_service_->LoadIcon(std::move(icon_key), icon_compression,
                            size_hint_in_dip, allow_placeholder_icon,
                            std::move(callback));
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index b79ac919..cf969497 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -31,6 +31,28 @@
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/size.h"
 
+// TODO(crbug.com/826982): investigate re-using the ArcAppIcon class directly.
+// This may or may not be difficult: see
+// (https://chromium-review.googlesource.com/c/chromium/src/+/1482350/7#message-b45fa253ea01b523e8389b30d74ce805b0e05f77)
+// and
+// (https://chromium-review.googlesource.com/c/chromium/src/+/1482350/7#message-52080b7d348d7806c818aa395392ff1385d1784e).
+
+// TODO(crbug.com/826982): consider that, per khmel@, "App icon can be
+// overwritten (setTaskDescription) or by assigning the icon for the app
+// window. In this case some consumers (Shelf for example) switch to
+// overwritten icon... IIRC this applies to shelf items and ArcAppWindow icon".
+
+// TODO(crbug.com/826982): consider that, per khmel@, "We may change the way
+// how we handle icons in ARC++ container. That means view of the icon can be
+// changed. We support invalidation of icon scales way, similar to the case
+// above... We have methods to notify about new icon arrival. IIRC ArcAppIcon
+// already handles this".
+
+// TODO(crbug.com/826982): consider that, per khmel@, "Functionality to detect
+// icons cannot be decoded correctly and issue request to refresh the icon
+// scale from ARC++ container... The logic here is wider. We request new copy
+// of icon in this case".
+
 namespace {
 
 // ArcApps::LoadIcon (via ArcApps::LoadIconFromVM) runs a series of callbacks,
@@ -81,6 +103,11 @@
                std::string icon_resource_id,
                apps::mojom::Publisher::LoadIconCallback callback,
                apps::ArcApps::AppConnectionHolder* app_connection_holder) {
+  // TODO(crbug.com/826982): consider that, per khmel@, "Regardless the number
+  // of request for the same icon scale it should be only one and only one
+  // request to ARC++ container to extract the real data. This logic is
+  // isolated inside ArcAppListPrefs and I don't think that anybody else should
+  // call mojom RequestAppIcon".
   if (icon_resource_id.empty()) {
     auto* app_instance =
         ARC_GET_INSTANCE_FOR_METHOD(app_connection_holder, RequestAppIcon);
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc
index b85daf2..c8fbb481 100644
--- a/chrome/browser/apps/app_service/extension_apps.cc
+++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -42,6 +42,11 @@
 // TODO(crbug.com/826982): do we also need to watch prefs, the same as
 // ExtensionAppModelBuilder?
 
+// TODO(crbug.com/826982): consider that, per khmel@, "in some places Chrome
+// apps is not used and raw extension app without any effect is displayed...
+// Search where ChromeAppIcon or ChromeAppIconLoader is used compared with
+// direct loading the ExtensionIcon".
+
 namespace {
 
 // Only supporting important permissions for now.
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index f3f6e537..dea1a92c1 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -2216,36 +2216,6 @@
                         {ObservedUiEvents::kPreviewFormData});
 }
 
-// Test that dynamic forms don't get filled when the feature is disabled.
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DynamicChangingFormFill) {
-  // Explicitly disable the filling of dynamic forms.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndDisableFeature(features::kAutofillDynamicForms);
-
-  CreateTestProfile();
-
-  GURL url =
-      embedded_test_server()->GetURL("/autofill/dynamic_form_disabled.html");
-  ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
-
-  TriggerFormFill("firstname");
-
-  // Wait for the re-fill to happen.
-  bool has_refilled = false;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      GetWebContents(), "hasRefilled()", &has_refilled));
-  ASSERT_FALSE(has_refilled);
-
-  // Make sure that the new form was not filled.
-  ExpectFieldValue("firstname_form1", "");
-  ExpectFieldValue("address_form1", "");
-  ExpectFieldValue("state_form1", "CA");  // Default value.
-  ExpectFieldValue("city_form1", "");
-  ExpectFieldValue("company_form1", "");
-  ExpectFieldValue("email_form1", "");
-  ExpectFieldValue("phone_form1", "");
-}
-
 // Test that a page with 2 forms with no name and id containing fields with no
 // name or if get filled properly.
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
@@ -2310,8 +2280,6 @@
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                        Dynamic_MultipleNoNameForms_BadNames_FourthForm) {
   CreateTestProfile();
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kAutofillDynamicForms);
 
   GURL url = embedded_test_server()->GetURL(
       "a.com", "/autofill/multiple_noname_forms_badnames.html");
@@ -2338,8 +2306,6 @@
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                        Dynamic_MultipleNoNameForms_BadNames_ThirdForm) {
   CreateTestProfile();
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kAutofillDynamicForms);
 
   GURL url = embedded_test_server()->GetURL(
       "a.com", "/autofill/multiple_noname_forms_badnames.html");
@@ -2366,8 +2332,6 @@
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                        Dynamic_MultipleNoNameForms_BadNames_SecondForm) {
   CreateTestProfile();
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kAutofillDynamicForms);
 
   GURL url = embedded_test_server()->GetURL(
       "a.com", "/autofill/multiple_noname_forms_badnames.html");
@@ -2391,8 +2355,6 @@
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                        Dynamic_MultipleNoNameForms_BadNames_FirstForm) {
   CreateTestProfile();
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kAutofillDynamicForms);
 
   GURL url = embedded_test_server()->GetURL(
       "a.com", "/autofill/multiple_noname_forms_badnames.html");
@@ -2851,12 +2813,6 @@
       disabled_features.push_back(features::kAutofillEnableCompanyName);
     }
 
-    // Explicitly enable the filling of dynamic forms and disabled the
-    // requirement for a secure context to fill credit cards.
-    enabled_features.push_back(features::kAutofillDynamicForms);
-    disabled_features.push_back(
-        features::kAutofillRestrictUnownedFieldsToFormlessCheckout);
-
     scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
     AutofillInteractiveTestBase::SetUp();
   }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 1204d01..6e16b1c 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -196,7 +196,7 @@
         <include name="IDR_EOC_INTERNALS_HTML" file="resources\eoc_internals\eoc_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
         <include name="IDR_EOC_INTERNALS_CSS" file="resources\eoc_internals\eoc_internals.css" compress="gzip" type="BINDATA" />
         <include name="IDR_EOC_INTERNALS_JS" file="resources\eoc_internals\eoc_internals.js" compress="gzip" type="BINDATA" />
-        <include name="IDR_EOC_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\eoc_internals\eoc_internals.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+        <include name="IDR_EOC_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\eoc_internals\eoc_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
         <include name="IDR_EXPLORE_SITES_INTERNALS_HTML" file="resources\explore_sites_internals\explore_sites_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
         <include name="IDR_EXPLORE_SITES_INTERNALS_CSS" file="resources\explore_sites_internals\explore_sites_internals.css" compress="gzip" type="BINDATA" />
         <include name="IDR_EXPLORE_SITES_INTERNALS_JS" file="resources\explore_sites_internals\explore_sites_internals.js" compress="gzip" type="BINDATA" />
@@ -212,7 +212,7 @@
         <include name="IDR_SNIPPETS_INTERNALS_HTML" file="resources\snippets_internals\snippets_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
         <include name="IDR_SNIPPETS_INTERNALS_CSS" file="resources\snippets_internals\snippets_internals.css" compress="gzip" type="BINDATA" />
         <include name="IDR_SNIPPETS_INTERNALS_JS" file="resources\snippets_internals\snippets_internals.js" compress="gzip" type="BINDATA" />
-        <include name="IDR_SNIPPETS_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\snippets_internals\snippets_internals.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+        <include name="IDR_SNIPPETS_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\snippets_internals\snippets_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
       </if>
       <include name="IDR_SUPERVISED_USER_INTERNALS_HTML" file="resources\supervised_user_internals\supervised_user_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
       <include name="IDR_SUPERVISED_USER_INTERNALS_CSS" file="resources\supervised_user_internals\supervised_user_internals.css" compress="gzip" type="BINDATA" />
@@ -725,7 +725,7 @@
       <if expr="safe_browsing_mode == 1">
         <include name="IDR_RESET_PASSWORD_HTML" file="resources\reset_password\reset_password.html" type="BINDATA" compress="gzip" />
         <include name="IDR_RESET_PASSWORD_JS" file="resources\reset_password\reset_password.js" type="BINDATA" compress="gzip" />
-        <include name="IDR_RESET_PASSWORD_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\reset_password\reset_password.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+        <include name="IDR_RESET_PASSWORD_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\reset_password\reset_password.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
       </if>
       <if expr="not is_android">
         <include name="IDR_TAB_RANKER_EXAMPLE_PREPROCESSOR_CONFIG_PB" file="resource_coordinator\tab_ranker\example_preprocessor_config.pb" type="BINDATA" />
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 831151a..f19356a1a 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -1489,21 +1489,11 @@
   focus_ring_names_for_extension_id_.erase(extension_id);
 }
 
-void AccessibilityManager::SetFocusRingColor(SkColor color,
-                                             std::string focus_ring_id) {
-  accessibility_focus_ring_controller_->SetFocusRingColor(color, focus_ring_id);
-}
+void AccessibilityManager::SetFocusRing(std::string focus_ring_id,
+                                        ash::mojom::FocusRingPtr focus_ring) {
+  accessibility_focus_ring_controller_->SetFocusRing(focus_ring_id,
+                                                     std::move(focus_ring));
 
-void AccessibilityManager::ResetFocusRingColor(std::string focus_ring_id) {
-  accessibility_focus_ring_controller_->ResetFocusRingColor(focus_ring_id);
-}
-
-void AccessibilityManager::SetFocusRing(
-    const std::vector<gfx::Rect>& rects_in_screen,
-    ash::mojom::FocusRingBehavior focus_ring_behavior,
-    std::string focus_ring_id) {
-  accessibility_focus_ring_controller_->SetFocusRing(
-      rects_in_screen, focus_ring_behavior, focus_ring_id);
   if (focus_ring_observer_for_test_)
     focus_ring_observer_for_test_.Run();
 }
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 591839c18..525bf0e 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -289,18 +289,9 @@
   // Starts or stops dictation (type what you speak).
   bool ToggleDictation();
 
-  // Sets the focus ring color.
-  void SetFocusRingColor(SkColor color, std::string caller_id);
-
-  // Resets the focus ring color back to the default.
-  void ResetFocusRingColor(std::string caller_id);
-
-  // Draws a focus ring around the given set of rects in screen coordinates. Use
-  // |focus_ring_behavior| to specify whether the focus ring should persist or
-  // fade out.
-  void SetFocusRing(const std::vector<gfx::Rect>& rects_in_screen,
-                    ash::mojom::FocusRingBehavior focus_ring_behavior,
-                    std::string caller_id);
+  // Sets the focus ring with the given ID based on |focus_ring|.
+  void SetFocusRing(std::string focus_ring_id,
+                    ash::mojom::FocusRingPtr focus_ring);
 
   // Hides focus ring on screen.
   void HideFocusRing(std::string caller_id);
diff --git a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc
index d59c8f8..048efda 100644
--- a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc
+++ b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc
@@ -32,20 +32,12 @@
           ash::mojom::AccessibilityFocusRingController::Name_);
 }
 
-void TestAccessibilityFocusRingController::SetFocusRingColor(
-    uint32_t skcolor,
-    const std::string& caller_id) {}
-
-void TestAccessibilityFocusRingController::ResetFocusRingColor(
-    const std::string& caller_id) {}
-
 void TestAccessibilityFocusRingController::SetFocusRing(
-    const std::vector<gfx::Rect>& rects_in_screen,
-    ash::mojom::FocusRingBehavior focus_ring_behavior,
-    const std::string& caller_id) {}
+    const std::string& focus_ring_id,
+    ash::mojom::FocusRingPtr focus_ring) {}
 
 void TestAccessibilityFocusRingController::HideFocusRing(
-    const std::string& caller_id) {}
+    const std::string& focus_ring_id) {}
 
 void TestAccessibilityFocusRingController::SetHighlights(
     const std::vector<gfx::Rect>& rects_in_screen,
@@ -58,9 +50,4 @@
   binding_.Bind(
       ash::mojom::AccessibilityFocusRingControllerRequest(std::move(handle)));
 }
-void TestAccessibilityFocusRingController::EnableDoubleFocusRing(
-    uint32_t skcolor,
-    const std::string& caller_id) {}
 
-void TestAccessibilityFocusRingController::DisableDoubleFocusRing(
-    const std::string& caller_id) {}
diff --git a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h
index 173b7f2a..9908beb 100644
--- a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h
+++ b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h
@@ -26,19 +26,12 @@
   ~TestAccessibilityFocusRingController() override;
 
   // ash::mojom::AccessibilityFocusRingController:
-  void SetFocusRingColor(uint32_t skcolor,
-                         const std::string& caller_id) override;
-  void ResetFocusRingColor(const std::string& caller_id) override;
-  void SetFocusRing(const std::vector<gfx::Rect>& rects_in_screen,
-                    ash::mojom::FocusRingBehavior focus_ring_behavior,
-                    const std::string& caller_id) override;
-  void HideFocusRing(const std::string& caller_id) override;
+  void SetFocusRing(const std::string& focus_ring_id,
+                    ash::mojom::FocusRingPtr focus_ring) override;
+  void HideFocusRing(const std::string& focus_ring_id) override;
   void SetHighlights(const std::vector<gfx::Rect>& rects_in_screen,
                      uint32_t skcolor) override;
   void HideHighlights() override;
-  void EnableDoubleFocusRing(uint32_t skcolor,
-                             const std::string& caller_id) override;
-  void DisableDoubleFocusRing(const std::string& caller_id) override;
 
  private:
   void Bind(mojo::ScopedMessagePipeHandle handle);
diff --git a/chrome/browser/chromeos/account_manager/account_manager_migrator.cc b/chrome/browser/chromeos/account_manager/account_manager_migrator.cc
index 0c9a02f..1121c15 100644
--- a/chrome/browser/chromeos/account_manager/account_manager_migrator.cc
+++ b/chrome/browser/chromeos/account_manager/account_manager_migrator.cc
@@ -32,6 +32,7 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/components/account_manager/account_manager.h"
 #include "chromeos/components/account_manager/account_manager_factory.h"
+#include "chromeos/constants/chromeos_pref_names.h"
 #include "components/account_id/account_id.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/prefs/pref_service.h"
@@ -440,9 +441,9 @@
 
   void Run() override {
     const int num_times_ran_successfully = pref_service_->GetInteger(
-        prefs::kAccountManagerNumTimesMigrationRanSuccessfully);
+        ::prefs::kAccountManagerNumTimesMigrationRanSuccessfully);
     pref_service_->SetInteger(
-        prefs::kAccountManagerNumTimesMigrationRanSuccessfully,
+        ::prefs::kAccountManagerNumTimesMigrationRanSuccessfully,
         num_times_ran_successfully + 1);
     FinishWithSuccess();
   }
@@ -493,7 +494,7 @@
   // Do not unnecessarily run migrations if they have been successfully run
   // before.
   if (profile_->GetPrefs()->GetInteger(
-          prefs::kAccountManagerNumTimesMigrationRanSuccessfully) >=
+          ::prefs::kAccountManagerNumTimesMigrationRanSuccessfully) >=
       kMaxMigrationRuns) {
     VLOG(1) << "Skipping migrations because of previous successful runs";
     return false;
@@ -523,20 +524,27 @@
       GetDeviceAccount(profile_), account_manager, identity_manager,
       WebDataServiceFactory::GetTokenWebDataForProfile(
           profile_, ServiceAccessType::EXPLICIT_ACCESS) /* token_web_data */));
-  migration_runner_.AddStep(std::make_unique<ContentAreaAccountsMigration>(
-      account_manager, identity_manager));
 
-  if (arc::IsArcProvisioned(profile_)) {
-    // Add a migration step for ARC only if ARC has been provisioned. If ARC has
-    // not been provisioned yet, there cannot be any accounts that need to be
-    // migrated.
-    migration_runner_.AddStep(std::make_unique<ArcAccountsMigration>(
-        account_manager, identity_manager,
-        arc::ArcAuthService::GetForBrowserContext(
-            profile_) /* arc_auth_service */));
-  } else {
-    VLOG(1) << "Skipping migration of ARC accounts. ARC has not been "
-               "provisioned yet";
+  const bool is_secondary_google_account_signin_allowed =
+      profile_->GetPrefs()->GetBoolean(
+          chromeos::prefs::kSecondaryGoogleAccountSigninAllowed);
+
+  if (is_secondary_google_account_signin_allowed) {
+    migration_runner_.AddStep(std::make_unique<ContentAreaAccountsMigration>(
+        account_manager, identity_manager));
+
+    if (arc::IsArcProvisioned(profile_)) {
+      // Add a migration step for ARC only if ARC has been provisioned. If ARC
+      // has not been provisioned yet, there cannot be any accounts that need to
+      // be migrated.
+      migration_runner_.AddStep(std::make_unique<ArcAccountsMigration>(
+          account_manager, identity_manager,
+          arc::ArcAuthService::GetForBrowserContext(
+              profile_) /* arc_auth_service */));
+    } else {
+      VLOG(1) << "Skipping migration of ARC accounts. ARC has not been "
+                 "provisioned yet";
+    }
   }
 
   // This MUST be the last step. Check the class level documentation of
diff --git a/chrome/browser/chromeos/assistant/assistant_util.cc b/chrome/browser/chromeos/assistant/assistant_util.cc
index 12a59b63..f9b2fdc 100644
--- a/chrome/browser/chromeos/assistant/assistant_util.cc
+++ b/chrome/browser/chromeos/assistant/assistant_util.cc
@@ -69,7 +69,11 @@
       return ash::mojom::AssistantAllowedState::DISALLOWED_BY_LOCALE;
   }
 
-  if (!ui::DeviceUsesKeyboardLayout2()) {
+  // Bypass the account type check when using fake gaia login, e.g. in Tast
+  // tests, or the account is logged in a device with a physical Assistant key
+  // on keyboard.
+  if (!chromeos::switches::IsGaiaServicesDisabled() &&
+      !ui::DeviceUsesKeyboardLayout2()) {
     // Only enable non-dasher accounts for devices without physical key.
     bool account_supported = false;
     auto* identity_manager =
diff --git a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.cc b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.cc
index 47b53400..18b3a15 100644
--- a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.cc
@@ -160,7 +160,8 @@
                     CHANGE_TYPE_ADD_OR_UPDATE);
     }
     for (auto& event : events) {
-      DispatchOnDirectoryChangedEventToExtension(extension_id, event.second);
+      DispatchOnDirectoryChangedEventToExtension(extension_id, event.first,
+                                                 event.second);
     }
   }
 }
@@ -204,7 +205,11 @@
 
 void DriveFsEventRouter::DispatchOnDirectoryChangedEventToExtension(
     const std::string& extension_id,
+    const base::FilePath& directory,
     const extensions::api::file_manager_private::FileWatchEvent& event) {
+  if (!IsPathWatched(directory)) {
+    return;
+  }
   DispatchEventToExtension(
       extension_id,
       extensions::events::FILE_MANAGER_PRIVATE_ON_DIRECTORY_CHANGED,
diff --git a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h
index 5c3f0b8c5..3f35624 100644
--- a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h
@@ -59,12 +59,15 @@
 
   virtual std::string GetDriveFileSystemName() = 0;
 
+  virtual bool IsPathWatched(const base::FilePath& path) = 0;
+
   void DispatchOnFileTransfersUpdatedEventToExtension(
       const std::string& extension_id,
       const extensions::api::file_manager_private::FileTransferStatus& status);
 
   void DispatchOnDirectoryChangedEventToExtension(
       const std::string& extension_id,
+      const base::FilePath& directory,
       const extensions::api::file_manager_private::FileWatchEvent& event);
 
   // Helper method for dispatching an event to an extension.
diff --git a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc
index b9c5f81..25bd751 100644
--- a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc
@@ -68,7 +68,9 @@
 
 class TestDriveFsEventRouter : public DriveFsEventRouter {
  public:
-  TestDriveFsEventRouter() = default;
+  TestDriveFsEventRouter() {
+    ON_CALL(*this, IsPathWatched).WillByDefault(testing::Return(true));
+  }
 
   void DispatchEventToExtension(
       const std::string& extension_id,
@@ -82,6 +84,7 @@
                void(const std::string& extension_id,
                     const std::string& name,
                     const base::ListValue& event));
+  MOCK_METHOD1(IsPathWatched, bool(const base::FilePath&));
 
   GURL ConvertDrivePathToFileSystemUrl(
       const base::FilePath& file_path,
@@ -529,6 +532,10 @@
         file_manager_private::CHANGE_TYPE_ADD_OR_UPDATE);
   }
 
+  EXPECT_CALL(mock(), IsPathWatched(base::FilePath("/root")))
+      .WillOnce(testing::Return(true));
+  EXPECT_CALL(mock(), IsPathWatched(base::FilePath("/other")))
+      .WillOnce(testing::Return(false));
   EXPECT_CALL(mock(),
               DispatchEventToExtensionImpl(
                   "ext", file_manager_private::OnDirectoryChanged::kEventName,
@@ -541,6 +548,8 @@
                        drivefs::mojom::FileChange::Type::kCreate);
   changes.emplace_back(base::FilePath("/root/c"),
                        drivefs::mojom::FileChange::Type::kModify);
+  changes.emplace_back(base::FilePath("/other/a"),
+                       drivefs::mojom::FileChange::Type::kModify);
   observer().OnFilesChanged(changes);
 }
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index c03e638a..2d9f484 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -391,7 +391,11 @@
 
 class DriveFsEventRouterImpl : public DriveFsEventRouter {
  public:
-  explicit DriveFsEventRouterImpl(Profile* profile) : profile_(profile) {}
+  DriveFsEventRouterImpl(
+      Profile* profile,
+      const std::map<base::FilePath, std::unique_ptr<FileWatcher>>*
+          file_watchers)
+      : profile_(profile), file_watchers_(file_watchers) {}
 
  private:
   std::set<std::string> GetEventListenerExtensionIds(
@@ -420,6 +424,14 @@
         .value();
   }
 
+  bool IsPathWatched(const base::FilePath& path) override {
+    base::FilePath absolute_path =
+        DriveIntegrationServiceFactory::FindForProfile(profile_)
+            ->GetMountPointPath();
+    return base::FilePath("/").AppendRelativePath(path, &absolute_path) &&
+           base::ContainsKey(*file_watchers_, absolute_path);
+  }
+
   void DispatchEventToExtension(
       const std::string& extension_id,
       extensions::events::HistogramValue histogram_value,
@@ -431,6 +443,8 @@
   }
 
   Profile* const profile_;
+  const std::map<base::FilePath, std::unique_ptr<FileWatcher>>* const
+      file_watchers_;
 
   DISALLOW_COPY_AND_ASSIGN(DriveFsEventRouterImpl);
 };
@@ -442,7 +456,8 @@
       profile_(profile),
       device_event_router_(std::make_unique<DeviceEventRouterImpl>(profile)),
       job_event_router_(std::make_unique<JobEventRouterImpl>(profile)),
-      drivefs_event_router_(std::make_unique<DriveFsEventRouterImpl>(profile)),
+      drivefs_event_router_(
+          std::make_unique<DriveFsEventRouterImpl>(profile, &file_watchers_)),
       dispatch_directory_change_event_impl_(
           base::Bind(&EventRouter::DispatchDirectoryChangeEventImpl,
                      base::Unretained(this))),
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index c1eba732..22e13b7 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -864,7 +864,9 @@
             .WithBrowser()
             .Offline()
             .EnableDriveFs(),
-        TestCase("saveFileDialogDriveOfflinePinned").WithBrowser().Offline()));
+        TestCase("saveFileDialogDriveOfflinePinned").WithBrowser().Offline(),
+        TestCase("openFileDialogDefaultFilter").WithBrowser(),
+        TestCase("saveFileDialogDefaultFilter").WithBrowser()));
 
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
     CopyBetweenWindows, /* copy_between_windows.js */
diff --git a/chrome/browser/chromeos/login/OWNERS b/chrome/browser/chromeos/login/OWNERS
index 73d229a..c801b775 100644
--- a/chrome/browser/chromeos/login/OWNERS
+++ b/chrome/browser/chromeos/login/OWNERS
@@ -1,4 +1,5 @@
 achuith@chromium.org
 alemate@chromium.org
 jdufault@chromium.org
+tbarzic@chromium.org
 xiyuan@chromium.org
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.cc b/chrome/browser/chromeos/login/screens/user_image_screen.cc
index 4e35bad0..a40adfe 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.cc
@@ -65,12 +65,6 @@
 
 }  // namespace
 
-// static
-UserImageScreen* UserImageScreen::Get(ScreenManager* manager) {
-  return static_cast<UserImageScreen*>(
-      manager->GetScreen(OobeScreen::SCREEN_USER_IMAGE_PICKER));
-}
-
 UserImageScreen::UserImageScreen(UserImageView* view)
     : BaseScreen(OobeScreen::SCREEN_USER_IMAGE_PICKER), view_(view) {
   if (view_)
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.h b/chrome/browser/chromeos/login/screens/user_image_screen.h
index af376f5..de1b17d6 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.h
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.h
@@ -28,7 +28,6 @@
 
 namespace chromeos {
 
-class ScreenManager;
 class UserImageManager;
 class UserImageView;
 
@@ -38,8 +37,6 @@
                         public user_manager::UserManager::Observer,
                         public UserImageSyncObserver::Observer {
  public:
-  static UserImageScreen* Get(ScreenManager* manager);
-
   explicit UserImageScreen(UserImageView* view);
   ~UserImageScreen() override;
 
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc b/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc
index ecf913a..d44596f 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc
@@ -6,11 +6,9 @@
 
 #include "base/bind.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/login/screens/user_image_screen.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/default_user_image/default_user_images.h"
-#include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/common/pref_names.h"
@@ -100,7 +98,7 @@
   bool local_image_updated = false;
   if (!GetSyncedImageIndex(&synced_index) || local_image_changed_) {
     UpdateSyncedImageFromLocal();
-  } else if (IsIndexSupported(synced_index) && CanUpdateLocalImageNow()) {
+  } else if (IsIndexSupported(synced_index)) {
     UpdateLocalImageFromSynced();
     local_image_updated = true;
   }
@@ -114,7 +112,7 @@
     is_synced_ = true;
     prefs_->RemoveObserver(this);
     OnInitialSync();
-  } else if (CanUpdateLocalImageNow()) {
+  } else {
     UpdateLocalImageFromSynced();
   }
 }
@@ -184,17 +182,4 @@
   return dict && dict->GetInteger(kImageIndex, index);
 }
 
-bool UserImageSyncObserver::CanUpdateLocalImageNow() {
-  if (WizardController* wizard_controller =
-          WizardController::default_controller()) {
-    UserImageScreen* screen =
-        UserImageScreen::Get(wizard_controller->screen_manager());
-    if (wizard_controller->current_screen() == screen) {
-      if (screen->user_selected_image())
-        return false;
-    }
-  }
-  return true;
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h b/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h
index d856fae..3ead53b2 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h
@@ -96,9 +96,6 @@
   // Gets synced image index. Returns false if user has no needed preferences.
   bool GetSyncedImageIndex(int* result);
 
-  // If it is allowed to change user image now.
-  bool CanUpdateLocalImageNow();
-
   const user_manager::User* user_;
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
   std::unique_ptr<content::NotificationRegistrar> notification_registrar_;
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc
index 25de150..010f951 100644
--- a/chrome/browser/download/download_target_determiner.cc
+++ b/chrome/browser/download/download_target_determiner.cc
@@ -219,7 +219,12 @@
     return CONTINUE;
   }
 
-  if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) {
+  bool no_prompt_needed = HasPromptedForPath();
+#if defined(OS_ANDROID)
+  // If |virtual_path_| is content URI, there is no need to prompt the user.
+  no_prompt_needed |= virtual_path_.IsContentUri();
+#endif
+  if (!virtual_path_.empty() && no_prompt_needed && !is_forced_path) {
     // The download is being resumed and the user has already been prompted for
     // a path. Assume that it's okay to overwrite the file if there's a conflict
     // and reuse the selection.
@@ -806,6 +811,16 @@
 
   next_state_ = STATE_NONE;
 
+#if defined(OS_ANDROID)
+  // If the local path is a content URI, the download should be from resumption
+  // and we can just use the current path.
+  if (local_path_.IsContentUri()) {
+    DCHECK(is_resumption_);
+    intermediate_path_ = local_path_;
+    return COMPLETE;
+  }
+#endif
+
   // Note that the intermediate filename is always uniquified (i.e. if a file by
   // the same name exists, it is never overwritten). Therefore the code below
   // does not attempt to find a name that doesn't conflict with an existing
diff --git a/chrome/browser/feature_engagement/session_duration_updater.cc b/chrome/browser/feature_engagement/session_duration_updater.cc
index d023ad3..2e57ffb 100644
--- a/chrome/browser/feature_engagement/session_duration_updater.cc
+++ b/chrome/browser/feature_engagement/session_duration_updater.cc
@@ -40,9 +40,8 @@
 base::TimeDelta SessionDurationUpdater::GetRecordedObservedSessionTime() const {
   const base::DictionaryValue* dict =
       pref_service_->GetDictionary(prefs::kObservedSessionTime);
-  const base::Value* dict_value =
-      dict->FindKey(observed_session_time_dict_key_);
-  const double stored_value = dict_value ? dict_value->GetDouble() : 0L;
+  const double stored_value =
+      dict->FindDoubleKey(observed_session_time_dict_key_).value_or(0);
   return base::TimeDelta::FromSeconds(stored_value);
 }
 
@@ -85,9 +84,8 @@
 
   const base::DictionaryValue* dict =
       pref_service_->GetDictionary(prefs::kObservedSessionTime);
-  const base::Value* dict_value =
-      dict->FindKey(observed_session_time_dict_key_);
-  const double stored_value = dict_value ? dict_value->GetDouble() : 0L;
+  const double stored_value =
+      dict->FindDoubleKey(observed_session_time_dict_key_).value_or(0);
 
   base::TimeDelta elapsed_session_time =
       base::TimeDelta::FromSeconds(stored_value) + elapsed;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c2ba21a..84e5a4ce 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -494,6 +494,11 @@
     "expiry_milestone": 88
   },
   {
+    "name": "delegate-overscroll-swipes",
+    // "owners": [ "your-team" ],
+    "expiry_milestone": 88
+  },
+  {
     "name": "device-discovery-notifications",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 2ef81960..15365bf 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -76,6 +76,11 @@
     "Allow Chrome to offer to generate passwords when it detects account "
     "creation pages.";
 
+const char kDelegateOverscrollSwipesName[] =
+    "Delegate overscroll swipes to websites";
+const char kDelegateOverscrollSwipesDescription[] =
+    "Delegate overscroll swipes to websites first";
+
 const char kEnableBlinkHeapUnifiedGarbageCollectionName[] =
     "Blink Heap Unified Garbage Collection";
 const char kEnableBlinkHeapUnifiedGarbageCollectionDescription[] =
@@ -105,10 +110,6 @@
     "When enabled, autofill will cache the responses it receives from the "
     "crowd-sourced field type prediction server.";
 
-const char kAutofillDynamicFormsName[] = "Autofill Dynamic Forms";
-const char kAutofillDynamicFormsDescription[] =
-    "Allows autofill to fill dynamically changing forms";
-
 const char kAutofillEnableCompanyNameName[] =
     "Enable Autofill Company Name field";
 const char kAutofillEnableCompanyNameDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 780849d..6657f67 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -93,9 +93,6 @@
 extern const char kAutofillCacheQueryResponsesName[];
 extern const char kAutofillCacheQueryResponsesDescription[];
 
-extern const char kAutofillDynamicFormsName[];
-extern const char kAutofillDynamicFormsDescription[];
-
 extern const char kAutofillEnableCompanyNameName[];
 extern const char kAutofillEnableCompanyNameDescription[];
 
@@ -172,6 +169,9 @@
 extern const char kCloudPrinterHandlerName[];
 extern const char kCloudPrinterHandlerDescription[];
 
+extern const char kDelegateOverscrollSwipesName[];
+extern const char kDelegateOverscrollSwipesDescription[];
+
 extern const char kExperimentalAccessibilityFeaturesName[];
 extern const char kExperimentalAccessibilityFeaturesDescription[];
 
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
index cfdb3b1..106b351 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -584,8 +584,9 @@
 #define MAYBE_FetchAndEmitMetricsWithHostedApps \
   DISABLED_FetchAndEmitMetricsWithHostedApps
 #else
+// TODO(crbug.com/943207): Re-enable this test once it's not flaky anymore.
 #define MAYBE_FetchAndEmitMetricsWithHostedApps \
-  FetchAndEmitMetricsWithHostedApps
+  DISABLED_FetchAndEmitMetricsWithHostedApps
 #endif
 IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest,
                        MAYBE_FetchAndEmitMetricsWithHostedApps) {
diff --git a/chrome/browser/resources/bookmarks/folder_node.html b/chrome/browser/resources/bookmarks/folder_node.html
index 32fb58a..1682e1b 100644
--- a/chrome/browser/resources/bookmarks/folder_node.html
+++ b/chrome/browser/resources/bookmarks/folder_node.html
@@ -1,9 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="actions.html">
 <link rel="import" href="command_manager.html">
 <link rel="import" href="shared_style.html">
@@ -54,25 +52,20 @@
         color: var(--google-grey-refresh-700);
       }
 
-      iron-icon {
-        flex-shrink: 0;
-      }
-
       #arrow {
-        color: var(--cr-secondary-text-color);
         margin: 0 8px;
       }
 
-      #arrow iron-icon {
+      #arrow:not([is-open]) {
         transform: rotate(-90deg);
         transition: transform 150ms;
       }
 
-      :host-context([dir='rtl']) #arrow iron-icon {
+      :host-context([dir='rtl']) #arrow:not([is-open]) {
         transform: rotate(90deg);
       }
 
-      #arrow iron-icon[is-open] {
+      #arrow[is-open] {
         transform: initial;
       }
 
@@ -91,15 +84,10 @@
         role="treeitem"
         aria-owns="descendants">
       <template is="dom-if" if="[[hasChildFolder_]]">
-        <paper-icon-button-light id="arrow">
-          <button on-click="toggleFolder_"
-              on-mousedown="preventDefault_"
-              tabindex="-1"
-              aria-label$="[[getButtonAriaLabel_(isOpen, item_)]]">
-            <iron-icon icon="cr:arrow-drop-down" is-open$="[[isOpen]]">
-            </iron-icon>
-          </button>
-        </paper-icon-button-light>
+        <cr-icon-button id="arrow" iron-icon="cr:arrow-drop-down"
+            on-click="toggleFolder_" on-mousedown="preventDefault_"
+            tabindex="-1" aria-label$="[[getButtonAriaLabel_(isOpen, item_)]]"
+            is-open$="[[isOpen]]" noink></cr-icon-button>
       </template>
       <div id="folder-label" class="v-centered">
         <div class="folder-icon"
diff --git a/chrome/browser/resources/bookmarks/item.html b/chrome/browser/resources/bookmarks/item.html
index d5e5f2a..9eb10af 100644
--- a/chrome/browser/resources/bookmarks/item.html
+++ b/chrome/browser/resources/bookmarks/item.html
@@ -74,7 +74,7 @@
       }
 
       :host-context([dark]):host([is-selected-item_]) cr-icon-button {
-        --cr-icon-button-ripple-color: var(--google-grey-700);
+        --cr-icon-button-color: var(--google-grey-700);
       }
 
       :host(:focus) {
diff --git a/chrome/browser/resources/bookmarks/toolbar.html b/chrome/browser/resources/bookmarks/toolbar.html
index d6579e9..5f9f879 100644
--- a/chrome/browser/resources/bookmarks/toolbar.html
+++ b/chrome/browser/resources/bookmarks/toolbar.html
@@ -21,14 +21,11 @@
       }
 
       cr-icon-button {
-        --cr-icon-button-color: white;
-        --cr-icon-button-ripple-color: white;
-        display: inline-block;
         margin: 4px;
       }
 
-      :host-context([dark]) cr-icon-button {
-        --cr-icon-button-color: var(--google-grey-200);
+      :host-context(html:not([dark])) cr-icon-button {
+        --cr-icon-button-color: currentColor;
       }
 
       :host(:not([narrow_])) cr-toolbar-selection-overlay {
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css
index a685200..0502cb7 100644
--- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css
+++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css
@@ -72,7 +72,6 @@
 }
 
 .hidden.arc-events-inner-band,
-.hidden.arc-events-inner-band-last-buffer,
 .hidden.arc-events-top-band {
   display: none;
 }
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js
index 17631c60..412915d0 100644
--- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js
+++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js
@@ -148,6 +148,18 @@
     svg.appendChild(rect);
   }
 
+  // Creates line element in the |svg| with provided attributes.
+  static addLine(svg, x1, y1, x2, y2, color) {
+    var line = document.createElementNS(svgNS, 'line');
+    line.setAttributeNS(null, 'x1', x1);
+    line.setAttributeNS(null, 'y1', y1);
+    line.setAttributeNS(null, 'x2', x2);
+    line.setAttributeNS(null, 'y2', y2);
+    line.setAttributeNS(null, 'stroke', color);
+    line.setAttributeNS(null, 'stroke-width', 0.5);
+    svg.appendChild(line);
+  }
+
   // Creates circle element in the |svg| with provided attributes.
   static addCircle(svg, x, y, radius, strokeWidth, color, strokeColor) {
     var circle = document.createElementNS(svgNS, 'circle');
@@ -212,22 +224,25 @@
   }
 }
 
-/** Represents one band with events. */
-class EventBand {
+/** Represents container for event bands. */
+class EventBands {
   /**
-   * Creates band with events.
+   * Creates container for the event bands.
    *
    * @param {EventBandTitle} title controls visibility of this band.
    * @param {string} className class name of the svg element that represents
    *     this band. 'arc-events-top-band' is used for top-level events and
    *     'arc-events-inner-band' is used for per-buffer events.
-   * @param {number} duration of band in microseconds.
-   * @param {height} height of elements in this band.
+   * @param {number} duration of bands in microseconds.
    */
-  constructor(title, className, duration, height) {
+  constructor(title, className, duration) {
+    // Keep information about bands and their bounds.
+    this.bands = [];
     this.duration = duration;
     this.width = timestampToOffset(duration);
-    this.height = height;
+    this.height = 0;
+    // Offset of the next band of events.
+    this.nextYOffset = 0;
     this.svg = document.createElementNS(svgNS, 'svg');
     this.svg.setAttributeNS(
         'http://www.w3.org/2000/xmlns/', 'xmlns:xlink',
@@ -243,48 +258,78 @@
   }
 
   /**
-   * Assigns events for this band. Events with type between |eventTypeMin|
-   * and |eventTypeMax| are only displayed on the band.
+   * This adds new band of events. Height of svg container is automatically
+   * adjusted to fit the new content.
    *
-   * @param {Object[]} events non-filtered list of all events. Each has
-   *     array where first element is type and second is timestamp.
-   * @param {number} eventTypeMin minimum inclusive type of the event to be
-   *     displayed on this band.
-   * @param {number} eventTypeMax maximum inclusive type of the event to be
-   *     displayed on this band.
+   * @param {Events} eventBand event band to add.
+   * @param {number} height of the band.
+   * @param {number} padding to separate from the next band.
    */
-  setEvents(events, eventTypeMin, eventTypeMax) {
-    this.events = events;
-    this.eventTypeMin = eventTypeMin;
-    this.eventTypeMax = eventTypeMax;
-    this.drawBand_();
-  }
-
-  /** Enumerates events and creates visual representation */
-  drawBand_() {
+  addBand(eventBand, height, padding) {
     var currentColor = bandColor;
     var x = 0;
-    for (var i = 0; i < this.events.length; ++i) {
-      var event = this.events[i];
-      if (event[0] < this.eventTypeMin || event[0] > this.eventTypeMax) {
-        continue;
+    var eventIndex = -1;
+    while (true) {
+      eventIndex = eventBand.getNextEvent(eventIndex, 1 /* direction */);
+      if (eventIndex < 0) {
+        break;
       }
+      var event = eventBand.events[eventIndex];
       var nextX = timestampToOffset(event[1]);
-      SVG.addRect(this.svg, x, 0, nextX - x, this.height, currentColor);
-      if (this.isEndOfSequence_(i)) {
+      SVG.addRect(
+          this.svg, x, this.nextYOffset, nextX - x, height, currentColor);
+      if (eventBand.isEndOfSequence(eventIndex)) {
         currentColor = bandColor;
       } else {
         currentColor = eventAttributes[event[0]].color;
       }
       x = nextX;
     }
-    SVG.addRect(this.svg, x, 0, this.width - x, this.height, currentColor);
+    SVG.addRect(
+        this.svg, x, this.nextYOffset, this.width - x, height, currentColor);
+
+    this.bands.push({
+      band: eventBand,
+      top: this.nextYOffset,
+      bottom: this.nextYOffset + height
+    });
+
+    this.nextYOffset += height;
+    this.height = this.nextYOffset;
+    this.svg.setAttribute('height', this.height + 'px');
+    this.nextYOffset += padding;
+  }
+
+  /**
+   * This adds events as a global events that do not belong to any band.
+   *
+   * @param {Events} events to add.
+   */
+  addGlobal(events) {
+    var eventIndex = -1;
+    while (true) {
+      eventIndex = events.getNextEvent(eventIndex, 1 /* direction */);
+      if (eventIndex < 0) {
+        break;
+      }
+      var event = events.events[eventIndex];
+      var attributes = events.getEventAttributes(eventIndex);
+      var x = timestampToOffset(event[1]);
+      SVG.addLine(this.svg, x, 0, x, this.height, attributes.color);
+    }
+  }
+
+  /** Initializes tooltip support by observing mouse events */
+  setTooltip_() {
+    this.tooltip = getSVGElement('arc-event-band-tooltip');
+    this.svg.onmouseover = this.showToolTip_.bind(this);
+    this.svg.onmouseout = this.hideToolTip_.bind(this);
+    this.svg.onmousemove = this.updateToolTip_.bind(this);
   }
 
   /** Updates tooltip and shows it for this band. */
   showToolTip_(event) {
     this.updateToolTip_(event);
-    this.tooltip.classList.add('active');
   }
 
   /** Hides the tooltip. */
@@ -293,59 +338,6 @@
   }
 
   /**
-   * Helper that finds next or previous event. Events that pass filter are
-   * only processed.
-   *
-   * @param {number} index starting index for the search, not inclusive.
-   * @param {direction} direction to search, 1 means to find the next event
-   *     and -1 means the previous event.
-   * @returns {number} index of the next or previous event or -1 in case
-   *     not found.
-   */
-  getNextEvent_(index, direction) {
-    while (true) {
-      index += direction;
-      if (index < 0 || index >= this.events.length) {
-        return -1;
-      }
-      if (this.events[index][0] >= this.eventTypeMin &&
-          this.events[index][0] <= this.eventTypeMax) {
-        return index;
-      }
-    }
-  }
-
-  /**
-   * Helper that returns render attributes for the event.
-   *
-   * @param {number} index element index in |this.events|.
-   */
-  getEventAttributes_(index) {
-    return eventAttributes[this.events[index][0]];
-  }
-
-  /**
-   * Returns true if the tested event denotes end of event sequence.
-   *
-   * @param {number} index element index in |this.events|.
-   */
-  isEndOfSequence_(index) {
-    var nextEventTypes = endSequenceEvents[this.events[index][0]];
-    if (!nextEventTypes) {
-      return false;
-    }
-    if (nextEventTypes.length == 0) {
-      return true;
-    }
-    var nextIndex = this.getNextEvent_(index, 1 /* direction */);
-    if (nextIndex < 0) {
-      // No more events after and it is listed as possible end of sequence.
-      return true;
-    }
-    return nextEventTypes.includes(this.events[nextIndex][0]);
-  }
-
-  /**
    * Updates tool tip based on event under the current cursor.
    *
    * @param {Object} event mouse event.
@@ -363,6 +355,22 @@
     var lineHeight = 16;
     var fontSize = 12;
 
+    // Find band for this mouse event.
+    var eventBand = undefined;
+
+    for (var i = 0; i < this.bands.length; ++i) {
+      if (this.bands[i].top <= event.offsetY &&
+          this.bands[i].bottom > event.offsetY) {
+        eventBand = this.bands[i].band;
+        break;
+      }
+    }
+
+    if (!eventBand) {
+      this.tooltip.classList.remove('active');
+      return;
+    }
+
     var yOffset = verticalGap + lineHeight;
     var eventTimestamp = offsetToTime(event.offsetX);
     SVG.addText(
@@ -372,20 +380,20 @@
 
     // Find the event under the cursor. |index| points to the current event
     // and |nextIndex| points to the next event.
-    var nextIndex = this.getNextEvent_(-1 /* index */, 1 /* direction */);
+    var nextIndex = eventBand.getNextEvent(-1 /* index */, 1 /* direction */);
     while (nextIndex >= 0) {
-      if (this.events[nextIndex][1] > eventTimestamp) {
+      if (eventBand.events[nextIndex][1] > eventTimestamp) {
         break;
       }
-      nextIndex = this.getNextEvent_(nextIndex, 1 /* direction */);
+      nextIndex = eventBand.getNextEvent(nextIndex, 1 /* direction */);
     }
-    var index = this.getNextEvent_(nextIndex, -1 /* direction */);
+    var index = eventBand.getNextEvent(nextIndex, -1 /* direction */);
 
     // In case cursor points to idle event, show its interval. Otherwise
     // show the sequence of non-idle events.
-    if (index < 0 || this.isEndOfSequence_(index)) {
-      var startIdle = index < 0 ? 0 : this.events[index][1];
-      var endIdle = index < 0 ? this.duration : this.events[nextIndex][1];
+    if (index < 0 || eventBand.isEndOfSequence(index)) {
+      var startIdle = index < 0 ? 0 : eventBand.events[index][1];
+      var endIdle = index < 0 ? this.duration : eventBand.events[nextIndex][1];
       SVG.addText(
           this.tooltip, horizontalGap, yOffset, 12,
           'Idle ' + timestempToMsText(startIdle) + '...' +
@@ -394,21 +402,21 @@
     } else {
       // Find the start of the non-idle sequence.
       while (true) {
-        var prevIndex = this.getNextEvent_(index, -1 /* direction */);
-        if (prevIndex < 0 || this.isEndOfSequence_(prevIndex)) {
+        var prevIndex = eventBand.getNextEvent(index, -1 /* direction */);
+        if (prevIndex < 0 || eventBand.isEndOfSequence(prevIndex)) {
           break;
         }
         index = prevIndex;
       }
 
-      var sequenceTimestamp = this.events[index][1];
+      var sequenceTimestamp = eventBand.events[index][1];
       var lastTimestamp = sequenceTimestamp;
       var firstEvent = true;
       // Scan for the entries to show.
       var entriesToShow = [];
       while (index >= 0) {
-        var attributes = this.getEventAttributes_(index);
-        var eventTimestamp = this.events[index][1];
+        var attributes = eventBand.getEventAttributes(index);
+        var eventTimestamp = eventBand.events[index][1];
         var entryToShow = {};
         if (firstEvent) {
           // Show the global timestamp.
@@ -426,11 +434,11 @@
               ' [' + timestempToMsText(eventTimestamp - lastTimestamp) + ' ms]';
         }
         entriesToShow.push(entryToShow);
-        if (this.isEndOfSequence_(index)) {
+        if (eventBand.isEndOfSequence(index)) {
           break;
         }
         lastTimestamp = eventTimestamp;
-        index = this.getNextEvent_(index, 1 /* direction */);
+        index = eventBand.getNextEvent(index, 1 /* direction */);
       }
 
       // Last element is end of sequence, use bandColor for the icon.
@@ -454,14 +462,80 @@
     this.tooltip.style.left = event.clientX + 'px';
     this.tooltip.style.top = event.clientY + 'px';
     this.tooltip.style.height = yOffset + 'px';
+    this.tooltip.classList.add('active');
+  }
+}
+
+/** Represents one band with events. */
+class Events {
+  /**
+   * Assigns events for this band. Events with type between |eventTypeMin|
+   * and |eventTypeMax| are only displayed on the band.
+   *
+   * @param {Object[]} events non-filtered list of all events. Each has
+   *     array where first element is type and second is timestamp.
+   * @param {number} eventTypeMin minimum inclusive type of the event to be
+   *     displayed on this band.
+   * @param {number} eventTypeMax maximum inclusive type of the event to be
+   *     displayed on this band.
+   */
+  constructor(events, eventTypeMin, eventTypeMax) {
+    this.events = events;
+    this.eventTypeMin = eventTypeMin;
+    this.eventTypeMax = eventTypeMax;
   }
 
-  /** Initializes tooltip support by observing mouse events */
-  setTooltip_() {
-    this.tooltip = getSVGElement('arc-event-band-tooltip');
-    this.svg.onmouseover = this.showToolTip_.bind(this);
-    this.svg.onmouseout = this.hideToolTip_.bind(this);
-    this.svg.onmousemove = this.updateToolTip_.bind(this);
+  /**
+   * Helper that finds next or previous event. Events that pass filter are
+   * only processed.
+   *
+   * @param {number} index starting index for the search, not inclusive.
+   * @param {direction} direction to search, 1 means to find the next event
+   *     and -1 means the previous event.
+   * @returns {number} index of the next or previous event or -1 in case
+   *     not found.
+   */
+  getNextEvent(index, direction) {
+    while (true) {
+      index += direction;
+      if (index < 0 || index >= this.events.length) {
+        return -1;
+      }
+      if (this.events[index][0] >= this.eventTypeMin &&
+          this.events[index][0] <= this.eventTypeMax) {
+        return index;
+      }
+    }
+  }
+
+  /**
+   * Helper that returns render attributes for the event.
+   *
+   * @param {number} index element index in |this.events|.
+   */
+  getEventAttributes(index) {
+    return eventAttributes[this.events[index][0]];
+  }
+
+  /**
+   * Returns true if the tested event denotes end of event sequence.
+   *
+   * @param {number} index element index in |this.events|.
+   */
+  isEndOfSequence(index) {
+    var nextEventTypes = endSequenceEvents[this.events[index][0]];
+    if (!nextEventTypes) {
+      return false;
+    }
+    if (nextEventTypes.length == 0) {
+      return true;
+    }
+    var nextIndex = this.getNextEvent(index, 1 /* direction */);
+    if (nextIndex < 0) {
+      // No more events after and it is listed as possible end of sequence.
+      return true;
+    }
+    return nextEventTypes.includes(this.events[nextIndex][0]);
   }
 }
 
@@ -474,17 +548,25 @@
   // Clear previous content.
   $('arc-event-bands').textContent = '';
 
-  var chromeTopBandTitle = new EventBandTitle('Chrome');
+  var vsyncEvents =
+      new Events(model.android, 400 /* kVsync */, 400 /* kVsync */);
+
+  var chromeTitle = new EventBandTitle('Chrome');
+  var chromeBands =
+      new EventBands(chromeTitle, 'arc-events-top-band', model.duration);
   for (i = 0; i < model.chrome.length; i++) {
-    var chromeTopBand = new EventBand(
-        chromeTopBandTitle, 'arc-events-top-band', model.duration, 20);
-    chromeTopBand.setEvents(model.chrome[i], 500, 504);
+    chromeBands.addBand(
+        new Events(model.chrome[i], 500, 504), 20 /* height */,
+        4 /* padding */);
   }
 
-  var androidTopBandTitle = new EventBandTitle('Android');
-  var androidTopBand = new EventBand(
-      androidTopBandTitle, 'arc-events-top-band', model.duration, 20);
-  androidTopBand.setEvents(model.android, 401, 504);
+  var androidTitle = new EventBandTitle('Android');
+  var androidBands =
+      new EventBands(androidTitle, 'arc-events-top-band', model.duration);
+  androidBands.addBand(
+      new Events(model.android, 401, 504), 20 /* height */, 0 /* padding */);
+  // Add vsync events
+  androidBands.addGlobal(vsyncEvents);
 
   for (i = 0; i < model.views.length; i++) {
     var view = model.views[i];
@@ -498,17 +580,25 @@
       activityTitleText = 'Task #' + view.task_id + ' - ' + view.activity;
     }
     var activityTitle = new EventBandTitle(activityTitleText, icon);
+    var activityBands =
+        new EventBands(activityTitle, 'arc-events-inner-band', model.duration);
     for (j = 0; j < view.buffers.length; j++) {
-      var androidBand = new EventBand(
+      var androidBand = new Events(
           activityTitle, 'arc-events-inner-band', model.duration, 14);
-      androidBand.setEvents(view.buffers[j], 100, 105);
-      var exoBand = new EventBand(
-          activityTitle, 'arc-events-inner-band', model.duration, 14);
-      exoBand.setEvents(view.buffers[j], 200, 204);
-      var chromeBand = new EventBand(
-          activityTitle, 'arc-events-inner-band-last-buffer', model.duration,
-          14);
-      chromeBand.setEvents(view.buffers[j], 300, 301);
+      // Android buffer events.
+      activityBands.addBand(
+          new Events(view.buffers[j], 100, 105), 14 /* height */,
+          4 /* padding */);
+      // exo events.
+      activityBands.addBand(
+          new Events(view.buffers[j], 200, 204), 14 /* height */,
+          4 /* padding */);
+      // Chrome buffer events.
+      activityBands.addBand(
+          new Events(view.buffers[j], 300, 301), 14 /* height */,
+          12 /* padding */);
     }
+    // Add vsync events
+    activityBands.addGlobal(vsyncEvents);
   }
 }
diff --git a/chrome/browser/resources/chromeos/login/OWNERS b/chrome/browser/resources/chromeos/login/OWNERS
index 5a1a5f7c..30325d9d 100644
--- a/chrome/browser/resources/chromeos/login/OWNERS
+++ b/chrome/browser/resources/chromeos/login/OWNERS
@@ -1,4 +1,5 @@
 achuith@chromium.org
 alemate@chromium.org
 jdufault@chromium.org
+tbarzic@chromium.org
 per-file *active_directory*=rsorokin@chromium.org
diff --git a/chrome/browser/resources/downloads/item.html b/chrome/browser/resources/downloads/item.html
index 60350e3..ad502b9 100644
--- a/chrome/browser/resources/downloads/item.html
+++ b/chrome/browser/resources/downloads/item.html
@@ -5,6 +5,7 @@
 <link rel="import" href="chrome://downloads/i18n_setup.html">
 <link rel="import" href="chrome://downloads/icon_loader.html">
 <link rel="import" href="chrome://downloads/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -18,7 +19,6 @@
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
@@ -243,23 +243,11 @@
         color: var(--controlled-by-active-link-color);
       }
 
-      #remove-wrapper {
-        align-self: flex-start;
-        margin: 0;
-      }
 
-      #remove-wrapper > paper-icon-button-light {
-        --cr-icon-size: 16px;
-        color: var(--google-grey-refresh-700);
-        height: 32px;
-        margin-inline-end: 8px;
-        margin-inline-start: 0;
+      cr-icon-button {
+        --cr-icon-button-icon-size: 16px;
+        --cr-icon-button-margin-end: 8px;
         margin-top: 8px;
-        width: 32px;
-      }
-
-      :host-context([dark]) #remove-wrapper > paper-icon-button-light {
-        color: var(--google-grey-refresh-500);
       }
 
       #incognito {
@@ -376,18 +364,12 @@
           </div>
         </template>
       </div>
-
-      <div id="remove-wrapper" class="icon-wrapper ">
-        <paper-icon-button-light class="icon-clear"
-            style$="[[computeRemoveStyle_(isDangerous_, showCancel_)]]">
-          <button id="remove"
-              title="$i18n{controlRemoveFromList}"
-              aria-label$="[[controlRemoveFromListAriaLabel_]]"
-              on-click="onRemoveTap_" focus-row-control focus-type="remove">
-          </button>
-        </paper-icon-button-light>
-      </div>
-
+      <cr-icon-button class="icon-clear"
+          style$="[[computeRemoveStyle_(isDangerous_, showCancel_)]]"
+          id="remove" title="$i18n{controlRemoveFromList}"
+          aria-label$="[[controlRemoveFromListAriaLabel_]]"
+          on-click="onRemoveTap_" focus-row-control focus-type="remove">
+      </cr-icon-button>
       <div id="incognito" title="$i18n{inIncognito}" hidden="[[!data.otr]]">
       </div>
     </div>
diff --git a/chrome/browser/resources/downloads/toolbar.html b/chrome/browser/resources/downloads/toolbar.html
index 80fc546b..ada013d 100644
--- a/chrome/browser/resources/downloads/toolbar.html
+++ b/chrome/browser/resources/downloads/toolbar.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://downloads/search_service.html">
 <link rel="import" href="chrome://downloads/browser_proxy.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -10,8 +11,6 @@
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/util.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
 <dom-module id="downloads-toolbar">
@@ -27,24 +26,20 @@
         flex: 1;
       }
 
-      #moreActionsContainer {
-        --iron-icon-height: 20px;
-        --iron-icon-width: 20px;
-        height: 32px;
-        padding: 6px 0;
-        width: 32px;
+      cr-icon-button {
+        margin: 4px;
+      }
+
+      :host-context(html:not([dark])) cr-icon-button {
+        --cr-icon-button-color: currentColor;
       }
     </style>
     <cr-toolbar id="toolbar" page-name="$i18n{title}"
         search-prompt="$i18n{search}" clear-label="$i18n{clearSearch}"
         spinner-active="{{spinnerActive}}" on-search-changed="onSearchChanged_">
-      <paper-icon-button-light id="moreActionsContainer"
-          class="dropdown-trigger">
-        <button id="moreActions" title="$i18n{moreActions}"
-            on-click="onMoreActionsTap_" aria-haspopup="menu">
-          <iron-icon icon="cr:more-vert"></iron-icon>
-        </button>
-      </paper-icon-button-light>
+      <cr-icon-button id="moreActions" iron-icon="cr:more-vert"
+          class="dropdown-trigger" title="$i18n{moreActions}"
+          on-click="onMoreActionsTap_" aria-haspopup="menu"></cr-icon-button>
     </cr-toolbar>
     <cr-action-menu id="moreActionsMenu"
         aria-label="$i18n{actionMenuDescription}">
diff --git a/chrome/browser/resources/eoc_internals/BUILD.gn b/chrome/browser/resources/eoc_internals/BUILD.gn
index 97fbc9b..cbef167 100644
--- a/chrome/browser/resources/eoc_internals/BUILD.gn
+++ b/chrome/browser/resources/eoc_internals/BUILD.gn
@@ -12,11 +12,7 @@
 
 js_library("eoc_internals") {
   deps = [
+    "//chrome/browser/ui/webui/eoc_internals:mojo_bindings_js_library_for_compile",
     "//ui/webui/resources/js:util",
   ]
-  extra_deps = [ "//chrome/browser/ui/webui/eoc_internals:mojo_bindings_js" ]
-  externs_list = [
-    "$root_gen_dir/chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom.externs.js",
-    "$externs_path/mojo.js",
-  ]
 }
diff --git a/chrome/browser/resources/eoc_internals/eoc_internals.html b/chrome/browser/resources/eoc_internals/eoc_internals.html
index 1841605..6b5bb2f1 100644
--- a/chrome/browser/resources/eoc_internals/eoc_internals.html
+++ b/chrome/browser/resources/eoc_internals/eoc_internals.html
@@ -13,9 +13,9 @@
   <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
   <link rel="stylesheet" href="eoc_internals.css">
 
-  <script src="chrome://resources/js/mojo_bindings.js"></script>
+  <script src="chrome://resources/js/mojo_bindings_lite.js"></script>
   <script src="chrome://resources/js/util.js"></script>
-  <script src="eoc_internals.mojom.js"></script>
+  <script src="eoc_internals.mojom-lite.js"></script>
 
   <script src="eoc_internals.js"></script>
 </head>
diff --git a/chrome/browser/resources/eoc_internals/eoc_internals.js b/chrome/browser/resources/eoc_internals/eoc_internals.js
index 33cf1846..4f36dfe 100644
--- a/chrome/browser/resources/eoc_internals/eoc_internals.js
+++ b/chrome/browser/resources/eoc_internals/eoc_internals.js
@@ -4,7 +4,10 @@
 
 'use strict';
 
-// Reference to the backend.
+/**
+ * Reference to the backend.
+ * @type {eocInternals.mojom.PageHandlerProxy}
+ */
 let pageHandler = null;
 
 (function() {
@@ -26,8 +29,8 @@
 // Get the general properties.
 function updatePageWithProperties() {
   pageHandler.getProperties().then(response => {
-    response.properties.forEach(function(value, field) {
-      $(field).textContent = value;
+    Object.keys(response.properties).forEach(function(field) {
+      $(field).textContent = response.properties[field];
     });
   });
 }
@@ -141,10 +144,7 @@
 
 document.addEventListener('DOMContentLoaded', function() {
   // Setup backend mojo.
-  pageHandler = new eocInternals.mojom.PageHandlerPtr;
-  Mojo.bindInterface(
-      eocInternals.mojom.PageHandler.name,
-      mojo.makeRequest(pageHandler).handle);
+  pageHandler = eocInternals.mojom.PageHandler.getProxy();
 
   updatePageWithProperties();
   updatePageWithCachedMetricEvents();
@@ -152,4 +152,4 @@
 
   setupEventListeners();
 });
-})();
\ No newline at end of file
+})();
diff --git a/chrome/browser/resources/history/history_item.html b/chrome/browser/resources/history/history_item.html
index a57f41d..648c047 100644
--- a/chrome/browser/resources/history/history_item.html
+++ b/chrome/browser/resources/history/history_item.html
@@ -9,11 +9,12 @@
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html">
+<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/html/icon.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 
-<!-- Lazy loaded: paper-icon-button-light. -->
+<!-- Lazy loaded: cr-icon-button. -->
 
 <dom-module id="history-item">
   <template>
@@ -102,25 +103,15 @@
         margin-inline-start: 16px;
       }
 
-      #menu-button-container {
-        margin-inline-end: 12px;
+      #menu-button {
+        --cr-icon-button-margin-end: 12px;
+        --cr-icon-button-margin-start: 12px;
       }
 
-      #star-container {
-        margin-inline-end: 4px;
-        margin-inline-start: 12px;
-        width: 32px;
-      }
-
-      #bookmark-star-container {
-        color: var(--interactive-color);
-        height: 32px;
-        width: 32px;
-      }
-
-      #bookmark-star-container iron-icon {
-        height: 16px;
-        width: 16px;
+      #bookmark-star {
+        --cr-icon-button-color: var(--interactive-color);
+        --cr-icon-button-icon-size: 16px;
+        --cr-icon-button-margin-start: 12px;
       }
 
       #time-gap-separator {
@@ -209,24 +200,16 @@
         </div>
         <div id="star-container">
           <template is="dom-if" if="[[item.starred]]" notify-dom-change>
-            <paper-icon-button-light id="bookmark-star-container">
-              <button id="bookmark-star" focus-row-control focus-type="star"
-                  title="$i18n{removeBookmark}" on-click="onRemoveBookmarkTap_">
-                <iron-icon icon="cr:star"></iron-icon>
-              </button>
-            </paper-icon-button-light>
+            <cr-icon-button id="bookmark-star" iron-icon="cr:star"
+                focus-row-control focus-type="star"
+                title="$i18n{removeBookmark}" on-click="onRemoveBookmarkTap_">
+            </cr-icon-button>
           </template>
         </div>
-        <paper-icon-button-light id="menu-button-container"
-            class="more-vert-button">
-          <button id="menu-button" focus-row-control focus-type="cr-menu-button"
-              title="$i18n{actionMenuDescription}" on-click="onMenuButtonTap_"
-              aria-haspopup="menu">
-            <div></div>
-            <div></div>
-            <div></div>
-          </button>
-        </paper-icon-button-light>
+        <cr-icon-button id="menu-button" iron-icon="cr:more-vert"
+            focus-row-control focus-type="cr-menu-button"
+            title="$i18n{actionMenuDescription}" on-click="onMenuButtonTap_"
+            aria-haspopup="menu"></cr-icon-button>
       </div>
       <div id="time-gap-separator" hidden="[[!hasTimeGap]]"></div>
     </div>
diff --git a/chrome/browser/resources/history/history_item.js b/chrome/browser/resources/history/history_item.js
index cee46334..6bdf7f52 100644
--- a/chrome/browser/resources/history/history_item.js
+++ b/chrome/browser/resources/history/history_item.js
@@ -104,7 +104,7 @@
       for (let i = 0; i < e.path.length; i++) {
         const elem = e.path[i];
         if (elem.id != 'checkbox' &&
-            (elem.nodeName == 'A' || elem.nodeName == 'BUTTON')) {
+            (elem.nodeName == 'A' || elem.nodeName == 'CR-ICON-BUTTON')) {
           return;
         }
       }
@@ -189,7 +189,7 @@
       }
 
       if (this.$$('#bookmark-star') == this.root.activeElement) {
-        this.$['menu-button'].focus();
+        cr.ui.focusWithoutInk(this.$['menu-button']);
       }
 
       const browserService = history.BrowserService.getInstance();
diff --git a/chrome/browser/resources/history/lazy_load.html b/chrome/browser/resources/history/lazy_load.html
index 81a6d85e..53567c5 100644
--- a/chrome/browser/resources/history/lazy_load.html
+++ b/chrome/browser/resources/history/lazy_load.html
@@ -6,8 +6,8 @@
   <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
+  <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-  <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 </body>
 </html>
diff --git a/chrome/browser/resources/history/shared_style.html b/chrome/browser/resources/history/shared_style.html
index daccd428a..c915d823 100644
--- a/chrome/browser/resources/history/shared_style.html
+++ b/chrome/browser/resources/history/shared_style.html
@@ -57,26 +57,6 @@
         text-overflow: ellipsis;
         white-space: nowrap;
       }
-
-      paper-icon-button-light {
-        background: none;
-        border: none;
-        height: 36px;
-        outline: none;
-        width: 36px;
-      }
-
-      paper-icon-button-light.more-vert-button > button {
-        padding: 8px;
-      }
-
-      paper-icon-button-light.more-vert-button div {
-        border: 2px solid var(--cr-secondary-text-color);
-        border-radius: 2px;
-        margin: 1px 8px;
-        pointer-events: none;
-        transform: scale(0.8);
-      }
     </style>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/history/synced_device_card.html b/chrome/browser/resources/history/synced_device_card.html
index f4d2c366..d7bdbf0 100644
--- a/chrome/browser/resources/history/synced_device_card.html
+++ b/chrome/browser/resources/history/synced_device_card.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_row.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/html/icon.html">
 <link rel="import" href="browser_service.html">
 <link rel="import" href="constants.html">
@@ -44,7 +44,7 @@
 
       #device-name {
         overflow: hidden;
-        padding-right: 3px;
+        padding-inline-end: 3px;
         text-overflow: ellipsis;
       }
 
@@ -87,21 +87,12 @@
           <span id="last-update-time">[[lastUpdateTime]]</span>
         </div>
         <div id="right-buttons">
-          <paper-icon-button-light class="more-vert-button">
-            <button id="menu-button" on-click="onMenuButtonTap_"
-                title="$i18n{actionMenuDescription}">
-              <div></div>
-              <div></div>
-              <div></div>
-            </button>
-          </paper-icon-button-light>
-          <paper-icon-button-light>
-            <button id="collapse-button" title$="[[getCollapseTitle_(opened)]]">
-              <iron-icon icon="[[getCollapseIcon_(opened)]]"
-                  id="dropdown-indicator">
-              </iron-icon>
-            </button>
-          </paper-icon-button-light>
+          <cr-icon-button id="menu-button" iron-icon="cr:more-vert"
+              on-click="onMenuButtonTap_" title="$i18n{actionMenuDescription}">
+          </cr-icon-button>
+          <cr-icon-button id="collapse-button"
+              iron-icon="[[getCollapseIcon_(opened)]]"
+              title$="[[getCollapseTitle_(opened)]]"></cr-icon-button>
         </div>
       </div>
 
diff --git a/chrome/browser/resources/history/synced_device_card.js b/chrome/browser/resources/history/synced_device_card.js
index 9908112..6e1c5a6 100644
--- a/chrome/browser/resources/history/synced_device_card.js
+++ b/chrome/browser/resources/history/synced_device_card.js
@@ -93,8 +93,6 @@
         SYNCED_TABS_HISTOGRAM_NAME, histogramValue, SyncedTabsHistogram.LIMIT);
 
     this.$.collapse.toggle();
-    this.$['dropdown-indicator'].icon =
-        this.$.collapse.opened ? 'cr:expand-less' : 'cr:expand-more';
 
     this.fire('update-focus-grid');
   },
diff --git a/chrome/browser/resources/md_extensions/activity_log/activity_log_history_item.html b/chrome/browser/resources/md_extensions/activity_log/activity_log_history_item.html
index 53c9992..8e72add 100644
--- a/chrome/browser/resources/md_extensions/activity_log/activity_log_history_item.html
+++ b/chrome/browser/resources/md_extensions/activity_log/activity_log_history_item.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="../shared_style.html">
 <link rel="import" href="../shared_vars.html">
 
 <dom-module id="activity-log-history-item">
diff --git a/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html b/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html
index f2fb6d5e..5ab89ab 100644
--- a/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html
+++ b/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html
@@ -10,7 +10,7 @@
   <template>
     <style include="shared-style paper-button-style">
       :host {
-        --activity-log-call-and-time-width: 590px;
+        --activity-log-call-and-time-width: 596px;
         --activity-type-width: 85px;
         --activity-time-width: 100px;
       }
diff --git a/chrome/browser/resources/md_extensions/activity_log/activity_log_stream_item.html b/chrome/browser/resources/md_extensions/activity_log/activity_log_stream_item.html
index 68d921c..10fae93 100644
--- a/chrome/browser/resources/md_extensions/activity_log/activity_log_stream_item.html
+++ b/chrome/browser/resources/md_extensions/activity_log/activity_log_stream_item.html
@@ -4,28 +4,27 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
+<link rel="import" href="../shared_style.html">
 <link rel="import" href="../shared_vars.html">
 
 <dom-module id="activity-log-stream-item">
   <template>
-    <style include="cr-icons cr-shared-style">
+    <style include="cr-icons cr-shared-style shared-style">
       :host {
         border-top: var(--cr-separator-line);
         display: block;
         padding: 8px var(--cr-section-padding);
       }
 
-      #activity-item-main-row {
-        align-items: center;
-        display: flex;
-        flex-direction: row;
+      cr-expand-button {
+        --cr-expand-button-disabled-display: none;
+
         /* Match separator height. */
         min-height: calc(var(--cr-section-min-height) - var(--separator-gap));
       }
 
-      #activity-item-main-row cr-expand-button {
-        margin-inline-end: 6px;
+      cr-expand-button[disabled] {
+        opacity: 1;
       }
 
       #activity-call-and-time {
@@ -53,14 +52,11 @@
         text-align: end;
       }
 
-      iron-collapse {
-        max-width: var(--activity-log-call-and-time-width);
-      }
-
       #expanded-data {
         display: flex;
         flex-direction: column;
         margin-inline-start: 16px;
+        max-width: var(--activity-log-call-and-time-width);
       }
 
       #page-url-link {
@@ -100,42 +96,35 @@
         margin-top: 10px;
       }
     </style>
-    <div actionable$="[[isExpandable_]]"
-        id="activity-item-main-row"
-        on-click="onExpandClick_">
+    <cr-expand-button expanded="[[data.expanded]]"
+        disabled="[[!isExpandable_]]" on-click="onExpandClick_">
       <div id="activity-call-and-time">
         <span id="activity-type">[[data.activityType]]</span>
         <span id="activity-name" title="[[data.name]]">[[data.name]]</span>
         <span id="activity-time">[[getFormattedTime_(data.timeStamp)]]</span>
       </div>
-      <cr-expand-button expanded="{{data.expanded}}"
-          hidden$="[[!isExpandable_]]">
-      </cr-expand-button>
-    </div>
-    <iron-collapse opened="[[data.expanded]]">
-      <div id="expanded-data" hidden$="[[!isExpandable_]]">
-        <a id="page-url-link" href="[[data.pageUrl]]"
-            hidden$="[[!hasPageUrl_(data.pageUrl)]]"
-            title="[[data.pageUrl]]">[[data.pageUrl]]</a>
-        <div id="args-list" hidden$="[[!hasArgs_(argsList_)]]">
-          <span class="expanded-data-heading">
-            $i18n{activityArgumentsHeading}
-          </span>
-          <template is="dom-repeat" items="[[argsList_]]">
-            <div class="list-item">
-              <span class="index">[[item.index]]</span>
-              <span class="arg">[[item.arg]]</span>
-            </div>
-          </template>
-        </div>
-        <div id="web-request-section"
-            hidden$="[[!hasWebRequestInfo_(data.webRequestInfo)]]">
-          <span class="expanded-data-heading">
-            $i18n{webRequestInfoHeading}</span>
-          <span id="web-request-details">[[data.webRequestInfo]]</span>
-        </div>
+    </cr-expand-button>
+    <div id="expanded-data" hidden$="[[!data.expanded]]">
+      <a id="page-url-link" href="[[data.pageUrl]]"
+          hidden$="[[!hasPageUrl_(data.pageUrl)]]"
+          title="[[data.pageUrl]]">[[data.pageUrl]]</a>
+      <div id="args-list" hidden$="[[!hasArgs_(argsList_)]]">
+        <span class="expanded-data-heading">
+          $i18n{activityArgumentsHeading}
+        </span>
+        <template is="dom-repeat" items="[[argsList_]]">
+          <div class="list-item">
+            <span class="index">[[item.index]]</span>
+            <span class="arg">[[item.arg]]</span>
+          </div>
+        </template>
       </div>
-    </iron-collapse>
+      <div id="web-request-section"
+          hidden$="[[!hasWebRequestInfo_(data.webRequestInfo)]]">
+        <span class="expanded-data-heading">$i18n{webRequestInfoHeading}</span>
+        <span id="web-request-details">[[data.webRequestInfo]]</span>
+      </div>
+    </div>
   </template>
   <script src="activity_log_stream_item.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/reset_password/BUILD.gn b/chrome/browser/resources/reset_password/BUILD.gn
index 1d0f2eb..2a2f75f 100644
--- a/chrome/browser/resources/reset_password/BUILD.gn
+++ b/chrome/browser/resources/reset_password/BUILD.gn
@@ -12,12 +12,8 @@
 
 js_library("reset_password") {
   deps = [
+    "//chrome/browser/ui/webui/reset_password:mojo_bindings_js_externs",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:util",
   ]
-  extra_deps = [ "//chrome/browser/ui/webui/reset_password:mojo_bindings_js" ]
-  externs_list = [
-    "$root_gen_dir/chrome/browser/ui/webui/reset_password/reset_password.mojom.externs.js",
-    "$externs_path/mojo.js",
-  ]
 }
diff --git a/chrome/browser/resources/reset_password/reset_password.html b/chrome/browser/resources/reset_password/reset_password.html
index b68848f..60838025 100644
--- a/chrome/browser/resources/reset_password/reset_password.html
+++ b/chrome/browser/resources/reset_password/reset_password.html
@@ -9,9 +9,9 @@
   <link rel="import" href="chrome://resources/cr_elements/icons.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-  <script src="chrome://resources/js/mojo_bindings.js"></script>
+  <script src="chrome://resources/js/mojo_bindings_lite.js"></script>
   <script src="chrome://resources/js/util.js"></script>
-  <script src="reset_password.mojom.js"></script>
+  <script src="reset_password.mojom-lite.js"></script>
   <script src="reset_password.js"></script>
   <style>
     html {
diff --git a/chrome/browser/resources/reset_password/reset_password.js b/chrome/browser/resources/reset_password/reset_password.js
index df5c5f7..15611b4d 100644
--- a/chrome/browser/resources/reset_password/reset_password.js
+++ b/chrome/browser/resources/reset_password/reset_password.js
@@ -8,13 +8,11 @@
  */
 (function() {
 
-/** @type {mojom.ResetPasswordHandler} */
+/** @type {mojom.ResetPasswordHandlerProxy} */
 let uiHandler;
 
 function initialize() {
-  uiHandler = new mojom.ResetPasswordHandlerPtr;
-  Mojo.bindInterface(
-      mojom.ResetPasswordHandler.name, mojo.makeRequest(uiHandler).handle);
+  uiHandler = mojom.ResetPasswordHandler.getProxy();
 
   /** @type {?HTMLElement} */
   const resetPasswordButton = $('reset-password-button');
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
index 4139346..7f31cb9 100644
--- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -247,8 +247,8 @@
             $i18n{a11yWebStore}
           </div>
         </div>
-        <paper-icon-button-light class="icon-external">
-          <button actionable aria-label="$i18n{additionalFeaturesTitle}"
+        <paper-icon-button-light actionable class="icon-external">
+          <button aria-label="$i18n{additionalFeaturesTitle}"
               aria-describedby="moreFeaturesSecondary"></button>
         </paper-icon-button-light>
       </a>
diff --git a/chrome/browser/resources/snippets_internals/BUILD.gn b/chrome/browser/resources/snippets_internals/BUILD.gn
index c636d01a..fbb85737 100644
--- a/chrome/browser/resources/snippets_internals/BUILD.gn
+++ b/chrome/browser/resources/snippets_internals/BUILD.gn
@@ -12,13 +12,8 @@
 
 js_library("snippets_internals") {
   deps = [
+    "//chrome/browser/ui/webui/snippets_internals:mojo_bindings_js_library_for_compile",
     "//third_party/jstemplate:jstemplate",
     "//ui/webui/resources/js:util",
   ]
-  extra_deps =
-      [ "//chrome/browser/ui/webui/snippets_internals:mojo_bindings_js" ]
-  externs_list = [
-    "$root_gen_dir/chrome/browser/ui/webui/snippets_internals/snippets_internals.mojom.externs.js",
-    "$externs_path/mojo.js",
-  ]
 }
diff --git a/chrome/browser/resources/snippets_internals/snippets_internals.html b/chrome/browser/resources/snippets_internals/snippets_internals.html
index 32cbe82..9763f1b 100644
--- a/chrome/browser/resources/snippets_internals/snippets_internals.html
+++ b/chrome/browser/resources/snippets_internals/snippets_internals.html
@@ -13,11 +13,11 @@
   <link rel="stylesheet" href="snippets_internals.css">
 
   <script src="chrome://resources/js/cr.js"></script>
-  <script src="chrome://resources/js/mojo_bindings.js"></script>
+  <script src="chrome://resources/js/mojo_bindings_lite.js"></script>
   <script src="chrome://resources/js/jstemplate_compiled.js"></script>
   <script src="chrome://resources/js/util.js"></script>
 
-  <script src="snippets_internals.mojom.js"></script>
+  <script src="snippets_internals.mojom-lite.js"></script>
   <script src="snippets_internals.js"></script>
 </head>
 
diff --git a/chrome/browser/resources/snippets_internals/snippets_internals.js b/chrome/browser/resources/snippets_internals/snippets_internals.js
index 97ba3cd6..71bd8db5 100644
--- a/chrome/browser/resources/snippets_internals/snippets_internals.js
+++ b/chrome/browser/resources/snippets_internals/snippets_internals.js
@@ -4,10 +4,10 @@
 
 'use strict';
 
-/** @type {snippetsInternals.mojom.PageHandlerPtr} */
+/** @type {snippetsInternals.mojom.PageHandlerProxy} */
 let pageHandler = null;
 
-/** @type {snippetsInternals.mojom.PageImpl} */
+/** @type {snippetsInternals.mojom.PageInterface} */
 let page = null;
 
 /* Javascript module for chrome://snippets-internals. */
@@ -18,11 +18,11 @@
 /**
  * Sets all the properties contained in the mapping in the page.
  * property map {id -> value}.
- * @param {Map} propertyMap Property name to value mapping.
+ * @param {!Object<string,string>} propertyMap Property name to value mapping.
  */
 function setPropertiesInPage(propertyMap) {
-  propertyMap.forEach(function(value, field) {
-    setPropertyInPage(field, value);
+  Object.keys(propertyMap).forEach(function(field) {
+    setPropertyInPage(field, propertyMap[field]);
   });
 }
 
@@ -91,12 +91,12 @@
 
     const table = $(domId);
     const rowTemplate = $('category-ranker-row');
-    response.properties.forEach(function(value, field) {
+    Object.keys(response.properties).forEach(function(field) {
       const row = document.importNode(rowTemplate.content, true);
       const td = row.querySelectorAll('td');
 
       td[0].textContent = field;
-      td[1].textContent = value;
+      td[1].textContent = response.properties[field];
       table.appendChild(row);
     });
   });
@@ -279,13 +279,8 @@
 }
 
 /* Represents the js-side of the IPC link. Backend talks to this. */
-/** @implements {snippetsInternals.mojom.PageImpl} */
+/** @implements {snippetsInternals.mojom.PageInterface} */
 class SnippetsInternalsPageImpl {
-  constructor(request) {
-    this.binding_ =
-        new mojo.Binding(snippetsInternals.mojom.Page, this, request);
-  }
-
   /* Callback for when suggestions change on the backend. */
   onSuggestionsChanged() {
     getSuggestionsByCategory();
@@ -295,17 +290,14 @@
 /* Main entry point. */
 document.addEventListener('DOMContentLoaded', function() {
   // Setup frontend mojo.
-  const client = new snippetsInternals.mojom.PagePtr;
-  assert(client);
-  page = new SnippetsInternalsPageImpl(mojo.makeRequest(client));
+  page = new SnippetsInternalsPageImpl;
 
   // Setup backend mojo.
-  const pageHandlerFactory = new snippetsInternals.mojom.PageHandlerFactoryPtr;
-  Mojo.bindInterface(
-      snippetsInternals.mojom.PageHandlerFactory.name,
-      mojo.makeRequest(pageHandlerFactory).handle);
+  const pageHandlerFactory =
+      snippetsInternals.mojom.PageHandlerFactory.getProxy();
 
   // Give backend mojo a reference to frontend mojo.
+  const client = new snippetsInternals.mojom.Page(page).createProxy();
   pageHandlerFactory.createPageHandler(client).then((response) => {
 
     pageHandler = response.handler;
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc
index f7148533..e1713a43 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win_unittest.cc
@@ -633,20 +633,10 @@
   controller_->RemoveObserver(&mock_observer_);
 }
 
-// Make all the test parameter types printable.
-
+// Make all the test parameter types printable. Use short names because these
+// are used in tests with very many parameters.
 std::ostream& operator<<(std::ostream& out, CleanerProcessStatus status) {
-  switch (status) {
-    case CleanerProcessStatus::kFetchFailure:
-      return out << "FetchFailure";
-    case CleanerProcessStatus::kFetchSuccessInvalidProcess:
-      return out << "FetchSuccessInvalidProcess";
-    case CleanerProcessStatus::kFetchSuccessValidProcess:
-      return out << "FetchSuccessValidProcess";
-    default:
-      NOTREACHED();
-      return out << "UnknownProcessStatus" << status;
-  }
+  return out << "Proc" << static_cast<int>(status);
 }
 
 // This includes all crash points after kOnStartup, except kAfterRequestSent.
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
index 2ab9d444..1aead41 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.cc
@@ -8,41 +8,16 @@
 
 using UserResponse = ChromeCleanerController::UserResponse;
 
+// Keep the printable names of these enums short since they're used in tests
+// with very long parameter lists.
+//
 std::ostream& operator<<(std::ostream& out,
                          ChromeCleanerController::State state) {
-  switch (state) {
-    case ChromeCleanerController::State::kIdle:
-      return out << "Idle";
-    case ChromeCleanerController::State::kReporterRunning:
-      return out << "ReporterRunning";
-    case ChromeCleanerController::State::kScanning:
-      return out << "Scanning";
-    case ChromeCleanerController::State::kInfected:
-      return out << "Infected";
-    case ChromeCleanerController::State::kCleaning:
-      return out << "Cleaning";
-    case ChromeCleanerController::State::kRebootRequired:
-      return out << "RebootRequired";
-    default:
-      NOTREACHED();
-      return out << "UnknownUserResponse" << state;
-  }
+  return out << "State" << static_cast<int>(state);
 }
 
 std::ostream& operator<<(std::ostream& out, UserResponse response) {
-  switch (response) {
-    case UserResponse::kAcceptedWithLogs:
-      return out << "UserAcceptedWithLogs";
-    case UserResponse::kAcceptedWithoutLogs:
-      return out << "UserAcceptedWithoutLogs";
-    case UserResponse::kDenied:
-      return out << "UserDenied";
-    case UserResponse::kDismissed:
-      return out << "UserDismissed";
-    default:
-      NOTREACHED();
-      return out << "UnknownUserResponse";
-  }
+  return out << "Resp" << static_cast<int>(response);
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc
index 638fa057..6e1b453 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_process_win.cc
@@ -427,63 +427,24 @@
   std::move(quit_closure).Run();
 }
 
+// Keep the printable names of these enums short since they're used in tests
+// with very long parameter lists.
+
 std::ostream& operator<<(std::ostream& out, CrashPoint crash_point) {
-  switch (crash_point) {
-    case CrashPoint::kNone:
-      return out << "NoCrash";
-    case CrashPoint::kOnStartup:
-      return out << "CrashOnStartup";
-    case CrashPoint::kAfterConnection:
-      return out << "CrashAfterConnection";
-    case CrashPoint::kAfterRequestSent:
-      return out << "CrashAfterRequestSent";
-    case CrashPoint::kAfterResponseReceived:
-      return out << "CrashAfterResponseReceived";
-    default:
-      NOTREACHED();
-      return out << "UnknownCrashPoint";
-  }
+  return out << "CrPt" << static_cast<int>(crash_point);
 }
 
 std::ostream& operator<<(std::ostream& out, UwsFoundStatus status) {
-  switch (status) {
-    case UwsFoundStatus::kNoUwsFound:
-      return out << "NoUwsFound";
-    case UwsFoundStatus::kUwsFoundRebootRequired:
-      return out << "UwsFoundRebootRequired";
-    case UwsFoundStatus::kUwsFoundNoRebootRequired:
-      return out << "UwsFoundNoRebootRequired";
-    default:
-      NOTREACHED();
-      return out << "UnknownFoundStatus";
-  }
+  return out << "UwS" << static_cast<int>(status);
 }
 
 std::ostream& operator<<(std::ostream& out,
                          ExtensionCleaningFeatureStatus status) {
-  switch (status) {
-    case ExtensionCleaningFeatureStatus::kEnabled:
-      return out << "ExtensionCleaningEnabled";
-    case ExtensionCleaningFeatureStatus::kDisabled:
-      return out << "ExtensionCleaningDisabled";
-    default:
-      NOTREACHED();
-      return out << "UnknownExtensionCleaningStatus";
-  }
+  return out << "Ext" << static_cast<int>(status);
 }
 
 std::ostream& operator<<(std::ostream& out, ItemsReporting items_reporting) {
-  switch (items_reporting) {
-    case ItemsReporting::kUnsupported:
-      return out << "kUnsupported";
-    case ItemsReporting::kNotReported:
-      return out << "kNotReported";
-    case ItemsReporting::kReported:
-      return out << "kReported";
-    default:
-      NOTREACHED();
-      return out << "UnknownItemsReporting";
-  }
+  return out << "Items" << static_cast<int>(items_reporting);
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/ui/ash/assistant/assistant_client.cc b/chrome/browser/ui/ash/assistant/assistant_client.cc
index a6508e26..76dd233b 100644
--- a/chrome/browser/ui/ash/assistant/assistant_client.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_client.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h"
 #include "chrome/browser/chromeos/assistant/assistant_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/ash/assistant/assistant_context_util.h"
 #include "chrome/browser/ui/ash/assistant/assistant_image_downloader.h"
 #include "chrome/browser/ui/ash/assistant/assistant_setup.h"
@@ -36,9 +37,19 @@
 AssistantClient::~AssistantClient() {
   DCHECK(g_instance);
   g_instance = nullptr;
+
+  if (identity_manager_)
+    identity_manager_->RemoveObserver(this);
 }
 
 void AssistantClient::MaybeInit(Profile* profile) {
+  if (!profile_) {
+    profile_ = profile;
+    identity_manager_ = IdentityManagerFactory::GetForProfile(profile_);
+    identity_manager_->AddObserver(this);
+  }
+  DCHECK_EQ(profile_, profile);
+
   if (assistant::IsAssistantAllowedForProfile(profile) !=
       ash::mojom::AssistantAllowedState::ALLOWED) {
     return;
@@ -86,3 +97,10 @@
     RequestAssistantStructureCallback callback) {
   RequestAssistantStructureForActiveBrowserWindow(std::move(callback));
 }
+
+void AssistantClient::OnExtendedAccountInfoUpdated(const AccountInfo& info) {
+  if (initialized_)
+    return;
+
+  MaybeInit(profile_);
+}
diff --git a/chrome/browser/ui/ash/assistant/assistant_client.h b/chrome/browser/ui/ash/assistant/assistant_client.h
index eef5571..97c17c2 100644
--- a/chrome/browser/ui/ash/assistant/assistant_client.h
+++ b/chrome/browser/ui/ash/assistant/assistant_client.h
@@ -11,13 +11,15 @@
 #include "chrome/browser/ui/ash/assistant/device_actions.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/identity/public/cpp/identity_manager.h"
 
 class Profile;
 class AssistantImageDownloader;
 class AssistantSetup;
 
 // Class to handle all assistant in-browser-process functionalities.
-class AssistantClient : chromeos::assistant::mojom::Client {
+class AssistantClient : chromeos::assistant::mojom::Client,
+                        public identity::IdentityManager::Observer {
  public:
   static AssistantClient* Get();
 
@@ -33,6 +35,14 @@
       RequestAssistantStructureCallback callback) override;
 
  private:
+  // identity::IdentityManager::Observer:
+  // Retry to initiate Assistant service when account info has been updated.
+  // This is necessary if previous calls of MaybeInit() failed due to Assistant
+  // disallowed by account type. This can happen when the chromeos sign-in
+  // finished before account info fetching is finished (|hosted_domain| field
+  // will be empty under this case).
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+
   mojo::Binding<chromeos::assistant::mojom::Client> client_binding_;
   mojo::Binding<chromeos::assistant::mojom::DeviceActions>
       device_actions_binding_;
@@ -45,6 +55,10 @@
 
   bool initialized_ = false;
 
+  // Non-owning pointers.
+  Profile* profile_ = nullptr;
+  identity::IdentityManager* identity_manager_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(AssistantClient);
 };
 
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index 5697c464..92b5786 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -551,7 +551,6 @@
       payments_client_(std::make_unique<payments::PaymentsClient>(
           Profile::FromBrowserContext(web_contents->GetBrowserContext())
               ->GetURLLoaderFactory(),
-          GetPrefs(),
           GetIdentityManager(),
           GetPersonalDataManager(),
           Profile::FromBrowserContext(web_contents->GetBrowserContext())
diff --git a/chrome/browser/ui/renderer_event_injection_browsertest.cc b/chrome/browser/ui/renderer_event_injection_browsertest.cc
new file mode 100644
index 0000000..8f72ca6
--- /dev/null
+++ b/chrome/browser/ui/renderer_event_injection_browsertest.cc
@@ -0,0 +1,136 @@
+// Copyright 2019 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 "base/macros.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "cc/base/switches.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/platform/web_touch_event.h"
+#include "ui/display/display_switches.h"
+
+namespace {
+
+// This test verifies renderer event injection works. That is, it verifies
+// a renderer can inject events and that they're received by content. It's in
+// the Chrome side (not content) so that it can verify events work correctly
+// when all of Chrome is brought up. This is especially important for ChromeOS,
+// as content tests do not bring up the ChromeOS window-manager (ash).
+//
+// The parameter is how the display is configured, and is only applicable to
+// ChromeOS.
+class RendererEventInjectionTest
+    : public InProcessBrowserTest,
+      public ::testing::WithParamInterface<const char*> {
+ public:
+  RendererEventInjectionTest() {}
+  ~RendererEventInjectionTest() override {}
+
+  // InProcessBrowserTest:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kSyntheticPointerActions);
+    InProcessBrowserTest::SetUp();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kDisableRendererBackgrounding);
+    command_line->AppendSwitch(cc::switches::kEnableGpuBenchmarking);
+    // kHostWindowBounds is unique to ChromeOS.
+#if defined(OS_CHROMEOS)
+    command_line->AppendSwitchASCII(switches::kHostWindowBounds, GetParam());
+#endif
+    embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(RendererEventInjectionTest);
+};
+
+// Detects when a touch press is received.
+class TouchEventObserver
+    : public content::RenderWidgetHost::InputEventObserver {
+ public:
+  TouchEventObserver(const gfx::Point& location,
+                     base::RepeatingClosure quit_closure)
+      : expected_location_(location), quit_closure_(std::move(quit_closure)) {}
+  ~TouchEventObserver() override = default;
+
+ private:
+  // content::RenderWidgetHost::InputEventObserver:
+  void OnInputEvent(const blink::WebInputEvent& event) override {
+    if (blink::WebInputEvent::IsTouchEventType(event.GetType())) {
+      const blink::WebTouchEvent& web_touch =
+          static_cast<const blink::WebTouchEvent&>(event);
+      if (event.GetType() == blink::WebInputEvent::kTouchStart) {
+        for (unsigned i = 0; i < web_touch.touches_length; i++) {
+          const blink::WebTouchPoint& touch_point = web_touch.touches[i];
+          const gfx::Point location(
+              static_cast<int>(touch_point.PositionInWidget().x),
+              static_cast<int>(touch_point.PositionInWidget().y));
+          if (touch_point.state == blink::WebTouchPoint::kStatePressed &&
+              location == expected_location_) {
+            quit_closure_.Run();
+          }
+        }
+      }
+    }
+  }
+
+  const gfx::Point expected_location_;
+  base::RepeatingClosure quit_closure_;
+
+  DISALLOW_COPY_AND_ASSIGN(TouchEventObserver);
+};
+
+IN_PROC_BROWSER_TEST_P(RendererEventInjectionTest, TestRootTransform) {
+  content::WebContents* main_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  GURL url = embedded_test_server()->GetURL("/title1.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  base::RunLoop run_loop;
+  content::RenderWidgetHost* rwh =
+      main_contents->GetRenderWidgetHostView()->GetRenderWidgetHost();
+  TouchEventObserver touch_observer(gfx::Point(100, 150),
+                                    run_loop.QuitClosure());
+  rwh->AddInputEventObserver(&touch_observer);
+  EXPECT_TRUE(ExecJs(main_contents,
+                     "chrome.gpuBenchmarking.tap(100, 150, ()=>{}, "
+                     "50, chrome.gpuBenchmarking.TOUCH_INPUT);"));
+  run_loop.Run();
+  rwh->RemoveInputEventObserver(&touch_observer);
+}
+
+#if defined(OS_CHROMEOS)
+// This configures the display in various interesting ways for ChromeOS. In
+// particular, it tests rotation "/r" and a scale factor of 2 "*2".
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    RendererEventInjectionTest,
+    ::testing::Values("1200x800", "1200x800/r", "1200x800*2", "1200x800*2/r"));
+#else
+INSTANTIATE_TEST_SUITE_P(, RendererEventInjectionTest, ::testing::Values(""));
+#endif
+
+}  // namespace
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.cc b/chrome/browser/ui/thumbnails/thumbnail_image.cc
index e5f8660..95a68ab 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_image.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_image.cc
@@ -48,6 +48,11 @@
   return image_representation_.bitmap()->computeByteSize();
 }
 
+bool ThumbnailImage::BackedBySameObjectAs(const ThumbnailImage& other) const {
+  return image_representation_.BackedBySameObjectAs(
+      other.image_representation_);
+}
+
 // static
 ThumbnailImage ThumbnailImage::FromSkBitmap(SkBitmap bitmap) {
   ThumbnailImage result;
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.h b/chrome/browser/ui/thumbnails/thumbnail_image.h
index 46576d9..c86696e8 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_image.h
+++ b/chrome/browser/ui/thumbnails/thumbnail_image.h
@@ -48,6 +48,10 @@
   // Returns the size (in bytes) required to store the internal representation.
   size_t GetStorageSize() const;
 
+  // Does an address comparison on the refcounted backing store of this object.
+  // May return false even if the backing stores contain equivalent image data.
+  bool BackedBySameObjectAs(const ThumbnailImage& other) const;
+
   // Encodes thumbnail data as ThumbnailRepresentation. May involve an expensive
   // operation. Prefer FromSkBitmapAsync() instead.
   static ThumbnailImage FromSkBitmap(SkBitmap bitmap);
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
index bfe8907..86d359a 100644
--- a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
@@ -8,12 +8,15 @@
 #include <string>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/callback_list.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/autofill/autofill_uitest_util.h"
+#include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
@@ -34,6 +37,7 @@
 #include "chrome/browser/ui/views/autofill/save_card_bubble_views.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h"
+#include "chrome/browser/web_data_service_factory.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
@@ -41,12 +45,15 @@
 #include "components/autofill/core/browser/form_data_importer.h"
 #include "components/autofill/core/browser/payments/credit_card_save_manager.h"
 #include "components/autofill/core/browser/payments/local_card_migration_manager.h"
+#include "components/autofill/core/browser/payments/payments_util.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/browser/test_event_waiter.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/keyed_service/core/service_access_type.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/sync/test/fake_server/fake_server.h"
@@ -79,6 +86,10 @@
 
 namespace {
 
+ACTION_P(QuitMessageLoop, loop) {
+  loop->Quit();
+}
+
 constexpr char kURLGetUploadDetailsRequest[] =
     "https://payments.google.com/payments/apis/chromepaymentsservice/"
     "getdetailsforsavecard";
@@ -114,6 +125,14 @@
 
 }  // namespace
 
+class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
+ public:
+  PersonalDataLoadedObserverMock() = default;
+  ~PersonalDataLoadedObserverMock() = default;
+
+  MOCK_METHOD0(OnPersonalDataChanged, void());
+};
+
 class LocalCardMigrationBrowserTest
     : public SyncTest,
       public LocalCardMigrationManager::ObserverForTest {
@@ -183,28 +202,63 @@
             ->local_card_migration_manager_.get();
 
     local_card_migration_manager_->SetEventObserverForTesting(this);
-    personal_data_ = local_card_migration_manager_->personal_data_manager_;
+    personal_data_ =
+        PersonalDataManagerFactory::GetForProfile(browser()->profile());
 
     // Set up the fake geolocation data.
     geolocation_overrider_ =
         std::make_unique<device::ScopedGeolocationOverrider>(
             kFakeGeolocationLatitude, kFakeGeolocationLongitude);
 
-    // Set up billing customer ID.
-    ContentAutofillDriver::GetForRenderFrameHost(
-        GetActiveWebContents()->GetMainFrame())
-        ->autofill_manager()
-        ->client()
-        ->GetPrefs()
-        ->SetDouble(prefs::kAutofillBillingCustomerNumber, 1234);
-
     scoped_feature_list_.InitAndEnableFeature(
         features::kAutofillCreditCardLocalCardMigration);
     ASSERT_TRUE(harness_->SetupSync());
+
+    // Set the billing_customer_number to designate existence of a Payments
+    // account.
+    const PaymentsCustomerData data =
+        PaymentsCustomerData(/*customer_id=*/"123456");
+    SetPaymentsCustomerData(data);
+
     SetUploadDetailsRpcPaymentsAccepts();
     SetUpMigrateCardsRpcPaymentsAccepts();
   }
 
+  void SetPaymentsCustomerDataOnDBSequence(
+      AutofillWebDataService* wds,
+      const PaymentsCustomerData& customer_data) {
+    DCHECK(wds->GetDBTaskRunner()->RunsTasksInCurrentSequence());
+    AutofillTable::FromWebDatabase(wds->GetDatabase())
+        ->SetPaymentsCustomerData(&customer_data);
+  }
+
+  void SetPaymentsCustomerData(const PaymentsCustomerData& customer_data) {
+    scoped_refptr<AutofillWebDataService> wds =
+        WebDataServiceFactory::GetAutofillWebDataForProfile(
+            browser()->profile(), ServiceAccessType::EXPLICIT_ACCESS);
+    base::RunLoop loop;
+    wds->GetDBTaskRunner()->PostTaskAndReply(
+        FROM_HERE,
+        base::BindOnce(
+            &LocalCardMigrationBrowserTest::SetPaymentsCustomerDataOnDBSequence,
+            base::Unretained(this), base::Unretained(wds.get()), customer_data),
+        base::BindOnce(&base::RunLoop::Quit, base::Unretained(&loop)));
+    loop.Run();
+    WaitForOnPersonalDataChanged();
+  }
+
+  void WaitForOnPersonalDataChanged() {
+    personal_data_->AddObserver(&personal_data_observer_);
+    personal_data_->Refresh();
+
+    base::RunLoop run_loop;
+    EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+        .WillRepeatedly(QuitMessageLoop(&run_loop));
+    run_loop.Run();
+    testing::Mock::VerifyAndClearExpectations(&personal_data_observer_);
+    personal_data_->RemoveObserver(&personal_data_observer_);
+  }
+
   void NavigateTo(const std::string& file_path) {
     ui_test_utils::NavigateToURL(
         browser(), file_path.find("data:") == 0U
@@ -456,6 +510,7 @@
   LocalCardMigrationManager* local_card_migration_manager_;
 
   PersonalDataManager* personal_data_;
+  PersonalDataLoadedObserverMock personal_data_observer_;
 
   base::test::ScopedFeatureList scoped_feature_list_;
 
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc
index 414d003..c20b6797 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.cc
+++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -52,45 +52,27 @@
 #endif
 }
 
-ExtensionPopup::ExtensionPopup(extensions::ExtensionViewHost* host,
-                               views::View* anchor_view,
-                               views::BubbleBorder::Arrow arrow,
-                               ShowAction show_action)
-    : BubbleDialogDelegateView(anchor_view,
-                               arrow,
-                               views::BubbleBorder::SMALL_SHADOW),
-      host_(host) {
-  set_margins(gfx::Insets());
-  SetLayoutManager(std::make_unique<views::FillLayout>());
-  AddChildView(GetExtensionView());
-  GetExtensionView()->set_container(this);
-  UpdateShowAction(show_action);
-
-  // Listen for the containing view calling window.close();
-  registrar_.Add(
-      this,
-      extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
-      content::Source<content::BrowserContext>(host->browser_context()));
-  content::DevToolsAgentHost::AddObserver(this);
-  observer_.Add(GetExtensionView()->GetBrowser()->tab_strip_model());
-
-  // If the host had somehow finished loading, then we'd miss the notification
-  // and not show.  This seems to happen in single-process mode.
-  if (host_->has_loaded_once()) {
-    ShowBubble();
-  } else {
-    // Wait to show the popup until the contained host finishes loading.
-    registrar_.Add(this,
-                   content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
-                   content::Source<content::WebContents>(
-                       host_->host_contents()));
-  }
-}
-
 ExtensionPopup::~ExtensionPopup() {
   content::DevToolsAgentHost::RemoveObserver(this);
 }
 
+gfx::Size ExtensionPopup::CalculatePreferredSize() const {
+  // Constrain the size to popup min/max.
+  gfx::Size sz = views::View::CalculatePreferredSize();
+  sz.set_width(std::max(kMinWidth, std::min(kMaxWidth, sz.width())));
+  sz.set_height(std::max(kMinHeight, std::min(kMaxHeight, sz.height())));
+  return sz;
+}
+
+void ExtensionPopup::AddedToWidget() {
+  const int radius =
+      GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius();
+  const bool contents_has_rounded_corners =
+      GetExtensionView()->holder()->SetCornerRadius(radius);
+  SetBorder(views::CreateEmptyBorder(
+      gfx::Insets(contents_has_rounded_corners ? 0 : radius, 0)));
+}
+
 int ExtensionPopup::GetDialogButtons() const {
   return ui::DIALOG_BUTTON_NONE;
 }
@@ -110,6 +92,10 @@
   return false;
 }
 
+void ExtensionPopup::OnExtensionSizeChanged(ExtensionViewViews* view) {
+  SizeToContents();
+}
+
 void ExtensionPopup::Observe(int type,
                              const content::NotificationSource& source,
                              const content::NotificationDetails& details) {
@@ -130,6 +116,14 @@
   }
 }
 
+void ExtensionPopup::OnTabStripModelChanged(
+    TabStripModel* tab_strip_model,
+    const TabStripModelChange& change,
+    const TabStripSelectionChange& selection) {
+  if (!tab_strip_model->empty() && selection.active_tab_changed())
+    GetWidget()->Close();
+}
+
 void ExtensionPopup::DevToolsAgentHostAttached(
     content::DevToolsAgentHost* agent_host) {
   if (host()->host_contents() == agent_host->GetWebContents())
@@ -144,37 +138,37 @@
   }
 }
 
-ExtensionViewViews* ExtensionPopup::GetExtensionView() {
-  return static_cast<ExtensionViewViews*>(host_.get()->view());
-}
+ExtensionPopup::ExtensionPopup(extensions::ExtensionViewHost* host,
+                               views::View* anchor_view,
+                               views::BubbleBorder::Arrow arrow,
+                               ShowAction show_action)
+    : BubbleDialogDelegateView(anchor_view,
+                               arrow,
+                               views::BubbleBorder::SMALL_SHADOW),
+      host_(host) {
+  set_margins(gfx::Insets());
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+  AddChildView(GetExtensionView());
+  GetExtensionView()->set_container(this);
+  UpdateShowAction(show_action);
 
-void ExtensionPopup::OnExtensionSizeChanged(ExtensionViewViews* view) {
-  SizeToContents();
-}
+  // Listen for the containing view calling window.close();
+  registrar_.Add(
+      this, extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
+      content::Source<content::BrowserContext>(host->browser_context()));
+  content::DevToolsAgentHost::AddObserver(this);
+  observer_.Add(GetExtensionView()->GetBrowser()->tab_strip_model());
 
-gfx::Size ExtensionPopup::CalculatePreferredSize() const {
-  // Constrain the size to popup min/max.
-  gfx::Size sz = views::View::CalculatePreferredSize();
-  sz.set_width(std::max(kMinWidth, std::min(kMaxWidth, sz.width())));
-  sz.set_height(std::max(kMinHeight, std::min(kMaxHeight, sz.height())));
-  return sz;
-}
-
-void ExtensionPopup::AddedToWidget() {
-  const int radius =
-      GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius();
-  const bool contents_has_rounded_corners =
-      GetExtensionView()->holder()->SetCornerRadius(radius);
-  SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(contents_has_rounded_corners ? 0 : radius, 0)));
-}
-
-void ExtensionPopup::OnTabStripModelChanged(
-    TabStripModel* tab_strip_model,
-    const TabStripModelChange& change,
-    const TabStripSelectionChange& selection) {
-  if (!tab_strip_model->empty() && selection.active_tab_changed())
-    GetWidget()->Close();
+  // If the host had somehow finished loading, then we'd miss the notification
+  // and not show.  This seems to happen in single-process mode.
+  if (host_->has_loaded_once()) {
+    ShowBubble();
+  } else {
+    // Wait to show the popup until the contained host finishes loading.
+    registrar_.Add(
+        this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
+        content::Source<content::WebContents>(host_->host_contents()));
+  }
 }
 
 void ExtensionPopup::UpdateShowAction(ShowAction show_action) {
@@ -193,3 +187,7 @@
         host()->host_contents(), DevToolsToggleAction::ShowConsolePanel());
   }
 }
+
+ExtensionViewViews* ExtensionPopup::GetExtensionView() {
+  return static_cast<ExtensionViewViews*>(host_.get()->view());
+}
diff --git a/chrome/browser/ui/views/extensions/extension_popup.h b/chrome/browser/ui/views/extensions/extension_popup.h
index 9853ff46..c429a32 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.h
+++ b/chrome/browser/ui/views/extensions/extension_popup.h
@@ -40,7 +40,11 @@
     SHOW_AND_INSPECT,
   };
 
-  ~ExtensionPopup() override;
+  // The min/max height of popups.
+  static const int kMinWidth;
+  static const int kMinHeight;
+  static const int kMaxWidth;
+  static const int kMaxHeight;
 
   // Creates and shows a popup with the given |host| positioned adjacent to
   // |anchor_view|.
@@ -55,55 +59,48 @@
                         views::BubbleBorder::Arrow arrow,
                         ShowAction show_action);
 
+  ~ExtensionPopup() override;
+
   extensions::ExtensionViewHost* host() const { return host_.get(); }
 
   // views::BubbleDialogDelegateView overrides.
+  gfx::Size CalculatePreferredSize() const override;
+  void AddedToWidget() override;
   int GetDialogButtons() const override;
   void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
   bool ShouldHaveRoundCorners() const override;
 
+  // ExtensionViewViews::Container overrides.
+  void OnExtensionSizeChanged(ExtensionViewViews* view) override;
+
   // content::NotificationObserver overrides.
   void Observe(int type,
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  // ExtensionViewViews::Container overrides.
-  void OnExtensionSizeChanged(ExtensionViewViews* view) override;
-
-  // views::View overrides.
-  gfx::Size CalculatePreferredSize() const override;
-  void AddedToWidget() override;
-
   // TabStripModelObserver overrides.
   void OnTabStripModelChanged(
       TabStripModel* tab_strip_model,
       const TabStripModelChange& change,
       const TabStripSelectionChange& selection) override;
 
-  // The min/max height of popups.
-  static const int kMinWidth;
-  static const int kMinHeight;
-  static const int kMaxWidth;
-  static const int kMaxHeight;
-
- protected:
-  ExtensionPopup(extensions::ExtensionViewHost* host,
-                 views::View* anchor_view,
-                 views::BubbleBorder::Arrow arrow,
-                 ShowAction show_action);
-
- private:
-  // Changes internal state to follow the supplied |show_action|.
-  void UpdateShowAction(ShowAction show_action);
-  // Shows the bubble, focuses its content, and registers listeners.
-  void ShowBubble();
-
   // content::DevToolsAgentHostObserver overrides.
   void DevToolsAgentHostAttached(
       content::DevToolsAgentHost* agent_host) override;
   void DevToolsAgentHostDetached(
       content::DevToolsAgentHost* agent_host) override;
 
+ private:
+  ExtensionPopup(extensions::ExtensionViewHost* host,
+                 views::View* anchor_view,
+                 views::BubbleBorder::Arrow arrow,
+                 ShowAction show_action);
+
+  // Changes internal state to follow the supplied |show_action|.
+  void UpdateShowAction(ShowAction show_action);
+  // Shows the bubble, focuses its content, and registers listeners.
+  void ShowBubble();
+
   ExtensionViewViews* GetExtensionView();
 
   // The contained host for the view.
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
index 313f1c72..f5c301b 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
@@ -25,6 +25,7 @@
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/text_constants.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/image_button.h"
@@ -86,7 +87,8 @@
     title_label_ = new views::Label(base::string16(), CONTEXT_BODY_TEXT_LARGE,
                                     views::style::TextStyle::STYLE_PRIMARY);
     location_label_ = new views::Label(
-        base::string16(), CONTEXT_BODY_TEXT_SMALL, STYLE_SECONDARY);
+        base::string16(), CONTEXT_BODY_TEXT_SMALL, STYLE_SECONDARY,
+        gfx::DirectionalityMode::DIRECTIONALITY_AS_URL);
 
     title_label_->SetBackgroundColor(background_color);
     title_label_->SetElideBehavior(gfx::ElideBehavior::ELIDE_TAIL);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index d55f5ce..c87c6d5c 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -1515,26 +1515,26 @@
       return true;
 
     case ui::VKEY_RIGHT:
-      if (!(control || alt || shift)) {
-        if (!base::i18n::IsRTL()) {
-          if (DirectionAwareSelectionAtEnd() && MaybeFocusTabButton())
-            return true;
-        } else {
-          if (MaybeUnfocusTabButton())
-            return true;
-        }
-      }
-      break;
-
     case ui::VKEY_LEFT:
-      if (!(control || alt || shift)) {
-        if (!base::i18n::IsRTL()) {
-          if (MaybeUnfocusTabButton())
-            return true;
-        } else {
-          if (DirectionAwareSelectionAtEnd() && MaybeFocusTabButton())
-            return true;
+      if (control || alt || shift)
+        return false;
+
+      // If advancing cursor (accounting for UI direction)
+      if (base::i18n::IsRTL() == (event.key_code() == ui::VKEY_LEFT)) {
+        if (!DirectionAwareSelectionAtEnd())
+          return false;
+
+        if (OmniboxFieldTrial::IsExperimentalKeywordModeEnabled() &&
+            model()->is_keyword_hint()) {
+          OnBeforePossibleChange();
+          model()->AcceptKeyword(OmniboxEventProto::SELECT_SUGGESTION);
+          OnAfterPossibleChange(true);
+          return true;
+        } else if (MaybeFocusTabButton()) {
+          return true;
         }
+      } else if (MaybeUnfocusTabButton()) {
+        return true;
       }
       break;
 
diff --git a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc
index f4c38cd..f342483 100644
--- a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc
+++ b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc
@@ -62,8 +62,6 @@
           content::BrowserContext::GetDefaultStoragePartition(
               web_contents_->GetBrowserContext())
               ->GetURLLoaderFactoryForBrowserProcess(),
-          Profile::FromBrowserContext(web_contents_->GetBrowserContext())
-              ->GetPrefs(),
           IdentityManagerFactory::GetForProfile(
               Profile::FromBrowserContext(web_contents_->GetBrowserContext())
                   ->GetOriginalProfile()),
diff --git a/chrome/browser/ui/views/tabs/tab_renderer_data.cc b/chrome/browser/ui/views/tabs/tab_renderer_data.cc
index bc4fb17..5156adf 100644
--- a/chrome/browser/ui/views/tabs/tab_renderer_data.cc
+++ b/chrome/browser/ui/views/tabs/tab_renderer_data.cc
@@ -19,6 +19,7 @@
 
 bool TabRendererData::operator==(const TabRendererData& other) const {
   return favicon.BackedBySameObjectAs(other.favicon) &&
+         thumbnail.BackedBySameObjectAs(other.thumbnail) &&
          network_state == other.network_state && title == other.title &&
          url == other.url && crashed_status == other.crashed_status &&
          incognito == other.incognito && show_icon == other.show_icon &&
diff --git a/chrome/browser/ui/webui/chromeos/login/OWNERS b/chrome/browser/ui/webui/chromeos/login/OWNERS
index 5a1a5f7c..30325d9d 100644
--- a/chrome/browser/ui/webui/chromeos/login/OWNERS
+++ b/chrome/browser/ui/webui/chromeos/login/OWNERS
@@ -1,4 +1,5 @@
 achuith@chromium.org
 alemate@chromium.org
 jdufault@chromium.org
+tbarzic@chromium.org
 per-file *active_directory*=rsorokin@chromium.org
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index cf13356..f6a36da 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -1244,10 +1244,14 @@
       base::BindOnce(&SigninScreenHandler::OnWallpaperBlurChanged,
                      weak_factory_.GetWeakPtr()));
 
-  // This updates post-OOBE shelf UI. Changes the color of shelf buttons and
-  // displays additional buttons that should only be shown in the login screen.
-  session_manager::SessionManager::Get()->SetSessionState(
-      session_manager::SessionState::LOGIN_PRIMARY);
+  session_manager::SessionManager* session_manager =
+      session_manager::SessionManager::Get();
+  if (session_manager->session_state() == session_manager::SessionState::OOBE) {
+    // This updates post-OOBE shelf UI. Changes the color of shelf buttons and
+    // displays additional buttons that should only be shown in the login screen
+    session_manager->SetSessionState(
+        session_manager::SessionState::LOGIN_PRIMARY);
+  }
 
   if (delegate_)
     delegate_->OnSigninScreenReady();
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index a8817df..6cb3336 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -341,6 +341,12 @@
   void HandleToggleKioskEnableScreen();
   void HandleToggleResetScreen();
   void HandleToggleKioskAutolaunchScreen();
+
+  // TODO(crbug.com/943720): Change to views account-picker screen in post-OOBE
+  // flow.
+  // WebUI account-picker screen is shown:
+  // * After OOBE enrollment when policy contains device local accounts.
+  // * On multiple sign-in account selection.
   void HandleAccountPickerReady();
   void HandleOpenInternetDetailDialog();
   void HandleLoginVisible(const std::string& source);
diff --git a/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc b/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc
index 7bf6185..f8bb27ec 100644
--- a/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc
+++ b/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc
@@ -26,7 +26,8 @@
 
   source->AddResourcePath("eoc_internals.css", IDR_EOC_INTERNALS_CSS);
   source->AddResourcePath("eoc_internals.js", IDR_EOC_INTERNALS_JS);
-  source->AddResourcePath("eoc_internals.mojom.js", IDR_EOC_INTERNALS_MOJO_JS);
+  source->AddResourcePath("eoc_internals.mojom-lite.js",
+                          IDR_EOC_INTERNALS_MOJOM_LITE_JS);
   source->SetDefaultResource(IDR_EOC_INTERNALS_HTML);
   source->UseGzip();
 
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
index 52f8b9bf..3fdb4b9 100644
--- a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
+++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
@@ -61,8 +61,7 @@
       base::FeatureList::IsEnabled(feed::kInterestFeedContentSuggestions);
   properties->is_feed_visible =
       pref_service_->GetBoolean(feed::prefs::kArticlesListVisible);
-  properties->is_feed_allowed =
-      pref_service_->GetBoolean(feed::prefs::kEnableSnippets);
+  properties->is_feed_allowed = IsFeedAllowed();
   properties->is_prefetching_enabled =
       offline_pages::prefetch_prefs::IsEnabled(pref_service_);
   properties->feed_fetch_url = feed::GetFeedFetchUrlForDebugging();
@@ -114,6 +113,12 @@
 
 void FeedInternalsPageHandler::GetCurrentContent(
     GetCurrentContentCallback callback) {
+  if (!IsFeedAllowed()) {
+    std::move(callback).Run(
+        std::vector<feed_internals::mojom::SuggestionPtr>());
+    return;
+  }
+
   feed_offline_host_->GetCurrentArticleSuggestions(base::BindOnce(
       &FeedInternalsPageHandler::OnGetCurrentArticleSuggestionsDone,
       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -141,3 +146,7 @@
     GetFeedProcessScopeDumpCallback callback) {
   std::move(callback).Run(feed::GetFeedProcessScopeDumpForDebugging());
 }
+
+bool FeedInternalsPageHandler::IsFeedAllowed() {
+  return pref_service_->GetBoolean(feed::prefs::kEnableSnippets);
+}
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h
index b334469..368bfb1 100644
--- a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h
+++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h
@@ -50,6 +50,8 @@
       GetCurrentContentCallback callback,
       std::vector<offline_pages::PrefetchSuggestion> suggestions);
 
+  bool IsFeedAllowed();
+
   // Services that provide the data and functionality.
   feed::FeedSchedulerHost* feed_scheduler_host_;
   feed::FeedOfflineHost* feed_offline_host_;
diff --git a/chrome/browser/ui/webui/reset_password/reset_password_ui.cc b/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
index e2acd7b..69e40cd0 100644
--- a/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
+++ b/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
@@ -111,8 +111,8 @@
   std::unique_ptr<content::WebUIDataSource> html_source(
       content::WebUIDataSource::Create(chrome::kChromeUIResetPasswordHost));
   html_source->AddResourcePath("reset_password.js", IDR_RESET_PASSWORD_JS);
-  html_source->AddResourcePath("reset_password.mojom.js",
-                               IDR_RESET_PASSWORD_MOJO_JS);
+  html_source->AddResourcePath("reset_password.mojom-lite.js",
+                               IDR_RESET_PASSWORD_MOJOM_LITE_JS);
   html_source->SetDefaultResource(IDR_RESET_PASSWORD_HTML);
   html_source->AddLocalizedStrings(PopulateStrings());
   html_source->UseGzip();
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index d445cde..feeb804 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1583,8 +1583,7 @@
       autofill::PersonalDataManagerFactory::GetForProfile(profile);
   html_source->AddBoolean(
       "hasGooglePaymentsAccount",
-      autofill::payments::GetBillingCustomerId(personal_data_manager_,
-                                               profile->GetPrefs()) != 0);
+      autofill::payments::GetBillingCustomerId(personal_data_manager_) != 0);
 
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile);
diff --git a/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc b/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc
index 30018db..8454343 100644
--- a/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc
+++ b/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc
@@ -24,8 +24,8 @@
       "script-src chrome://resources 'self' 'unsafe-eval';");
   source->AddResourcePath("snippets_internals.css", IDR_SNIPPETS_INTERNALS_CSS);
   source->AddResourcePath("snippets_internals.js", IDR_SNIPPETS_INTERNALS_JS);
-  source->AddResourcePath("snippets_internals.mojom.js",
-                          IDR_SNIPPETS_INTERNALS_MOJO_JS);
+  source->AddResourcePath("snippets_internals.mojom-lite.js",
+                          IDR_SNIPPETS_INTERNALS_MOJOM_LITE_JS);
   source->SetDefaultResource(IDR_SNIPPETS_INTERNALS_HTML);
   source->UseGzip();
 
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn
index 5629a18..accf6157 100644
--- a/chrome/browser/web_applications/extensions/BUILD.gn
+++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -48,6 +48,7 @@
   sources = [
     "bookmark_app_install_finalizer_unittest.cc",
     "bookmark_app_installation_task_unittest.cc",
+    "bookmark_app_uninstaller_unittest.cc",
     "bookmark_app_util_unittest.cc",
     "pending_bookmark_app_manager_unittest.cc",
     "web_app_extension_ids_map_unittest.cc",
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h
index 13c84e4..be69df76 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h
@@ -19,12 +19,12 @@
 class BookmarkAppUninstaller {
  public:
   BookmarkAppUninstaller(Profile* profile, web_app::AppRegistrar* registrar);
-  ~BookmarkAppUninstaller();
+  virtual ~BookmarkAppUninstaller();
 
   // Returns true if the app with |app_url| was successfully uninstalled.
   // Returns false if the app doesn't not exist, or the app failed to be
   // uninstalled.
-  bool UninstallApp(const GURL& app_url);
+  virtual bool UninstallApp(const GURL& app_url);
 
  private:
   Profile* profile_;
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc
new file mode 100644
index 0000000..78aafa6
--- /dev/null
+++ b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc
@@ -0,0 +1,206 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/scoped_observer.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/web_applications/components/web_app_constants.h"
+#include "chrome/browser/web_applications/extensions/bookmark_app_registrar.h"
+#include "chrome/browser/web_applications/test/test_app_registrar.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/crx_file/id_util.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_registry_observer.h"
+#include "extensions/common/extension_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+namespace {
+
+const char kFooWebAppUrl[] = "https://foo.example";
+const char kBarWebAppUrl[] = "https://bar.example";
+
+class TestExtensionRegistryObserver : public ExtensionRegistryObserver {
+ public:
+  explicit TestExtensionRegistryObserver(ExtensionRegistry* registry) {
+    extension_registry_observer_.Add(registry);
+  }
+
+  ~TestExtensionRegistryObserver() override = default;
+
+  const std::vector<std::string>& uninstalled_extension_ids() {
+    return uninstalled_extension_ids_;
+  }
+
+  void ResetResults() { uninstalled_extension_ids_.clear(); }
+
+  // ExtensionRegistryObserver
+  void OnExtensionUninstalled(content::BrowserContext* browser_context,
+                              const Extension* extension,
+                              UninstallReason reason) override {
+    uninstalled_extension_ids_.push_back(extension->id());
+  }
+
+ private:
+  std::vector<std::string> uninstalled_extension_ids_;
+
+  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
+      extension_registry_observer_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(TestExtensionRegistryObserver);
+};
+
+std::string GenerateFakeAppId(const GURL& url) {
+  return crx_file::id_util::GenerateId("fake_app_id_for:" + url.spec());
+}
+
+}  // namespace
+
+class BookmarkAppUninstallerTest : public ChromeRenderViewHostTestHarness {
+ public:
+  BookmarkAppUninstallerTest() = default;
+  ~BookmarkAppUninstallerTest() override = default;
+
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+
+    TestExtensionSystem* test_system =
+        static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()));
+    test_system->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
+                                        profile()->GetPath(),
+                                        false /* autoupdate_enabled */);
+    test_extension_registry_observer_ =
+        std::make_unique<TestExtensionRegistryObserver>(
+            ExtensionRegistry::Get(profile()));
+
+    extension_ids_map_ =
+        std::make_unique<web_app::ExtensionIdsMap>(profile()->GetPrefs());
+    registrar_ = std::make_unique<BookmarkAppRegistrar>(profile());
+
+    uninstaller_ =
+        std::make_unique<BookmarkAppUninstaller>(profile(), registrar_.get());
+  }
+
+  void TearDown() override {
+    // Delete the observer before ExtensionRegistry is deleted.
+    test_extension_registry_observer_.reset();
+    ChromeRenderViewHostTestHarness::TearDown();
+  }
+
+  std::string SimulateInstalledApp(const GURL& app_url) {
+    std::string app_id = GenerateFakeAppId(app_url);
+
+    auto extension = ExtensionBuilder("FooBar")
+                         .SetLocation(Manifest::EXTERNAL_POLICY)
+                         .SetID(app_id)
+                         .Build();
+    ExtensionRegistry::Get(profile())->AddEnabled(extension);
+    extension_ids_map_->Insert(app_url, app_id,
+                               web_app::InstallSource::kExternalPolicy);
+    return app_id;
+  }
+
+  void SimulateExternalAppUninstalledByUser(const GURL& app_url) {
+    const std::string app_id = GenerateFakeAppId(app_url);
+    ExtensionRegistry::Get(profile())->RemoveEnabled(app_id);
+    ExtensionPrefs::Get(profile())->OnExtensionUninstalled(
+        app_id, Manifest::EXTERNAL_POLICY, false /* external_uninstall */);
+  }
+
+  void ResetResults() { test_extension_registry_observer_->ResetResults(); }
+
+  BookmarkAppUninstaller& uninstaller() { return *uninstaller_; }
+
+  const std::vector<std::string>& uninstalled_extension_ids() {
+    return test_extension_registry_observer_->uninstalled_extension_ids();
+  }
+
+  const ExtensionSet& enabled_extensions() {
+    return ExtensionRegistry::Get(profile())->enabled_extensions();
+  }
+
+ private:
+  std::unique_ptr<TestExtensionRegistryObserver>
+      test_extension_registry_observer_;
+
+  std::unique_ptr<web_app::ExtensionIdsMap> extension_ids_map_;
+  std::unique_ptr<BookmarkAppRegistrar> registrar_;
+  std::unique_ptr<BookmarkAppUninstaller> uninstaller_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkAppUninstallerTest);
+};
+
+TEST_F(BookmarkAppUninstallerTest, Uninstall_Successful) {
+  SimulateInstalledApp(GURL(kFooWebAppUrl));
+  ASSERT_EQ(1u, enabled_extensions().size());
+
+  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  content::RunAllTasksUntilIdle();
+
+  EXPECT_EQ(1u, uninstalled_extension_ids().size());
+  EXPECT_EQ(0u, enabled_extensions().size());
+}
+
+TEST_F(BookmarkAppUninstallerTest, Uninstall_Multiple) {
+  auto foo_app_id = SimulateInstalledApp(GURL(kFooWebAppUrl));
+  auto bar_app_id = SimulateInstalledApp(GURL(kBarWebAppUrl));
+  ASSERT_EQ(2u, enabled_extensions().size());
+
+  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kBarWebAppUrl)));
+  content::RunAllTasksUntilIdle();
+
+  EXPECT_EQ(1u, uninstalled_extension_ids().size());
+  EXPECT_EQ(1u, enabled_extensions().size());
+  EXPECT_FALSE(enabled_extensions().Contains(bar_app_id));
+  EXPECT_TRUE(enabled_extensions().Contains(foo_app_id));
+
+  ResetResults();
+
+  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  content::RunAllTasksUntilIdle();
+
+  EXPECT_EQ(1u, uninstalled_extension_ids().size());
+  EXPECT_TRUE(enabled_extensions().is_empty());
+}
+
+TEST_F(BookmarkAppUninstallerTest, Uninstall_UninstalledExternalApp) {
+  SimulateInstalledApp(GURL(kFooWebAppUrl));
+  SimulateExternalAppUninstalledByUser(GURL(kFooWebAppUrl));
+
+  EXPECT_FALSE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+}
+
+// Tests trying to uninstall an app that was never installed.
+TEST_F(BookmarkAppUninstallerTest, Uninstall_FailsNeverInstalled) {
+  EXPECT_FALSE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+}
+
+// Tests trying to uninstall an app that was previously uninstalled.
+TEST_F(BookmarkAppUninstallerTest, Uninstall_FailsAlreadyUninstalled) {
+  SimulateInstalledApp(GURL(kFooWebAppUrl));
+
+  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  content::RunAllTasksUntilIdle();
+
+  EXPECT_EQ(1u, uninstalled_extension_ids().size());
+  EXPECT_TRUE(enabled_extensions().is_empty());
+
+  ResetResults();
+
+  EXPECT_FALSE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  content::RunAllTasksUntilIdle();
+
+  EXPECT_EQ(0u, uninstalled_extension_ids().size());
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
index e84ad771..d8de5dc 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
@@ -55,7 +55,8 @@
     web_app::AppRegistrar* registrar)
     : profile_(profile),
       registrar_(registrar),
-      uninstaller_(profile_, registrar_),
+      uninstaller_(
+          std::make_unique<BookmarkAppUninstaller>(profile_, registrar_)),
       extension_ids_map_(profile->GetPrefs()),
       web_contents_factory_(base::BindRepeating(&WebContentsCreateWrapper)),
       task_factory_(base::BindRepeating(&InstallationTaskCreateWrapper)),
@@ -93,7 +94,8 @@
     std::vector<GURL> apps_to_uninstall,
     const UninstallCallback& callback) {
   for (auto& app_to_uninstall : apps_to_uninstall) {
-    callback.Run(app_to_uninstall, uninstaller_.UninstallApp(app_to_uninstall));
+    callback.Run(app_to_uninstall,
+                 uninstaller_->UninstallApp(app_to_uninstall));
   }
 }
 
@@ -115,6 +117,11 @@
   task_factory_ = std::move(task_factory);
 }
 
+void PendingBookmarkAppManager::SetUninstallerForTesting(
+    std::unique_ptr<BookmarkAppUninstaller> uninstaller) {
+  uninstaller_ = std::move(uninstaller);
+}
+
 void PendingBookmarkAppManager::SetTimerForTesting(
     std::unique_ptr<base::OneShotTimer> timer) {
   timer_ = std::move(timer);
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
index 66d9e6e0..696de12 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
@@ -64,6 +64,8 @@
 
   void SetFactoriesForTesting(WebContentsFactory web_contents_factory,
                               TaskFactory task_factory);
+  void SetUninstallerForTesting(
+      std::unique_ptr<BookmarkAppUninstaller> uninstaller);
   void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer);
 
  private:
@@ -98,7 +100,7 @@
 
   Profile* profile_;
   web_app::AppRegistrar* registrar_;
-  BookmarkAppUninstaller uninstaller_;
+  std::unique_ptr<BookmarkAppUninstaller> uninstaller_;
   web_app::ExtensionIdsMap extension_ids_map_;
 
   WebContentsFactory web_contents_factory_;
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
index ea4a106..1c6000a3 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h"
 
+#include <map>
 #include <memory>
 #include <string>
 #include <utility>
@@ -15,7 +16,6 @@
 #include "base/scoped_observer.h"
 #include "base/test/bind_test_util.h"
 #include "base/timer/mock_timer.h"
-#include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/web_applications/components/app_registrar.h"
 #include "chrome/browser/web_applications/components/pending_app_manager.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
@@ -24,13 +24,7 @@
 #include "chrome/browser/web_applications/test/test_app_registrar.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/crx_file/id_util.h"
-#include "content/public/test/test_utils.h"
 #include "content/public/test/web_contents_tester.h"
-#include "extensions/browser/extension_prefs.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_registry_observer.h"
-#include "extensions/common/extension_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
@@ -78,47 +72,10 @@
   return info;
 }
 
-scoped_refptr<const Extension> CreateDummyExtension(const std::string& id) {
-  return ExtensionBuilder("Dummy name")
-      .SetLocation(Manifest::EXTERNAL_POLICY)
-      .SetID(id)
-      .Build();
-}
-
 std::string GenerateFakeAppId(const GURL& url) {
-  return crx_file::id_util::GenerateId("fake_app_id_for:" + url.spec());
+  return std::string("fake_app_id_for:") + url.spec();
 }
 
-class TestExtensionRegistryObserver : public ExtensionRegistryObserver {
- public:
-  explicit TestExtensionRegistryObserver(ExtensionRegistry* registry) {
-    extension_registry_observer_.Add(registry);
-  }
-
-  ~TestExtensionRegistryObserver() override = default;
-
-  const std::vector<std::string>& uninstalled_extension_ids() {
-    return uninstalled_extension_ids_;
-  }
-
-  void ResetResults() { uninstalled_extension_ids_.clear(); }
-
-  // ExtensionRegistryObserver
-  void OnExtensionUninstalled(content::BrowserContext* browser_context,
-                              const Extension* extension,
-                              UninstallReason reason) override {
-    uninstalled_extension_ids_.push_back(extension->id());
-  }
-
- private:
-  std::vector<std::string> uninstalled_extension_ids_;
-
-  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
-      extension_registry_observer_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(TestExtensionRegistryObserver);
-};
-
 class TestBookmarkAppInstallationTask : public BookmarkAppInstallationTask {
  public:
   TestBookmarkAppInstallationTask(Profile* profile,
@@ -139,8 +96,6 @@
     if (succeeds_) {
       result_code = web_app::InstallResultCode::kSuccess;
       app_id = GenerateFakeAppId(app_info().url);
-      ExtensionRegistry::Get(profile_)->AddEnabled(
-          CreateDummyExtension(app_id));
       extension_ids_map_.Insert(app_info().url, app_id,
                                 app_info().install_source);
       registrar_->AddAsInstalled(app_id);
@@ -166,6 +121,52 @@
   DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppInstallationTask);
 };
 
+class TestBookmarkAppUninstaller : public BookmarkAppUninstaller {
+ public:
+  TestBookmarkAppUninstaller(Profile* profile, web_app::AppRegistrar* registrar)
+      : BookmarkAppUninstaller(profile, registrar) {}
+
+  ~TestBookmarkAppUninstaller() override = default;
+
+  size_t uninstall_call_count() { return uninstall_call_count_; }
+
+  void ResetResults() {
+    uninstall_call_count_ = 0;
+    uninstalled_app_urls_.clear();
+  }
+
+  const std::vector<GURL>& uninstalled_app_urls() {
+    return uninstalled_app_urls_;
+  }
+
+  const GURL& last_uninstalled_app_url() { return uninstalled_app_urls_[0]; }
+
+  void SetNextResultForTesting(const GURL& app_url, bool result) {
+    DCHECK(!base::ContainsKey(next_result_map_, app_url));
+    next_result_map_[app_url] = result;
+  }
+
+  // BookmarkAppUninstaller
+  bool UninstallApp(const GURL& app_url) override {
+    DCHECK(base::ContainsKey(next_result_map_, app_url));
+
+    ++uninstall_call_count_;
+    uninstalled_app_urls_.push_back(app_url);
+
+    bool result = next_result_map_[app_url];
+    next_result_map_.erase(app_url);
+    return result;
+  }
+
+ private:
+  std::map<GURL, bool> next_result_map_;
+
+  size_t uninstall_call_count_ = 0;
+  std::vector<GURL> uninstalled_app_urls_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppUninstaller);
+};
+
 }  // namespace
 
 class PendingBookmarkAppManagerTest : public ChromeRenderViewHostTestHarness {
@@ -185,23 +186,11 @@
 
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
-    // CrxInstaller in BookmarkAppInstaller needs an ExtensionService, so
-    // create one for the profile.
-    TestExtensionSystem* test_system =
-        static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()));
-    test_system->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
-                                        profile()->GetPath(),
-                                        false /* autoupdate_enabled */);
-
-    test_extension_registry_observer_ =
-        std::make_unique<TestExtensionRegistryObserver>(
-            ExtensionRegistry::Get(profile()));
-
     registrar_ = std::make_unique<web_app::TestAppRegistrar>();
   }
 
   void TearDown() override {
-    test_extension_registry_observer_.reset();
+    uninstaller_ = nullptr;
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
@@ -258,7 +247,7 @@
     installation_task_run_count_ = 0;
     uninstall_callback_url_.reset();
     last_uninstall_successful_.reset();
-    test_extension_registry_observer_->ResetResults();
+    uninstaller_->ResetResults();
   }
 
   const PendingBookmarkAppManager::WebContentsFactory&
@@ -282,6 +271,15 @@
         profile(), registrar_.get());
     manager->SetFactoriesForTesting(test_web_contents_creator(),
                                     successful_installation_task_creator());
+
+    // The test suite doesn't support multiple uninstallers.
+    DCHECK_EQ(nullptr, uninstaller_);
+
+    auto uninstaller = std::make_unique<TestBookmarkAppUninstaller>(
+        profile(), registrar_.get());
+    uninstaller_ = uninstaller.get();
+    manager->SetUninstallerForTesting(std::move(uninstaller));
+
     return manager;
   }
 
@@ -324,17 +322,20 @@
     return last_uninstall_successful_.value();
   }
 
-  size_t uninstalls_count() {
-    return test_extension_registry_observer_->uninstalled_extension_ids()
-        .size();
+  size_t uninstall_call_count() { return uninstaller_->uninstall_call_count(); }
+
+  const std::vector<GURL>& uninstalled_app_urls() {
+    return uninstaller_->uninstalled_app_urls();
   }
 
-  const std::vector<std::string>& uninstalled_extension_ids() {
-    return test_extension_registry_observer_->uninstalled_extension_ids();
+  const GURL& last_uninstalled_app_url() {
+    return uninstaller_->last_uninstalled_app_url();
   }
 
   web_app::TestAppRegistrar* registrar() { return registrar_.get(); }
 
+  TestBookmarkAppUninstaller* uninstaller() { return uninstaller_; }
+
  private:
   content::WebContentsTester* web_contents_tester_ = nullptr;
   base::Optional<GURL> install_callback_url_;
@@ -342,8 +343,6 @@
   base::Optional<web_app::PendingAppManager::AppInfo> last_app_info_;
   size_t installation_task_run_count_ = 0;
 
-  std::unique_ptr<TestExtensionRegistryObserver>
-      test_extension_registry_observer_;
   base::Optional<GURL> uninstall_callback_url_;
   base::Optional<bool> last_uninstall_successful_;
 
@@ -352,6 +351,7 @@
   PendingBookmarkAppManager::TaskFactory failing_installation_task_creator_;
 
   std::unique_ptr<web_app::TestAppRegistrar> registrar_;
+  TestBookmarkAppUninstaller* uninstaller_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(PendingBookmarkAppManagerTest);
 };
@@ -951,17 +951,6 @@
   const std::string app_id = GenerateFakeAppId(GURL(kFooWebAppUrl));
   registrar()->RemoveAsInstalled(app_id);
 
-  // Trying to uninstall the app should fail and have no effect.
-  pending_app_manager->UninstallApps(
-      std::vector<GURL>{GURL(kFooWebAppUrl)},
-      base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
-                          base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(GURL(kFooWebAppUrl), uninstall_callback_url());
-  EXPECT_FALSE(last_uninstall_successful());
-  EXPECT_EQ(0u, uninstalls_count());
-
   // Try to install the app again.
   pending_app_manager->Install(
       GetFooAppInfo(),
@@ -995,18 +984,6 @@
   registrar()->AddAsExternalAppUninstalledByUser(app_id);
   registrar()->RemoveAsInstalled(app_id);
 
-  // Trying to uninstall the app should fail and have no effect.
-  pending_app_manager->UninstallApps(
-      std::vector<GURL>{GURL(kFooWebAppUrl)},
-      base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
-                          base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(GURL(kFooWebAppUrl), uninstall_callback_url());
-  EXPECT_FALSE(last_uninstall_successful());
-  EXPECT_EQ(0u, uninstalls_count());
-  ResetResults();
-
   // The extension was uninstalled by the user. Installing again should succeed
   // or fail depending on whether we set override_previous_user_uninstall. We
   // try with override_previous_user_uninstall false first, true second.
@@ -1030,68 +1007,48 @@
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Succeeds) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
-  pending_app_manager->Install(
-      GetFooAppInfo(),
-      base::BindOnce(&PendingBookmarkAppManagerTest::InstallCallback,
-                     base::Unretained(this)));
 
-  base::RunLoop().RunUntilIdle();
-  SuccessfullyLoad(GURL(kFooWebAppUrl));
-
-  EXPECT_TRUE(app_installed());
-  ResetResults();
-
+  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
   pending_app_manager->UninstallApps(
       std::vector<GURL>{GURL(kFooWebAppUrl)},
       base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
                           base::Unretained(this)));
-  // Uninstalling posts a task to the IO thread so we need to wait for all
-  // threads to finish.
-  content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(GURL(kFooWebAppUrl), uninstall_callback_url());
   EXPECT_TRUE(last_uninstall_successful());
-  EXPECT_EQ(1u, uninstalls_count());
-  EXPECT_EQ(std::vector<std::string>{GenerateFakeAppId(GURL(kFooWebAppUrl))},
-            uninstalled_extension_ids());
+  EXPECT_EQ(1u, uninstall_call_count());
+  EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+}
+
+TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Fails) {
+  auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
+
+  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false);
+  pending_app_manager->UninstallApps(
+      std::vector<GURL>{GURL(kFooWebAppUrl)},
+      base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
+                          base::Unretained(this)));
+
+  EXPECT_EQ(GURL(kFooWebAppUrl), uninstall_callback_url());
+  EXPECT_FALSE(last_uninstall_successful());
+  EXPECT_EQ(1u, uninstall_call_count());
+  EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
 }
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Multiple) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
-  std::vector<web_app::PendingAppManager::AppInfo> apps_to_install;
-  apps_to_install.push_back(GetFooAppInfo());
-  apps_to_install.push_back(GetBarAppInfo());
 
-  pending_app_manager->InstallApps(
-      std::move(apps_to_install),
-      base::BindRepeating(&PendingBookmarkAppManagerTest::InstallCallback,
-                          base::Unretained(this)));
-
-  // Finish the first install.
-  base::RunLoop().RunUntilIdle();
-  SuccessfullyLoad(GURL(kFooWebAppUrl));
-
-  ResetResults();
-
-  // Finish the second install.
-  base::RunLoop().RunUntilIdle();
-  SuccessfullyLoad(GURL(kBarWebAppUrl));
-
-  ResetResults();
-
+  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
+  uninstaller()->SetNextResultForTesting(GURL(kBarWebAppUrl), true);
   pending_app_manager->UninstallApps(
       std::vector<GURL>{GURL(kFooWebAppUrl), GURL(kBarWebAppUrl)},
       base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
                           base::Unretained(this)));
-  // Uninstalling posts a task to the IO thread so we need to wait for all
-  // threads to finish.
-  content::RunAllTasksUntilIdle();
 
   EXPECT_TRUE(last_uninstall_successful());
-  EXPECT_EQ(2u, uninstalls_count());
-  EXPECT_EQ(std::vector<std::string>({GenerateFakeAppId(GURL(kFooWebAppUrl)),
-                                      GenerateFakeAppId(GURL(kBarWebAppUrl))}),
-            uninstalled_extension_ids());
+  EXPECT_EQ(2u, uninstall_call_count());
+  EXPECT_EQ(std::vector<GURL>({GURL(kFooWebAppUrl), GURL(kBarWebAppUrl)}),
+            uninstalled_app_urls());
 }
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_PendingInstall) {
@@ -1100,16 +1057,16 @@
       GetFooAppInfo(),
       base::BindOnce(&PendingBookmarkAppManagerTest::InstallCallback,
                      base::Unretained(this)));
+
+  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false);
   pending_app_manager->UninstallApps(
       std::vector<GURL>{GURL(kFooWebAppUrl)},
       base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
                           base::Unretained(this)));
 
-  // Uninstallation runs synchronously and since the app was not installed yet
-  // it fails.
   EXPECT_EQ(GURL(kFooWebAppUrl), uninstall_callback_url());
   EXPECT_FALSE(last_uninstall_successful());
-  EXPECT_EQ(0u, uninstalls_count());
+  EXPECT_EQ(1u, uninstall_call_count());
 
   base::RunLoop().RunUntilIdle();
   SuccessfullyLoad(GURL(kFooWebAppUrl));
@@ -1117,42 +1074,4 @@
   EXPECT_TRUE(app_installed());
 }
 
-// Tests that uninstalling an app doesn't remove all previously installed apps.
-TEST_F(PendingBookmarkAppManagerTest, UninstallApps_TwoPreviouslyInstalled) {
-  auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
-  std::vector<web_app::PendingAppManager::AppInfo> apps_to_install;
-  apps_to_install.push_back(GetFooAppInfo());
-  apps_to_install.push_back(GetBarAppInfo());
-
-  pending_app_manager->InstallApps(
-      std::move(apps_to_install),
-      base::BindRepeating(&PendingBookmarkAppManagerTest::InstallCallback,
-                          base::Unretained(this)));
-
-  // Finish the first install.
-  base::RunLoop().RunUntilIdle();
-  SuccessfullyLoad(GURL(kFooWebAppUrl));
-
-  ResetResults();
-
-  // Finish the second install.
-  base::RunLoop().RunUntilIdle();
-  SuccessfullyLoad(GURL(kBarWebAppUrl));
-
-  ResetResults();
-
-  pending_app_manager->UninstallApps(
-      std::vector<GURL>{GURL(kFooWebAppUrl)},
-      base::BindRepeating(&PendingBookmarkAppManagerTest::UninstallCallback,
-                          base::Unretained(this)));
-  // Uninstalling posts a task to the IO thread so we need to wait for all
-  // threads to finish.
-  content::RunAllTasksUntilIdle();
-
-  EXPECT_TRUE(last_uninstall_successful());
-  EXPECT_EQ(1u, uninstalls_count());
-  EXPECT_EQ(std::vector<std::string>({GenerateFakeAppId(GURL(kFooWebAppUrl))}),
-            uninstalled_extension_ids());
-}
-
 }  // namespace extensions
diff --git a/chrome/services/app_service/README.md b/chrome/services/app_service/README.md
index 36bcd38..12a0cdd1 100644
--- a/chrome/services/app_service/README.md
+++ b/chrome/services/app_service/README.md
@@ -29,18 +29,18 @@
 provides to Consumers a uniform API over the various Provider implementations,
 for these aspects:
 
-- App Registry: list the installed apps.
-- App Icon Factory: load an app's icon, at various resolutions.
-- App Runner: launch apps and track app instances.
-- App Installer: install, uninstall and update apps.
-- App Coordinator: keep system-wide settings, e.g. default handlers.
+  - App Registry: list the installed apps.
+  - App Icon Factory: load an app's icon, at various resolutions.
+  - App Runner: launch apps and track app instances.
+  - App Installer: install, uninstall and update apps.
+  - App Coordinator: keep system-wide settings, e.g. default handlers.
 
 Some things are still the responsbility of individual Consumers or Providers.
 For example, the order in which the apps' icons are presented in the launcher
 is a launcher-specific detail, not a system-wide detail, and is managed by the
-launcher, not the App Service. Similarly, Android-specific VM configuration is
-Android-specific, not generalizable system-wide, and is managed by the Android
-provider (ARC++).
+launcher, not the App Service. Similarly, Android-specific VM (Virtual Machine)
+configuration is Android-specific, not generalizable system-wide, and is
+managed by the Android provider (ARC++).
 
 
 ## Profiles
@@ -271,20 +271,6 @@
 (monotonically increasing) epoch number so that an icon update results in a
 different `u_key` and hence a different `IconKey`.
 
-Grouping the `IconKey` with the other `LoadIcon` arguments, the combination
-identifies a static (unchanging, but possibly obsolete) image: if a new version
-of an app results in a new icon, or if a change in app state results in a
-grayed out icon, this is represented by a different `IconKey`, such as a
-different `u_key` or `icon_effects` value. As a consequence, the combined
-`LoadIcon` arguments can be used to key a cache or map of `IconValue`s, or to
-recognize and coalesce multiple concurrent requests to the same combination.
-
-Consumers (via the `AppServiceProxy`) can always ask the `AppService` to load
-an icon. As an optimization, if the `AppServiceProxy` knows how to load an icon
-for a given `IconKey`, it can skip the Mojo round trip and bulk data IPC and
-load it directly instead. For example, it may know how to load icons from a
-statically built resource ID.
-
     interface AppService {
       // App Icon Factory methods.
       LoadIcon(
@@ -331,6 +317,53 @@
     };
 
 
+## Icon Changes
+
+Apps can change their icons, e.g. after a new version is installed. From the
+App Service's point of view, an icon change is like any other change: Providers
+broadcast an `App` value representing what's changed (icon or otherwise) about
+an app, the Proxy's `AppRegistryCache` enriches this `App` struct to be an
+`AppUpdate`, and `AppRegistryCache` observers can, if that `AppUpdate` shows
+that the icon has changed, issue a new `LoadIcon` Mojo call. A new Mojo call is
+necessary, because a Mojo callback is a `base::OnceCallback`, so the same
+callback can't be used for both the old and the new icon.
+
+
+## Caching and Other Optimizations
+
+Grouping the `IconKey` with the other `LoadIcon` arguments, the combination
+identifies a static (unchanging, but possibly obsolete) image: if a new version
+of an app results in a new icon, or if a change in app state results in a
+grayed out icon, this is represented by a different `IconKey`, such as a
+different `u_key` or `icon_effects` value. As a consequence, the combined
+`LoadIcon` arguments can be used to key a cache or map of `IconValue`s, or to
+recognize and coalesce multiple concurrent requests to the same combination.
+
+Such optimizations can be implemented as a series of "wrapper" classes (as in
+the classic "decorator" or "wrapper" design pattern) that all implement the
+same C++ interface (an `IconLoader` interface). They add their specific feature
+(e.g. caching) by wrapping another `IconLoader`, doing feature-specific work on
+every call or reply before sending the call forward or the reply backward.
+
+There may be multiple caches, as there may be multiple cache eviction policies
+(also known as garbage collection policies), spanning the trade-off from
+favoring minimizing memory use to favoring maximizing cache hit rates. The
+Proxy may have a single cache, with a relatively aggressive eviction policy,
+which applies to all of its Consumer clients. A Consumer might have an
+additional Consumer-specific cache, with a more relaxed eviction policy, if it
+has additional Consumer-specific UI signals to guide when icon-loading requests
+and cache hits are more or less likely.
+
+Note that cache values (the `IconValue` Mojo struct) are, primarily, a
+gfx.mojom.ImageSkia, which are cheap to share. Copying an ImageSkia value does
+not duplicate any underlying pixel buffers.
+
+As a separate optimization, if the `AppServiceProxy` knows how to load an icon
+for a given `IconKey`, it can skip the Mojo round trip and bulk data IPC and
+load it directly instead. For example, it may know how to load icons from a
+statically built resource ID.
+
+
 ## Placeholder Icons
 
 It can take some time for `Publisher`s to provide an icon. For example, loading
@@ -357,9 +390,42 @@
 placeholder. That field should only be true if the corresponding `LoadIcon`
 call had `allow_placeholder_icon` true. When the `LoadIcon` caller receives a
 placeholder icon, it is up to the caller to issue a new `LoadIcon` call, this
-time with `allow_placeholder_icon` false. A new Mojo call is necessary, because
-a Mojo callback is a `base::OnceCallback`, so the same callback can't be used
-for both the placeholder and the real icon.
+time with `allow_placeholder_icon` false. As before, a new Mojo call is
+necessary, because a Mojo callback is a `base::OnceCallback`, so the same
+callback can't be used for both the placeholder and the real icon.
+
+
+## Provider-Specific Subtleties
+
+Some concerns (like caching and coalescing multiple in-flight calls with the
+same `IconKey`) are not specific to any particular Providers like ARC++ or
+Crostini, and can be solved by the Proxy.
+
+Other concerns are Provider-specific, and are generally solved in Provider
+implementations, albeit often with non-Provider-specific support (such as for
+placeholder icons, discussed above). Such concerns include:
+
+  - Multiple icon sources: some icons for built-in VM-based apps (e.g. ARC++ or
+    Crostini) should be served from a compiled-into-the-browser resource
+    instead of from the VM.
+  - Pending LoadIcon calls: some `LoadIcon` calls might need to wait on
+    bringing up a VM.
+  - Potential on-disk corruption: for whatever reason, an on-disk file that's
+    meant to hold a cached icon may be missing or invalid. In that case, the
+    Provider should still provide a (placeholder) icon, and trigger
+    Provider-specific clean-up and re-load of the real app icon.
+
+All of these concerns listed should be straightforward to handle, and don't
+invalidate the overall App Service `Publisher.LoadIcon` Mojo design, including
+its non-Provider-specific caching and other optimization layers.
+
+There are also yet another category of concerns that are Provider-specific, but
+also outside the purview of the App Service. For example, the file system
+layout of ARC++'s on-disk icon cache is, from the App Service's point of view,
+considered a private ARC++ implementation detail. As long as ARC++'s API
+remains the same, and if ARC++ can notify the App Service if the App Service
+needs to reload any or all icons, then any change in ARC++'s file system layout
+isn't a direct concern to the App Service.
 
 
 # App Runner
@@ -417,4 +483,4 @@
 
 ---
 
-Updated on 2019-03-07.
+Updated on 2019-03-15.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d262b47..87f264276 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -980,6 +980,7 @@
       "../browser/ui/permission_bubble/permission_bubble_browser_test_util.h",
       "../browser/ui/prefs/prefs_tab_helper_browsertest.cc",
       "../browser/ui/profile_error_browsertest.cc",
+      "../browser/ui/renderer_event_injection_browsertest.cc",
       "../browser/ui/search/instant_test_base.cc",
       "../browser/ui/search/instant_test_base.h",
       "../browser/ui/search/instant_test_utils.cc",
diff --git a/chrome/test/data/extensions/api_test/activity_log_private/test/test.js b/chrome/test/data/extensions/api_test/activity_log_private/test/test.js
index 6774e9b..cc1dbc9 100644
--- a/chrome/test/data/extensions/api_test/activity_log_private/test/test.js
+++ b/chrome/test/data/extensions/api_test/activity_log_private/test/test.js
@@ -453,7 +453,6 @@
 // Listener to check the expected logging is done in the test cases.
 var testCaseIndx = 0;
 var callIndx = -1;
-var enabledTestCases = [];
 var blinkArgs = {
   'blinkRequestResource': 2,
   'blinkSetAttribute': 3
@@ -473,7 +472,7 @@
         apiCall += ' ' + args.join(' ');
       }
       expectedCall = 'runtime.onMessageExternal';
-      var testCase = enabledTestCases[testCaseIndx];
+      var testCase = testCases[testCaseIndx];
       if (callIndx > -1) {
         expectedCall = testCase.expected_activity[callIndx];
       }
@@ -504,37 +503,4 @@
     }
 );
 
-function setupTestCasesAndRun() {
-  chrome.test.getConfig(function(config) {
-    chrome.runtime.getPlatformInfo(function(info) {
-      var tests = [];
-      for (var i = 0; i < testCases.length; i++) {
-        // Ignore test case if disabled for this OS.
-        if (testCases[i].disabled != undefined &&
-            info.os in testCases[i].disabled &&
-            testCases[i].disabled[info.os]) {
-          console.log('Test case disabled for this OS: ' + info.os);
-          continue;
-        }
-
-        // Add the test case to the enabled list and set the expected activity
-        // appriorate for this OS.
-        if (testCases[i].func != undefined) {
-          tests.push(testCases[i].func);
-          var enabledTestCase = testCases[i];
-          var activityListForOS = 'expected_activity_' + info.os;
-          if (activityListForOS in enabledTestCase) {
-            console.log('Expecting OS specific activity for: ' + info.os);
-            enabledTestCase.expected_activity =
-                enabledTestCase[activityListForOS];
-          }
-
-          enabledTestCases.push(enabledTestCase);
-        }
-      }
-      chrome.test.runTests(tests);
-    });
-  });
-}
-
-setupTestCasesAndRun();
+chrome.test.runTests(testCases.map(testCase => testCase.func));
diff --git a/chrome/test/data/webui/extensions/activity_log_stream_item_test.js b/chrome/test/data/webui/extensions/activity_log_stream_item_test.js
index 6ec5d12e..d9623b5 100644
--- a/chrome/test/data/webui/extensions/activity_log_stream_item_test.js
+++ b/chrome/test/data/webui/extensions/activity_log_stream_item_test.js
@@ -43,8 +43,11 @@
       function() {
         Polymer.dom.flush();
 
-        testVisible('#activity-item-main-row', true);
-        testVisible('cr-expand-button', false);
+        testVisible('cr-expand-button', true);
+
+        // Since |cr-expand-button| is always visible, we test that the
+        // |cr-icon-button| within is not visible.
+        testVisible('cr-icon-button', false);
       });
 
   test(
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc
index 98e2b8cb..b33df97 100644
--- a/chromeos/constants/chromeos_switches.cc
+++ b/chromeos/constants/chromeos_switches.cc
@@ -647,5 +647,10 @@
   return base::CommandLine::ForCurrentProcess()->HasSwitch(kOobeSkipPostLogin);
 }
 
+bool IsGaiaServicesDisabled() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      kDisableGaiaServices);
+}
+
 }  // namespace switches
 }  // namespace chromeos
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h
index c78173a47..9bf1260 100644
--- a/chromeos/constants/chromeos_switches.h
+++ b/chromeos/constants/chromeos_switches.h
@@ -292,6 +292,9 @@
 // Returns true if we should skip all other OOBE pages after user login.
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldSkipOobePostLogin();
 
+// Returns true if GAIA services has been disabled.
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsGaiaServicesDisabled();
+
 }  // namespace switches
 }  // namespace chromeos
 
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn
index d287296..ac0dbe0 100644
--- a/chromeos/services/device_sync/BUILD.gn
+++ b/chromeos/services/device_sync/BUILD.gn
@@ -53,6 +53,8 @@
     "cryptauth_v2_enroller.h",
     "cryptauth_v2_enroller_impl.cc",
     "cryptauth_v2_enroller_impl.h",
+    "cryptauth_v2_enrollment_manager_impl.cc",
+    "cryptauth_v2_enrollment_manager_impl.h",
     "device_sync_base.cc",
     "device_sync_base.h",
     "device_sync_impl.cc",
@@ -179,6 +181,7 @@
     "cryptauth_key_registry_impl_unittest.cc",
     "cryptauth_key_unittest.cc",
     "cryptauth_v2_enroller_impl_unittest.cc",
+    "cryptauth_v2_enrollment_manager_impl_unittest.cc",
     "device_sync_service_unittest.cc",
     "network_aware_enrollment_scheduler_unittest.cc",
     "persistent_enrollment_scheduler_unittest.cc",
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_manager.h b/chromeos/services/device_sync/cryptauth_enrollment_manager.h
index d3a514a..3106d19 100644
--- a/chromeos/services/device_sync/cryptauth_enrollment_manager.h
+++ b/chromeos/services/device_sync/cryptauth_enrollment_manager.h
@@ -47,6 +47,9 @@
   // enrollment is already in progress, this function does nothing.
   // |invocation_reason| specifies the reason that the enrollment was triggered,
   // which is upload to the server.
+  // TODO(nohle): Change cryptauth::InvocationReason to
+  // cryptauthv2::ClientMetadata::InvocationReason when CryptAuth v1 is
+  // obsolete.
   virtual void ForceEnrollmentNow(
       cryptauth::InvocationReason invocation_reason) = 0;
 
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h b/chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h
index 81063dc..3a1b9a1c 100644
--- a/chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h
+++ b/chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h
@@ -35,6 +35,22 @@
 class CryptAuthEnrollerFactory;
 
 // Concrete CryptAuthEnrollmentManager implementation.
+//
+// This implementation considers three sources of enrollment requests:
+//  1) A sync scheduler requests periodic enrollments and handles any failed
+//     attempts.
+//  2) The enrollment manager listens to the GCM manager for re-enrollment
+//     requests.
+//  3) The ForceEnrollmentNow() method allows for immediate requests.
+//
+// When an enrollment has been requested, this implementation generates a user
+// key pair, if one doesn't already exists, and persists these keys as
+// preferences. Thus, the user key pair should never rotate.
+//
+// This implementation also determines the times between enrollment attempts,
+// which is roughly 30 days after a successful enrollments and 10 minutes after
+// a failed enrollment attempt, exponentially increasing for consecutive
+// failures. An enrollment is considered "invalid" after 45 days.
 class CryptAuthEnrollmentManagerImpl : public CryptAuthEnrollmentManager,
                                        public SyncScheduler::Delegate,
                                        public CryptAuthGCMManager::Observer {
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.cc b/chromeos/services/device_sync/cryptauth_enrollment_result.cc
index 0c85864..d1e5fb6 100644
--- a/chromeos/services/device_sync/cryptauth_enrollment_result.cc
+++ b/chromeos/services/device_sync/cryptauth_enrollment_result.cc
@@ -145,6 +145,12 @@
       stream << "[Error: Could not retrieve ClientAppMetadata from "
              << "ClientAppMetadataProvider]";
       break;
+    case ResultCode::kErrorTimeoutWaitingForGcmRegistration:
+      stream << "[Error: Timeout waiting for GCM registration]";
+      break;
+    case ResultCode::kErrorTimeoutWaitingForClientAppMetadata:
+      stream << "[Error: Timeout waiting for ClientAppMetadata]";
+      break;
   }
 
   return stream;
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.h b/chromeos/services/device_sync/cryptauth_enrollment_result.h
index 0213753..ea420336 100644
--- a/chromeos/services/device_sync/cryptauth_enrollment_result.h
+++ b/chromeos/services/device_sync/cryptauth_enrollment_result.h
@@ -97,7 +97,11 @@
     // requesting it to re-enroll or re-sync.
     kErrorGcmRegistrationFailed,
     // Could not retrieve ClientAppMetadata from ClientAppMetadataProvider.
-    kErrorClientAppMetadataFetchFailed
+    kErrorClientAppMetadataFetchFailed,
+    // The enrollment manager timed out waiting for GCM registration.
+    kErrorTimeoutWaitingForGcmRegistration,
+    // The enrollment manager timed out waiting for ClientAppMetadata.
+    kErrorTimeoutWaitingForClientAppMetadata
   };
 
   CryptAuthEnrollmentResult(
diff --git a/chromeos/services/device_sync/cryptauth_key_registry_impl.cc b/chromeos/services/device_sync/cryptauth_key_registry_impl.cc
index 17c246d5..56f0fa0 100644
--- a/chromeos/services/device_sync/cryptauth_key_registry_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_key_registry_impl.cc
@@ -33,6 +33,8 @@
   test_factory_ = test_factory;
 }
 
+CryptAuthKeyRegistryImpl::Factory::~Factory() = default;
+
 std::unique_ptr<CryptAuthKeyRegistry>
 CryptAuthKeyRegistryImpl::Factory::BuildInstance(PrefService* pref_service) {
   return base::WrapUnique(new CryptAuthKeyRegistryImpl(pref_service));
diff --git a/chromeos/services/device_sync/cryptauth_key_registry_impl.h b/chromeos/services/device_sync/cryptauth_key_registry_impl.h
index 3bc7dabc..3de3df1a 100644
--- a/chromeos/services/device_sync/cryptauth_key_registry_impl.h
+++ b/chromeos/services/device_sync/cryptauth_key_registry_impl.h
@@ -26,6 +26,7 @@
    public:
     static Factory* Get();
     static void SetFactoryForTesting(Factory* test_factory);
+    virtual ~Factory();
     virtual std::unique_ptr<CryptAuthKeyRegistry> BuildInstance(
         PrefService* pref_service);
 
@@ -41,7 +42,7 @@
  private:
   // Populates the in-memory key bundle map with the enrolled key bundles
   // persisted in a pref.
-  CryptAuthKeyRegistryImpl(PrefService* pref_service);
+  explicit CryptAuthKeyRegistryImpl(PrefService* pref_service);
 
   // CryptAuthKeyRegistry:
   void OnKeyRegistryUpdated() override;
diff --git a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
new file mode 100644
index 0000000..7143de5
--- /dev/null
+++ b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
@@ -0,0 +1,551 @@
+// Copyright 2019 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 "chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h"
+
+#include <utility>
+
+#include "base/base64url.h"
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
+#include "base/time/clock.h"
+#include "base/timer/timer.h"
+#include "chromeos/components/multidevice/logging/logging.h"
+#include "chromeos/services/device_sync/cryptauth_constants.h"
+#include "chromeos/services/device_sync/cryptauth_key_registry.h"
+#include "chromeos/services/device_sync/cryptauth_v2_enroller_impl.h"
+#include "chromeos/services/device_sync/network_aware_enrollment_scheduler.h"
+#include "chromeos/services/device_sync/pref_names.h"
+#include "chromeos/services/device_sync/public/cpp/client_app_metadata_provider.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+
+namespace chromeos {
+
+namespace device_sync {
+
+namespace {
+
+cryptauthv2::ClientMetadata::InvocationReason ConvertInvocationReasonV1ToV2(
+    cryptauth::InvocationReason invocation_reason_v1) {
+  switch (invocation_reason_v1) {
+    case cryptauth::InvocationReason::INVOCATION_REASON_UNKNOWN:
+      return cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED;
+    case cryptauth::InvocationReason::INVOCATION_REASON_INITIALIZATION:
+      return cryptauthv2::ClientMetadata::INITIALIZATION;
+    case cryptauth::InvocationReason::INVOCATION_REASON_PERIODIC:
+      return cryptauthv2::ClientMetadata::PERIODIC;
+    case cryptauth::InvocationReason::INVOCATION_REASON_SLOW_PERIODIC:
+      return cryptauthv2::ClientMetadata::SLOW_PERIODIC;
+    case cryptauth::InvocationReason::INVOCATION_REASON_FAST_PERIODIC:
+      return cryptauthv2::ClientMetadata::FAST_PERIODIC;
+    case cryptauth::InvocationReason::INVOCATION_REASON_EXPIRATION:
+      return cryptauthv2::ClientMetadata::EXPIRATION;
+    case cryptauth::InvocationReason::INVOCATION_REASON_FAILURE_RECOVERY:
+      return cryptauthv2::ClientMetadata::FAILURE_RECOVERY;
+    case cryptauth::InvocationReason::INVOCATION_REASON_NEW_ACCOUNT:
+      return cryptauthv2::ClientMetadata::NEW_ACCOUNT;
+    case cryptauth::InvocationReason::INVOCATION_REASON_CHANGED_ACCOUNT:
+      return cryptauthv2::ClientMetadata::CHANGED_ACCOUNT;
+    case cryptauth::InvocationReason::INVOCATION_REASON_FEATURE_TOGGLED:
+      return cryptauthv2::ClientMetadata::FEATURE_TOGGLED;
+    case cryptauth::InvocationReason::INVOCATION_REASON_SERVER_INITIATED:
+      return cryptauthv2::ClientMetadata::SERVER_INITIATED;
+    case cryptauth::InvocationReason::INVOCATION_REASON_ADDRESS_CHANGE:
+      return cryptauthv2::ClientMetadata::ADDRESS_CHANGE;
+    case cryptauth::InvocationReason::INVOCATION_REASON_SOFTWARE_UPDATE:
+      return cryptauthv2::ClientMetadata::SOFTWARE_UPDATE;
+    case cryptauth::InvocationReason::INVOCATION_REASON_MANUAL:
+      return cryptauthv2::ClientMetadata::MANUAL;
+    default:
+      PA_LOG(WARNING) << "Unknown v1 invocation reason: "
+                      << invocation_reason_v1;
+      return cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED;
+  }
+}
+
+// Timeout values for asynchronous operations.
+// TODO(https://crbug.com/933656): Tune these values.
+constexpr base::TimeDelta kWaitingForGcmRegistrationTimeout =
+    base::TimeDelta::FromSeconds(10);
+constexpr base::TimeDelta kWaitingForClientAppMetadataTimeout =
+    base::TimeDelta::FromSeconds(10);
+
+}  // namespace
+
+// static
+CryptAuthV2EnrollmentManagerImpl::Factory*
+    CryptAuthV2EnrollmentManagerImpl::Factory::test_factory_ = nullptr;
+
+// static
+CryptAuthV2EnrollmentManagerImpl::Factory*
+CryptAuthV2EnrollmentManagerImpl::Factory::Get() {
+  if (test_factory_)
+    return test_factory_;
+
+  static base::NoDestructor<CryptAuthV2EnrollmentManagerImpl::Factory> factory;
+  return factory.get();
+}
+
+// static
+void CryptAuthV2EnrollmentManagerImpl::Factory::SetFactoryForTesting(
+    Factory* test_factory) {
+  test_factory_ = test_factory;
+}
+
+// static
+void CryptAuthV2EnrollmentManagerImpl::RegisterPrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterIntegerPref(
+      prefs::kCryptAuthEnrollmentFailureRecoveryInvocationReason,
+      cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED);
+
+  // TODO(nohle): Remove when v1 Enrollment is deprecated.
+  registry->RegisterStringPref(prefs::kCryptAuthEnrollmentUserPublicKey,
+                               std::string());
+  registry->RegisterStringPref(prefs::kCryptAuthEnrollmentUserPrivateKey,
+                               std::string());
+}
+
+// static
+// Note: The enroller handles timeouts internally.
+base::Optional<base::TimeDelta>
+CryptAuthV2EnrollmentManagerImpl::GetTimeoutForState(State state) {
+  switch (state) {
+    case State::kWaitingForGcmRegistration:
+      return kWaitingForGcmRegistrationTimeout;
+    case State::kWaitingForClientAppMetadata:
+      return kWaitingForClientAppMetadataTimeout;
+    default:
+      // Signifies that there should not be a timeout.
+      return base::nullopt;
+  }
+}
+
+// static
+base::Optional<CryptAuthEnrollmentResult::ResultCode>
+CryptAuthV2EnrollmentManagerImpl::ResultCodeErrorFromState(State state) {
+  switch (state) {
+    case State::kWaitingForGcmRegistration:
+      return CryptAuthEnrollmentResult::ResultCode::
+          kErrorTimeoutWaitingForGcmRegistration;
+    case State::kWaitingForClientAppMetadata:
+      return CryptAuthEnrollmentResult::ResultCode::
+          kErrorTimeoutWaitingForClientAppMetadata;
+    default:
+      return base::nullopt;
+  }
+}
+
+CryptAuthV2EnrollmentManagerImpl::Factory::~Factory() = default;
+
+std::unique_ptr<CryptAuthEnrollmentManager>
+CryptAuthV2EnrollmentManagerImpl::Factory::BuildInstance(
+    ClientAppMetadataProvider* client_app_metadata_provider,
+    CryptAuthKeyRegistry* key_registry,
+    CryptAuthClientFactory* client_factory,
+    CryptAuthGCMManager* gcm_manager,
+    PrefService* pref_service,
+    base::Clock* clock,
+    std::unique_ptr<base::OneShotTimer> timer) {
+  return base::WrapUnique(new CryptAuthV2EnrollmentManagerImpl(
+      client_app_metadata_provider, key_registry, client_factory, gcm_manager,
+      pref_service, clock, std::move(timer)));
+}
+
+CryptAuthV2EnrollmentManagerImpl::CryptAuthV2EnrollmentManagerImpl(
+    ClientAppMetadataProvider* client_app_metadata_provider,
+    CryptAuthKeyRegistry* key_registry,
+    CryptAuthClientFactory* client_factory,
+    CryptAuthGCMManager* gcm_manager,
+    PrefService* pref_service,
+    base::Clock* clock,
+    std::unique_ptr<base::OneShotTimer> timer)
+    : client_app_metadata_provider_(client_app_metadata_provider),
+      key_registry_(key_registry),
+      client_factory_(client_factory),
+      gcm_manager_(gcm_manager),
+      pref_service_(pref_service),
+      clock_(clock),
+      timer_(std::move(timer)),
+      weak_ptr_factory_(this) {
+  // TODO(nohle): Remove when v1 Enrollment is deprecated.
+  AddV1UserKeyPairToRegistryIfNecessary();
+}
+
+CryptAuthV2EnrollmentManagerImpl::~CryptAuthV2EnrollmentManagerImpl() {
+  gcm_manager_->RemoveObserver(this);
+}
+
+void CryptAuthV2EnrollmentManagerImpl::Start() {
+  // Ensure that Start() is only called once.
+  DCHECK(!scheduler_);
+
+  scheduler_ = NetworkAwareEnrollmentScheduler::Factory::Get()->BuildInstance(
+      this, pref_service_);
+
+  gcm_manager_->AddObserver(this);
+}
+
+void CryptAuthV2EnrollmentManagerImpl::ForceEnrollmentNow(
+    cryptauth::InvocationReason invocation_reason) {
+  if (state_ != State::kIdle) {
+    PA_LOG(WARNING) << "ForceEnrollmentNow() called while an enrollment is in "
+                    << "progress. No action taken.";
+    return;
+  }
+
+  current_enrollment_invocation_reason_ =
+      ConvertInvocationReasonV1ToV2(invocation_reason);
+
+  scheduler_->RequestEnrollmentNow();
+}
+
+bool CryptAuthV2EnrollmentManagerImpl::IsEnrollmentValid() const {
+  base::Optional<base::Time> last_successful_enrollment_time =
+      scheduler_->GetLastSuccessfulEnrollmentTime();
+
+  if (!last_successful_enrollment_time)
+    return false;
+
+  return (clock_->Now() - *last_successful_enrollment_time) <
+         scheduler_->GetRefreshPeriod();
+}
+
+base::Time CryptAuthV2EnrollmentManagerImpl::GetLastEnrollmentTime() const {
+  base::Optional<base::Time> last_successful_enrollment_time =
+      scheduler_->GetLastSuccessfulEnrollmentTime();
+
+  if (!last_successful_enrollment_time)
+    return base::Time();
+
+  return *last_successful_enrollment_time;
+}
+
+base::TimeDelta CryptAuthV2EnrollmentManagerImpl::GetTimeToNextAttempt() const {
+  return scheduler_->GetTimeToNextEnrollmentRequest();
+}
+
+bool CryptAuthV2EnrollmentManagerImpl::IsEnrollmentInProgress() const {
+  return state_ != State::kIdle;
+}
+
+bool CryptAuthV2EnrollmentManagerImpl::IsRecoveringFromFailure() const {
+  return scheduler_->GetNumConsecutiveFailures() > 0;
+}
+
+std::string CryptAuthV2EnrollmentManagerImpl::GetUserPublicKey() const {
+  const CryptAuthKey* user_key_pair =
+      key_registry_->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
+
+  // If a v1 key exists, it should have been added to the v2 registry already by
+  // AddV1UserKeyPairToRegistryIfNecessary().
+  DCHECK(
+      GetV1UserPublicKey().empty() ||
+      (user_key_pair && user_key_pair->public_key() == GetV1UserPublicKey()));
+
+  if (!user_key_pair)
+    return std::string();
+
+  return user_key_pair->public_key();
+}
+
+std::string CryptAuthV2EnrollmentManagerImpl::GetUserPrivateKey() const {
+  const CryptAuthKey* user_key_pair =
+      key_registry_->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
+  std::string private_key_v1 = GetV1UserPrivateKey();
+
+  // If a v1 key exists, it should have been added to the v2 registry already by
+  // AddV1UserKeyPairToRegistryIfNecessary().
+  DCHECK(
+      GetV1UserPrivateKey().empty() ||
+      (user_key_pair && user_key_pair->private_key() == GetV1UserPrivateKey()));
+
+  if (!user_key_pair)
+    return std::string();
+
+  return user_key_pair->private_key();
+}
+
+void CryptAuthV2EnrollmentManagerImpl::OnEnrollmentRequested(
+    const base::Optional<cryptauthv2::PolicyReference>&
+        client_directive_policy_reference) {
+  DCHECK(state_ == State::kIdle);
+
+  NotifyEnrollmentStarted();
+
+  client_directive_policy_reference_ = client_directive_policy_reference;
+
+  base::Optional<cryptauthv2::ClientMetadata::InvocationReason>
+      failure_recovery_invocation_reason =
+          GetFailureRecoveryInvocationReasonFromPref();
+
+  if (current_enrollment_invocation_reason_) {
+    // The invocation reason has already been set by ForceEnrollmentNow().
+  } else if (failure_recovery_invocation_reason) {
+    DCHECK(IsRecoveringFromFailure());
+    current_enrollment_invocation_reason_ = *failure_recovery_invocation_reason;
+  } else if (GetLastEnrollmentTime().is_null()) {
+    current_enrollment_invocation_reason_ =
+        cryptauthv2::ClientMetadata::INITIALIZATION;
+  } else if (!IsEnrollmentValid()) {
+    current_enrollment_invocation_reason_ =
+        cryptauthv2::ClientMetadata::PERIODIC;
+  } else {
+    current_enrollment_invocation_reason_ =
+        cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED;
+  }
+
+  // TODO(http://crbug.com/940944): [Metrics] Log invocation reason.
+
+  AttemptEnrollment();
+}
+
+void CryptAuthV2EnrollmentManagerImpl::OnGCMRegistrationResult(bool success) {
+  if (state_ != State::kWaitingForGcmRegistration)
+    return;
+
+  if (!success || gcm_manager_->GetRegistrationId().empty()) {
+    OnEnrollmentFinished(CryptAuthEnrollmentResult(
+        CryptAuthEnrollmentResult::ResultCode::kErrorGcmRegistrationFailed,
+        base::nullopt /* client_directive */));
+    return;
+  }
+
+  AttemptEnrollment();
+}
+
+void CryptAuthV2EnrollmentManagerImpl::OnReenrollMessage() {
+  ForceEnrollmentNow(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
+}
+
+void CryptAuthV2EnrollmentManagerImpl::OnClientAppMetadataFetched(
+    const base::Optional<cryptauthv2::ClientAppMetadata>& client_app_metadata) {
+  DCHECK(state_ == State::kWaitingForClientAppMetadata);
+
+  if (!client_app_metadata) {
+    OnEnrollmentFinished(
+        CryptAuthEnrollmentResult(CryptAuthEnrollmentResult::ResultCode::
+                                      kErrorClientAppMetadataFetchFailed,
+                                  base::nullopt /* client_directive */));
+    return;
+  }
+
+  client_app_metadata_ = client_app_metadata;
+
+  AttemptEnrollment();
+}
+
+void CryptAuthV2EnrollmentManagerImpl::AttemptEnrollment() {
+  if (gcm_manager_->GetRegistrationId().empty()) {
+    SetState(State::kWaitingForGcmRegistration);
+    gcm_manager_->RegisterWithGCM();
+    return;
+  }
+
+  if (!client_app_metadata_) {
+    SetState(State::kWaitingForClientAppMetadata);
+    client_app_metadata_provider_->GetClientAppMetadata(
+        gcm_manager_->GetRegistrationId(),
+        base::BindOnce(
+            &CryptAuthV2EnrollmentManagerImpl::OnClientAppMetadataFetched,
+            weak_ptr_factory_.GetWeakPtr()));
+    return;
+  }
+
+  Enroll();
+}
+
+void CryptAuthV2EnrollmentManagerImpl::Enroll() {
+  cryptauthv2::ClientMetadata client_metadata;
+  client_metadata.set_retry_count(scheduler_->GetNumConsecutiveFailures());
+  client_metadata.set_invocation_reason(*current_enrollment_invocation_reason_);
+
+  enroller_ = CryptAuthV2EnrollerImpl::Factory::Get()->BuildInstance(
+      key_registry_, client_factory_);
+
+  SetState(State::kWaitingForEnrollment);
+
+  enroller_->Enroll(
+      client_metadata, *client_app_metadata_,
+      client_directive_policy_reference_,
+      base::BindOnce(&CryptAuthV2EnrollmentManagerImpl::OnEnrollmentFinished,
+                     base::Unretained(this)));
+}
+
+void CryptAuthV2EnrollmentManagerImpl::OnEnrollmentFinished(
+    const CryptAuthEnrollmentResult& enrollment_result) {
+  // Once an enrollment attempt finishes, no other callbacks should be
+  // invoked. This is particularly relevant for timeout failures.
+  weak_ptr_factory_.InvalidateWeakPtrs();
+  enroller_.reset();
+
+  if (enrollment_result.IsSuccess()) {
+    PA_LOG(INFO) << "Enrollment attempt with invocation reason "
+                 << *current_enrollment_invocation_reason_
+                 << " succeeded with result code "
+                 << enrollment_result.result_code();
+
+    pref_service_->SetInteger(
+        prefs::kCryptAuthEnrollmentFailureRecoveryInvocationReason,
+        cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED);
+
+  } else {
+    PA_LOG(WARNING) << "Enrollment attempt with invocation reason "
+                    << *current_enrollment_invocation_reason_
+                    << " failed with result code "
+                    << enrollment_result.result_code();
+
+    pref_service_->SetInteger(
+        prefs::kCryptAuthEnrollmentFailureRecoveryInvocationReason,
+        *current_enrollment_invocation_reason_);
+  }
+
+  current_enrollment_invocation_reason_.reset();
+
+  // TODO(http://crbug.com/940944): [Metrics] Log enrollment result code to
+  // UMA.
+
+  scheduler_->HandleEnrollmentResult(enrollment_result);
+
+  PA_LOG(INFO) << "Time until next enrollment attempt: "
+               << GetTimeToNextAttempt();
+
+  if (!enrollment_result.IsSuccess()) {
+    PA_LOG(INFO) << "Number of consecutive failures: "
+                 << scheduler_->GetNumConsecutiveFailures();
+  }
+
+  SetState(State::kIdle);
+
+  NotifyEnrollmentFinished(enrollment_result.IsSuccess());
+}
+
+void CryptAuthV2EnrollmentManagerImpl::SetState(State state) {
+  timer_->Stop();
+
+  PA_LOG(INFO) << "Transitioning from " << state_ << " to " << state;
+  state_ = state;
+
+  base::Optional<base::TimeDelta> timeout_for_state = GetTimeoutForState(state);
+  if (!timeout_for_state)
+    return;
+
+  base::Optional<CryptAuthEnrollmentResult::ResultCode> error_code =
+      ResultCodeErrorFromState(state);
+
+  // If there's a timeout specified, there should be a corresponding error
+  // code.
+  DCHECK(error_code);
+
+  // TODO(https://crbug.com/936273): Add metrics to track failure rates due to
+  // async timeouts.
+  timer_->Start(
+      FROM_HERE, *timeout_for_state,
+      base::BindOnce(&CryptAuthV2EnrollmentManagerImpl::OnEnrollmentFinished,
+                     base::Unretained(this),
+                     CryptAuthEnrollmentResult(
+                         *error_code, base::nullopt /*client_directive */)));
+}
+
+base::Optional<cryptauthv2::ClientMetadata::InvocationReason>
+CryptAuthV2EnrollmentManagerImpl::GetFailureRecoveryInvocationReasonFromPref()
+    const {
+  int reason_stored_in_prefs = pref_service_->GetInteger(
+      prefs::kCryptAuthEnrollmentFailureRecoveryInvocationReason);
+
+  if (!cryptauthv2::ClientMetadata::InvocationReason_IsValid(
+          reason_stored_in_prefs)) {
+    PA_LOG(WARNING) << "Unknown invocation reason, " << reason_stored_in_prefs
+                    << ", stored in pref.";
+
+    return base::nullopt;
+  }
+
+  if (reason_stored_in_prefs ==
+      cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED) {
+    return base::nullopt;
+  }
+
+  return static_cast<cryptauthv2::ClientMetadata::InvocationReason>(
+      reason_stored_in_prefs);
+}
+
+std::string CryptAuthV2EnrollmentManagerImpl::GetV1UserPublicKey() const {
+  std::string public_key;
+  if (!base::Base64UrlDecode(
+          pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPublicKey),
+          base::Base64UrlDecodePolicy::REQUIRE_PADDING, &public_key)) {
+    PA_LOG(ERROR) << "Invalid public key stored in user prefs.";
+    return std::string();
+  }
+  return public_key;
+}
+
+std::string CryptAuthV2EnrollmentManagerImpl::GetV1UserPrivateKey() const {
+  std::string private_key;
+  if (!base::Base64UrlDecode(
+          pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPrivateKey),
+          base::Base64UrlDecodePolicy::REQUIRE_PADDING, &private_key)) {
+    PA_LOG(ERROR) << "Invalid private key stored in user prefs.";
+    return std::string();
+  }
+  return private_key;
+}
+
+void CryptAuthV2EnrollmentManagerImpl::AddV1UserKeyPairToRegistryIfNecessary() {
+  std::string public_key_v1 = GetV1UserPublicKey();
+  std::string private_key_v1 = GetV1UserPrivateKey();
+
+  const CryptAuthKey* key_v2 =
+      key_registry_->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair);
+
+  bool v1_key_exists = !public_key_v1.empty() && !private_key_v1.empty();
+  bool v1_and_v2_keys_exist_and_agree =
+      (v1_key_exists && key_v2 && public_key_v1 == key_v2->public_key() &&
+       private_key_v1 == key_v2->private_key());
+
+  // TODO(http://crbug.com/940944): [Metrics] Log the following scenarios to
+  // UMA:
+  //   - No v1 key; no v2 key. (Not enrolled)
+  //   - v1 key exists; no v2 key. (Only v1 enrolled)
+  //   - No v1 key; v2 key exists. (Only v2 enrolled)
+  //   - v1 and v2 keys exist and agree.
+  //   - v1 and v2 keys exist and disagree. (Enrolled with v2, rolled back to
+  //     v1, enrolled with v1, rolled forward to v2)
+
+  if (!v1_key_exists || v1_and_v2_keys_exist_and_agree)
+    return;
+
+  key_registry_->AddEnrolledKey(
+      CryptAuthKeyBundle::Name::kUserKeyPair,
+      CryptAuthKey(public_key_v1, private_key_v1, CryptAuthKey::Status::kActive,
+                   cryptauthv2::KeyType::P256,
+                   kCryptAuthFixedUserKeyPairHandle));
+}
+
+std::ostream& operator<<(std::ostream& stream,
+                         const CryptAuthV2EnrollmentManagerImpl::State& state) {
+  switch (state) {
+    case CryptAuthV2EnrollmentManagerImpl::State::kIdle:
+      stream << "[EnrollmentManager state: Idle]";
+      break;
+    case CryptAuthV2EnrollmentManagerImpl::State::kWaitingForGcmRegistration:
+      stream << "[EnrollmentManager state: Waiting for GCM registration]";
+      break;
+    case CryptAuthV2EnrollmentManagerImpl::State::kWaitingForClientAppMetadata:
+      stream << "[EnrollmentManager state: Waiting for ClientAppMetadata]";
+      break;
+    case CryptAuthV2EnrollmentManagerImpl::State::kWaitingForEnrollment:
+      stream << "[EnrollmentManager state: Waiting for enrollment to finish]";
+      break;
+  }
+
+  return stream;
+}
+
+}  // namespace device_sync
+
+}  // namespace chromeos
diff --git a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h
new file mode 100644
index 0000000..020518b
--- /dev/null
+++ b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h
@@ -0,0 +1,197 @@
+// Copyright 2019 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 CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_V2_ENROLLMENT_MANAGER_IMPL_H_
+#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_V2_ENROLLMENT_MANAGER_IMPL_H_
+
+#include <memory>
+#include <ostream>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/time/default_clock.h"
+#include "chromeos/services/device_sync/cryptauth_enrollment_manager.h"
+#include "chromeos/services/device_sync/cryptauth_enrollment_result.h"
+#include "chromeos/services/device_sync/cryptauth_enrollment_scheduler.h"
+#include "chromeos/services/device_sync/cryptauth_gcm_manager.h"
+#include "chromeos/services/device_sync/proto/cryptauth_client_app_metadata.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h"
+
+class PrefService;
+class PrefRegistrySimple;
+
+namespace base {
+class OneShotTimer;
+}  // namespace base
+
+namespace chromeos {
+
+namespace device_sync {
+
+class ClientAppMetadataProvider;
+class CryptAuthClientFactory;
+class CryptAuthKeyRegistry;
+class CryptAuthV2Enroller;
+
+// Implementation of CryptAuthEnrollmentManager for CryptAuth v2 Enrollment.
+//
+// This implementation considers three sources of enrollment requests:
+//  1) A network-aware enrollment scheduler requests periodic enrollments and
+//     handles any failed attempts.
+//  2) The enrollment manager listens to the GCM manager for re-enrollment
+//     requests.
+//  3) The ForceEnrollmentNow() method allows for immediate requests.
+//
+// All flavors of enrollment attempts are guarded by timeouts. For example, an
+// enrollment attempt triggeredd by ForceEnrollmentNow() will always
+// conclude--successfully or not--in an allotted period of time.
+//
+// The v2 Enrollment infrastructure stores keys in a CryptAuthKeyRegistry. In
+// contrast, the v1 enrollment manager implementation directly controls a set of
+// prefs that store the user key pair. However, on construction of
+// CryptAuthV2EnrollmentManagerImpl, any existing v1 user key pair is added to
+// the v2 key registry to ensure consistency across the v1 to v2 Enrollment
+// migration. The converse is not true. The v1 prefs will never be modified by
+// v2 Enrollment.
+//
+// The enrollment invocation reason sent to CryptAuth in ClientMetadata is
+// determined using the following order of priority:
+//  1) If ForceEnrollmentNow() was called, use its invocation reason argument.
+//  2) If we are recovering from a failed enrollment attempt, reuse the initial
+//     invocation reason, which is stored as a pref.
+//  3) If the user has never enrolled, use INITIALIZATION.
+//  4) If the enrollment is no longer valid--due for a refresh, for
+//     example--use PERIODIC.
+//  5) As a last resort, use INVOCATION_REASON_UNSPECIFIED.
+class CryptAuthV2EnrollmentManagerImpl
+    : public CryptAuthEnrollmentManager,
+      public CryptAuthEnrollmentScheduler::Delegate,
+      public CryptAuthGCMManager::Observer {
+ public:
+  class Factory {
+   public:
+    static Factory* Get();
+    static void SetFactoryForTesting(Factory* test_factory);
+    virtual ~Factory();
+    virtual std::unique_ptr<CryptAuthEnrollmentManager> BuildInstance(
+        ClientAppMetadataProvider* client_app_metadata_provider,
+        CryptAuthKeyRegistry* key_registry,
+        CryptAuthClientFactory* client_factory,
+        CryptAuthGCMManager* gcm_manager,
+        PrefService* pref_service,
+        base::Clock* clock = base::DefaultClock::GetInstance(),
+        std::unique_ptr<base::OneShotTimer> timer =
+            std::make_unique<base::OneShotTimer>());
+
+   private:
+    static Factory* test_factory_;
+  };
+
+  // Note: This should never be called with
+  // CryptAuthEnrollmentManagerImpl::RegisterPrefs().
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+  ~CryptAuthV2EnrollmentManagerImpl() override;
+
+  // CryptAuthEnrollmentManager:
+  void Start() override;
+  void ForceEnrollmentNow(
+      cryptauth::InvocationReason invocation_reason) override;
+  bool IsEnrollmentValid() const override;
+  base::Time GetLastEnrollmentTime() const override;
+  base::TimeDelta GetTimeToNextAttempt() const override;
+  bool IsEnrollmentInProgress() const override;
+  bool IsRecoveringFromFailure() const override;
+  std::string GetUserPublicKey() const override;
+  std::string GetUserPrivateKey() const override;
+
+ protected:
+  CryptAuthV2EnrollmentManagerImpl(
+      ClientAppMetadataProvider* client_app_metadata_provider,
+      CryptAuthKeyRegistry* key_registry,
+      CryptAuthClientFactory* client_factory,
+      CryptAuthGCMManager* gcm_manager,
+      PrefService* pref_service,
+      base::Clock* clock,
+      std::unique_ptr<base::OneShotTimer> timer);
+
+ private:
+  enum class State {
+    kIdle,
+    kWaitingForGcmRegistration,
+    kWaitingForClientAppMetadata,
+    kWaitingForEnrollment
+  };
+
+  friend std::ostream& operator<<(std::ostream& stream, const State& state);
+
+  static base::Optional<base::TimeDelta> GetTimeoutForState(State state);
+  static base::Optional<CryptAuthEnrollmentResult::ResultCode>
+  ResultCodeErrorFromState(State state);
+
+  // CryptAuthEnrollmentScheduler::Delegate:
+  void OnEnrollmentRequested(const base::Optional<cryptauthv2::PolicyReference>&
+                                 client_directive_policy_reference) override;
+
+  // CryptAuthGCMManager::Observer:
+  void OnGCMRegistrationResult(bool success) override;
+  void OnReenrollMessage() override;
+
+  void OnClientAppMetadataFetched(
+      const base::Optional<cryptauthv2::ClientAppMetadata>&
+          client_app_metadata);
+
+  // Starts the enrollment flow if a valid GCM registration ID exists and the
+  // ClientAppMetadata has already been fetched; otherwise, the enrollment is
+  // postposed while they are retrieved.
+  void AttemptEnrollment();
+
+  void Enroll();
+  void OnEnrollmentFinished(const CryptAuthEnrollmentResult& enrollment_result);
+
+  void SetState(State state);
+
+  // Returns the invocation reason to be used when recovering from a failed
+  // enrollment attempt. If no valid reason is stored, returns null.
+  base::Optional<cryptauthv2::ClientMetadata::InvocationReason>
+  GetFailureRecoveryInvocationReasonFromPref() const;
+
+  std::string GetV1UserPublicKey() const;
+  std::string GetV1UserPrivateKey() const;
+
+  // If a v1 user key-pair exists, add it to the registry as the active key in
+  // the kUserKeyPair key bundle.
+  void AddV1UserKeyPairToRegistryIfNecessary();
+
+  ClientAppMetadataProvider* client_app_metadata_provider_;
+  CryptAuthKeyRegistry* key_registry_;
+  CryptAuthClientFactory* client_factory_;
+  CryptAuthGCMManager* gcm_manager_;
+  PrefService* pref_service_;
+  base::Clock* clock_;
+  std::unique_ptr<base::OneShotTimer> timer_;
+
+  State state_ = State::kIdle;
+  std::unique_ptr<CryptAuthEnrollmentScheduler> scheduler_;
+  std::unique_ptr<CryptAuthV2Enroller> enroller_;
+
+  // Only non-null while an enrollment attempt is active.
+  base::Optional<cryptauthv2::ClientMetadata::InvocationReason>
+      current_enrollment_invocation_reason_;
+
+  base::Optional<cryptauthv2::ClientAppMetadata> client_app_metadata_;
+  base::Optional<cryptauthv2::PolicyReference>
+      client_directive_policy_reference_;
+  base::WeakPtrFactory<CryptAuthV2EnrollmentManagerImpl> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(CryptAuthV2EnrollmentManagerImpl);
+};
+
+}  // namespace device_sync
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_V2_ENROLLMENT_MANAGER_IMPL_H_
diff --git a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl_unittest.cc
new file mode 100644
index 0000000..e2b1e31
--- /dev/null
+++ b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl_unittest.cc
@@ -0,0 +1,673 @@
+// Copyright 2019 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 <memory>
+#include <utility>
+
+#include "base/base64url.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/test/simple_test_clock.h"
+#include "base/timer/mock_timer.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/services/device_sync/cryptauth_constants.h"
+#include "chromeos/services/device_sync/cryptauth_enrollment_result.h"
+#include "chromeos/services/device_sync/cryptauth_enrollment_scheduler.h"
+#include "chromeos/services/device_sync/cryptauth_key_bundle.h"
+#include "chromeos/services/device_sync/cryptauth_key_registry.h"
+#include "chromeos/services/device_sync/cryptauth_key_registry_impl.h"
+#include "chromeos/services/device_sync/cryptauth_v2_enroller.h"
+#include "chromeos/services/device_sync/cryptauth_v2_enroller_impl.h"
+#include "chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h"
+#include "chromeos/services/device_sync/fake_cryptauth_enrollment_scheduler.h"
+#include "chromeos/services/device_sync/fake_cryptauth_gcm_manager.h"
+#include "chromeos/services/device_sync/fake_cryptauth_v2_enroller.h"
+#include "chromeos/services/device_sync/mock_cryptauth_client.h"
+#include "chromeos/services/device_sync/network_aware_enrollment_scheduler.h"
+#include "chromeos/services/device_sync/pref_names.h"
+#include "chromeos/services/device_sync/proto/cryptauth_api.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_better_together_feature_metadata.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_client_app_metadata.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_directive.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_v2_test_util.h"
+#include "chromeos/services/device_sync/public/cpp/fake_client_app_metadata_provider.h"
+#include "chromeos/services/device_sync/public/cpp/gcm_constants.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace device_sync {
+
+namespace {
+
+const char kFakeV1PublicKey[] = "public_key_v1";
+const char kFakeV1PrivateKey[] = "private_key_v1";
+const char kFakeV2PublicKey[] = "public_key_v2";
+const char kFakeV2PrivateKey[] = "private_key_v2";
+
+const base::TimeDelta kFakeRefreshPeriod = base::TimeDelta::FromMilliseconds(
+    cryptauthv2::kTestClientDirectiveCheckinDelayMillis);
+const base::TimeDelta kFakeRetryPeriod = base::TimeDelta::FromMilliseconds(
+    cryptauthv2::kTestClientDirectiveRetryPeriodMillis);
+const base::Time kFakeLastEnrollmentTime = base::Time::UnixEpoch();
+const base::Time kFakeTimeAfterRefreshPeriod = kFakeLastEnrollmentTime +
+                                               kFakeRefreshPeriod +
+                                               base::TimeDelta::FromSeconds(1);
+const base::Time kFakeTimeBeforeRefreshPeriod = kFakeLastEnrollmentTime +
+                                                kFakeRefreshPeriod -
+                                                base::TimeDelta::FromSeconds(1);
+
+// A child of FakeCryptAuthEnrollmentScheduler that sets scheduler parameters
+// based on the latest enrollment result.
+class FakeCryptAuthEnrollmentSchedulerWithResultHandling
+    : public FakeCryptAuthEnrollmentScheduler {
+ public:
+  FakeCryptAuthEnrollmentSchedulerWithResultHandling(
+      CryptAuthEnrollmentScheduler::Delegate* delegate,
+      base::Clock* clock)
+      : FakeCryptAuthEnrollmentScheduler(delegate), clock_(clock) {}
+
+  ~FakeCryptAuthEnrollmentSchedulerWithResultHandling() override = default;
+
+  void HandleEnrollmentResult(
+      const CryptAuthEnrollmentResult& enrollment_result) override {
+    FakeCryptAuthEnrollmentScheduler::HandleEnrollmentResult(enrollment_result);
+
+    if (handled_enrollment_results().back().IsSuccess()) {
+      set_num_consecutive_failures(0);
+      set_time_to_next_enrollment_request(kFakeRefreshPeriod);
+      set_last_successful_enrollment_time(clock_->Now());
+    } else {
+      set_num_consecutive_failures(GetNumConsecutiveFailures() + 1);
+      set_time_to_next_enrollment_request(kFakeRetryPeriod);
+    }
+  }
+
+ private:
+  base::Clock* clock_;
+};
+
+class FakeNetworkAwareEnrollmentSchedulerFactory
+    : public NetworkAwareEnrollmentScheduler::Factory {
+ public:
+  FakeNetworkAwareEnrollmentSchedulerFactory(
+      const PrefService* expected_pref_service,
+      base::Clock* clock)
+      : expected_pref_service_(expected_pref_service), clock_(clock) {}
+
+  ~FakeNetworkAwareEnrollmentSchedulerFactory() override = default;
+
+  FakeCryptAuthEnrollmentSchedulerWithResultHandling* instance() {
+    return instance_;
+  }
+
+  void SetInitialNumConsecutiveFailures(size_t num_consecutive_failures) {
+    initial_num_consecutive_failures_ = num_consecutive_failures;
+  }
+
+ private:
+  // NetworkAwareEnrollmentScheduler::Factory
+  std::unique_ptr<CryptAuthEnrollmentScheduler> BuildInstance(
+      CryptAuthEnrollmentScheduler::Delegate* delegate,
+      PrefService* pref_service,
+      NetworkStateHandler* network_state_handler) override {
+    EXPECT_EQ(expected_pref_service_, pref_service);
+
+    auto instance =
+        std::make_unique<FakeCryptAuthEnrollmentSchedulerWithResultHandling>(
+            delegate, clock_);
+    instance_ = instance.get();
+
+    if (initial_num_consecutive_failures_) {
+      instance->set_num_consecutive_failures(
+          *initial_num_consecutive_failures_);
+    }
+
+    return instance;
+  }
+
+  const PrefService* expected_pref_service_;
+  base::Clock* clock_;
+
+  base::Optional<size_t> initial_num_consecutive_failures_;
+
+  FakeCryptAuthEnrollmentSchedulerWithResultHandling* instance_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeNetworkAwareEnrollmentSchedulerFactory);
+};
+
+class FakeCryptAuthV2EnrollerFactory : public CryptAuthV2EnrollerImpl::Factory {
+ public:
+  FakeCryptAuthV2EnrollerFactory(
+      const CryptAuthKeyRegistry* expected_key_registry,
+      const CryptAuthClientFactory* expected_client_factory)
+      : expected_key_registry_(expected_key_registry),
+        expected_client_factory_(expected_client_factory) {}
+
+  ~FakeCryptAuthV2EnrollerFactory() override = default;
+
+  const std::vector<FakeCryptAuthV2Enroller*>& created_instances() {
+    return created_instances_;
+  }
+
+ private:
+  // CryptAuthV2EnrollerImpl::Factory:
+  std::unique_ptr<CryptAuthV2Enroller> BuildInstance(
+      CryptAuthKeyRegistry* key_registry,
+      CryptAuthClientFactory* client_factory,
+      std::unique_ptr<base::OneShotTimer> timer =
+          std::make_unique<base::MockOneShotTimer>()) override {
+    EXPECT_EQ(expected_key_registry_, key_registry);
+    EXPECT_EQ(expected_client_factory_, client_factory);
+
+    auto instance = std::make_unique<FakeCryptAuthV2Enroller>();
+    created_instances_.push_back(instance.get());
+
+    return instance;
+  }
+
+  const CryptAuthKeyRegistry* expected_key_registry_;
+  const CryptAuthClientFactory* expected_client_factory_;
+
+  std::vector<FakeCryptAuthV2Enroller*> created_instances_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthV2EnrollerFactory);
+};
+
+}  // namespace
+
+class DeviceSyncCryptAuthV2EnrollmentManagerImplTest
+    : public testing::Test,
+      CryptAuthEnrollmentManager::Observer {
+ protected:
+  DeviceSyncCryptAuthV2EnrollmentManagerImplTest()
+      : fake_gcm_manager_(std::string() /* registration_id */),
+        mock_client_factory_(
+            MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS) {}
+
+  // testing::Test:
+  void SetUp() override {
+    DBusThreadManager::Initialize();
+    NetworkHandler::Initialize();
+    base::RunLoop().RunUntilIdle();
+
+    CryptAuthV2EnrollmentManagerImpl::RegisterPrefs(
+        test_pref_service_.registry());
+    CryptAuthKeyRegistryImpl::RegisterPrefs(test_pref_service_.registry());
+
+    key_registry_ = CryptAuthKeyRegistryImpl::Factory::Get()->BuildInstance(
+        &test_pref_service_);
+
+    fake_enrollment_scheduler_factory_ =
+        std::make_unique<FakeNetworkAwareEnrollmentSchedulerFactory>(
+            &test_pref_service_, &test_clock_);
+    NetworkAwareEnrollmentScheduler::Factory::SetFactoryForTesting(
+        fake_enrollment_scheduler_factory_.get());
+
+    fake_enroller_factory_ = std::make_unique<FakeCryptAuthV2EnrollerFactory>(
+        key_registry_.get(), &mock_client_factory_);
+    CryptAuthV2EnrollerImpl::Factory::SetFactoryForTesting(
+        fake_enroller_factory_.get());
+  }
+
+  // testing::Test:
+  void TearDown() override {
+    if (enrollment_manager())
+      enrollment_manager()->RemoveObserver(this);
+
+    NetworkAwareEnrollmentScheduler::Factory::SetFactoryForTesting(nullptr);
+    CryptAuthV2EnrollerImpl::Factory::SetFactoryForTesting(nullptr);
+
+    NetworkHandler::Shutdown();
+    DBusThreadManager::Shutdown();
+  }
+
+  void AddV1UserKeyPairToV1Prefs(const std::string& public_key,
+                                 const std::string& private_key) {
+    std::string public_key_b64, private_key_b64;
+    base::Base64UrlEncode(public_key,
+                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+                          &public_key_b64);
+    base::Base64UrlEncode(private_key,
+                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+                          &private_key_b64);
+
+    test_pref_service_.SetString(prefs::kCryptAuthEnrollmentUserPublicKey,
+                                 public_key_b64);
+    test_pref_service_.SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
+                                 private_key_b64);
+  }
+
+  void SetInitialNumConsecutiveFailures(size_t num_consecutive_failures) {
+    num_consecutive_failures_ = num_consecutive_failures;
+    fake_enrollment_scheduler_factory_->SetInitialNumConsecutiveFailures(
+        num_consecutive_failures);
+  }
+
+  // CryptAuthEnrollmentManager::Observer:
+  void OnEnrollmentStarted() override {
+    ++num_enrollment_started_notifications_;
+
+    enrollment_finished_success_ = base::nullopt;
+  }
+  void OnEnrollmentFinished(bool success) override {
+    enrollment_finished_success_ = success;
+  }
+
+  void CreateEnrollmentManager() {
+    auto mock_timer = std::make_unique<base::MockOneShotTimer>();
+    mock_timer_ = mock_timer.get();
+
+    enrollment_manager_ =
+        CryptAuthV2EnrollmentManagerImpl::Factory::Get()->BuildInstance(
+            &fake_client_app_metadata_provider_, key_registry_.get(),
+            &mock_client_factory_, &fake_gcm_manager_, &test_pref_service_,
+            &test_clock_, std::move(mock_timer));
+
+    enrollment_manager()->AddObserver(this);
+  }
+
+  void VerifyEnrollmentManagerObserversNotifiedOfStart(
+      size_t expected_num_enrollment_started_notifications) {
+    EXPECT_EQ(expected_num_enrollment_started_notifications,
+              num_enrollment_started_notifications_);
+  }
+
+  void VerifyPersistedFailureRecoveryInvocationReason(
+      const cryptauthv2::ClientMetadata::InvocationReason&
+          expected_failure_recovery_invocation_reason) {
+    EXPECT_EQ(
+        expected_failure_recovery_invocation_reason,
+        static_cast<cryptauthv2::ClientMetadata::InvocationReason>(
+            test_pref_service_.GetInteger(
+                prefs::kCryptAuthEnrollmentFailureRecoveryInvocationReason)));
+  }
+
+  void VerifyEnrollmentResult(
+      const CryptAuthEnrollmentResult& expected_result) {
+    VerifyResultSentToEnrollmentManagerObservers(expected_result.IsSuccess());
+    EXPECT_EQ(expected_result,
+              fake_enrollment_scheduler()->handled_enrollment_results().back());
+  }
+
+  TestingPrefServiceSimple* test_pref_service() { return &test_pref_service_; }
+
+  CryptAuthKeyRegistry* key_registry() { return key_registry_.get(); }
+
+  FakeCryptAuthEnrollmentSchedulerWithResultHandling*
+  fake_enrollment_scheduler() {
+    return fake_enrollment_scheduler_factory_->instance();
+  }
+
+  FakeCryptAuthGCMManager* fake_gcm_manager() { return &fake_gcm_manager_; }
+
+  base::SimpleTestClock* test_clock() { return &test_clock_; }
+
+  base::MockOneShotTimer* mock_timer() { return mock_timer_; }
+
+  FakeClientAppMetadataProvider* fake_client_app_metadata_provider() {
+    return &fake_client_app_metadata_provider_;
+  }
+
+  MockCryptAuthClientFactory* mock_client_factory() {
+    return &mock_client_factory_;
+  }
+
+  FakeCryptAuthV2Enroller* fake_enroller(size_t index = 0u) {
+    // Only the most recently created enroller is valid.
+    EXPECT_EQ(fake_enroller_factory_->created_instances().size() - 1, index);
+
+    return fake_enroller_factory_->created_instances()[index];
+  }
+
+  CryptAuthEnrollmentManager* enrollment_manager() {
+    return enrollment_manager_.get();
+  }
+
+ private:
+  void VerifyResultSentToEnrollmentManagerObservers(bool success) {
+    EXPECT_EQ(success, enrollment_finished_success_);
+  }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  size_t num_enrollment_started_notifications_ = 0;
+  base::Optional<bool> enrollment_finished_success_ = base::nullopt;
+  size_t num_consecutive_failures_ = 0;
+
+  TestingPrefServiceSimple test_pref_service_;
+  FakeClientAppMetadataProvider fake_client_app_metadata_provider_;
+  FakeCryptAuthGCMManager fake_gcm_manager_;
+  base::SimpleTestClock test_clock_;
+  base::MockOneShotTimer* mock_timer_;
+  MockCryptAuthClientFactory mock_client_factory_;
+  std::unique_ptr<CryptAuthKeyRegistry> key_registry_;
+  std::unique_ptr<FakeNetworkAwareEnrollmentSchedulerFactory>
+      fake_enrollment_scheduler_factory_;
+  std::unique_ptr<FakeCryptAuthV2EnrollerFactory> fake_enroller_factory_;
+
+  std::unique_ptr<CryptAuthEnrollmentManager> enrollment_manager_;
+};
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       EnrollmentRequestedFromScheduler_NeverPreviouslyEnrolled) {
+  CreateEnrollmentManager();
+  EXPECT_FALSE(fake_enrollment_scheduler());
+
+  enrollment_manager()->Start();
+  EXPECT_TRUE(fake_enrollment_scheduler());
+
+  // The user has never enrolled with v1 or v2 and has not registered with GCM.
+  EXPECT_TRUE(key_registry()->enrolled_key_bundles().empty());
+  EXPECT_TRUE(fake_gcm_manager()->GetRegistrationId().empty());
+  EXPECT_TRUE(enrollment_manager()->GetLastEnrollmentTime().is_null());
+  EXPECT_FALSE(enrollment_manager()->IsEnrollmentValid());
+
+  cryptauthv2::PolicyReference expected_policy_reference =
+      cryptauthv2::BuildPolicyReference("expected_policy_reference_name",
+                                        1 /* version */);
+  fake_enrollment_scheduler()->set_client_directive_policy_reference(
+      expected_policy_reference);
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+  EXPECT_TRUE(enrollment_manager()->IsEnrollmentInProgress());
+  VerifyEnrollmentManagerObserversNotifiedOfStart(
+      1 /* expected_num_enrollment_started_notifications */);
+
+  fake_gcm_manager()->CompleteRegistration(cryptauthv2::kTestGcmRegistrationId);
+
+  EXPECT_EQ(1u,
+            fake_client_app_metadata_provider()->metadata_requests().size());
+  EXPECT_EQ(cryptauthv2::kTestGcmRegistrationId,
+            fake_client_app_metadata_provider()
+                ->metadata_requests()[0]
+                .gcm_registration_id);
+  std::move(
+      fake_client_app_metadata_provider()->metadata_requests()[0].callback)
+      .Run(cryptauthv2::GetClientAppMetadataForTest());
+
+  EXPECT_TRUE(fake_enroller()->was_enroll_called());
+  EXPECT_EQ(
+      cryptauthv2::BuildClientMetadata(
+          0 /* retry_count */,
+          cryptauthv2::ClientMetadata::INITIALIZATION /* invocation_reason */)
+          .SerializeAsString(),
+      fake_enroller()->client_metadata()->SerializeAsString());
+  EXPECT_EQ(cryptauthv2::GetClientAppMetadataForTest().SerializeAsString(),
+            fake_enroller()->client_app_metadata()->SerializeAsString());
+  EXPECT_EQ(expected_policy_reference.SerializeAsString(),
+            (*fake_enroller()->client_directive_policy_reference())
+                ->SerializeAsString());
+
+  CryptAuthEnrollmentResult expected_enrollment_result(
+      CryptAuthEnrollmentResult::ResultCode::kSuccessNewKeysEnrolled,
+      cryptauthv2::GetClientDirectiveForTest());
+  fake_enroller()->FinishAttempt(expected_enrollment_result);
+  EXPECT_FALSE(enrollment_manager()->IsEnrollmentInProgress());
+
+  VerifyEnrollmentResult(expected_enrollment_result);
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest, GcmRegistrationFailed) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+
+  // An empty registration ID is interpreted as an error by
+  // FakeCryptAuthGCMManager.
+  fake_gcm_manager()->CompleteRegistration(std::string() /* registration_id */);
+
+  VerifyEnrollmentResult(CryptAuthEnrollmentResult(
+      CryptAuthEnrollmentResult::ResultCode::kErrorGcmRegistrationFailed,
+      base::nullopt /* client_directive */));
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest, GcmRegistrationTimeout) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+
+  // Timeout waiting for GcmRegistration.
+  EXPECT_TRUE(mock_timer()->IsRunning());
+  mock_timer()->Fire();
+
+  VerifyEnrollmentResult(
+      CryptAuthEnrollmentResult(CryptAuthEnrollmentResult::ResultCode::
+                                    kErrorTimeoutWaitingForGcmRegistration,
+                                base::nullopt /* client_directive */));
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       ClientAppMetadataFetchFailed) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+  fake_gcm_manager()->CompleteRegistration(cryptauthv2::kTestGcmRegistrationId);
+
+  // A failed metadata retrieval will return base::nullopt.
+  std::move(
+      fake_client_app_metadata_provider()->metadata_requests()[0].callback)
+      .Run(base::nullopt /* client_app_metadata */);
+
+  VerifyEnrollmentResult(CryptAuthEnrollmentResult(
+      CryptAuthEnrollmentResult::ResultCode::kErrorClientAppMetadataFetchFailed,
+      base::nullopt /* client_directive */));
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       ClientAppMetadataTimeout) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+  fake_gcm_manager()->CompleteRegistration(cryptauthv2::kTestGcmRegistrationId);
+
+  // Timeout waiting for ClientAppMetadata.
+  EXPECT_TRUE(mock_timer()->IsRunning());
+  mock_timer()->Fire();
+
+  VerifyEnrollmentResult(
+      CryptAuthEnrollmentResult(CryptAuthEnrollmentResult::ResultCode::
+                                    kErrorTimeoutWaitingForClientAppMetadata,
+                                base::nullopt /* client_directive */));
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest, ForcedEnrollment) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+
+  enrollment_manager()->ForceEnrollmentNow(
+      cryptauth::InvocationReason::INVOCATION_REASON_FEATURE_TOGGLED);
+  EXPECT_TRUE(enrollment_manager()->IsEnrollmentInProgress());
+  VerifyEnrollmentManagerObserversNotifiedOfStart(
+      1 /* expected_num_enrollment_started_notifications */);
+
+  // Simulate a failed enrollment attempt due to CryptAuth server overload.
+  fake_gcm_manager()->CompleteRegistration(cryptauthv2::kTestGcmRegistrationId);
+  std::move(
+      fake_client_app_metadata_provider()->metadata_requests()[0].callback)
+      .Run(cryptauthv2::GetClientAppMetadataForTest());
+  CryptAuthEnrollmentResult expected_enrollment_result(
+      CryptAuthEnrollmentResult::ResultCode::kErrorCryptAuthServerOverloaded,
+      base::nullopt /* client_directive */);
+  fake_enroller()->FinishAttempt(expected_enrollment_result);
+  VerifyEnrollmentResult(expected_enrollment_result);
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       RetryAfterFailedPeriodicEnrollment_PreviouslyEnrolled) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+
+  // The user has already enrolled and is due for a refresh.
+  base::Time expected_last_enrollment_time = kFakeLastEnrollmentTime;
+  fake_enrollment_scheduler()->set_last_successful_enrollment_time(
+      expected_last_enrollment_time);
+  fake_enrollment_scheduler()->set_refresh_period(kFakeRefreshPeriod);
+  test_clock()->SetNow(kFakeTimeAfterRefreshPeriod);
+  base::TimeDelta expected_time_to_next_attempt =
+      base::TimeDelta::FromSeconds(0);
+  fake_enrollment_scheduler()->set_time_to_next_enrollment_request(
+      expected_time_to_next_attempt);
+  cryptauthv2::ClientMetadata::InvocationReason expected_invocation_reason =
+      cryptauthv2::ClientMetadata::PERIODIC;
+
+  EXPECT_EQ(expected_last_enrollment_time,
+            enrollment_manager()->GetLastEnrollmentTime());
+  EXPECT_FALSE(enrollment_manager()->IsEnrollmentValid());
+  EXPECT_EQ(expected_time_to_next_attempt,
+            enrollment_manager()->GetTimeToNextAttempt());
+  EXPECT_FALSE(enrollment_manager()->IsEnrollmentInProgress());
+  EXPECT_FALSE(enrollment_manager()->IsRecoveringFromFailure());
+
+  // First enrollment attempt fails.
+  // Note: User does not yet have a GCM registration ID or ClientAppMetadata.
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+  EXPECT_TRUE(enrollment_manager()->IsEnrollmentInProgress());
+  VerifyEnrollmentManagerObserversNotifiedOfStart(
+      1 /* expected_num_enrollment_started_notifications */);
+  fake_gcm_manager()->CompleteRegistration(cryptauthv2::kTestGcmRegistrationId);
+  std::move(
+      fake_client_app_metadata_provider()->metadata_requests()[0].callback)
+      .Run(cryptauthv2::GetClientAppMetadataForTest());
+  EXPECT_EQ(cryptauthv2::BuildClientMetadata(0 /* retry_count */,
+                                             expected_invocation_reason)
+                .SerializeAsString(),
+            fake_enroller()->client_metadata()->SerializeAsString());
+
+  CryptAuthEnrollmentResult expected_enrollment_result(
+      CryptAuthEnrollmentResult::ResultCode::kErrorCryptAuthServerOverloaded,
+      base::nullopt /* client_directive */);
+  fake_enroller()->FinishAttempt(expected_enrollment_result);
+  EXPECT_FALSE(enrollment_manager()->IsEnrollmentInProgress());
+  VerifyEnrollmentResult(expected_enrollment_result);
+
+  // The initial invocation reason is persisted for reuse in subsequent failure
+  // recovery attempts.
+  VerifyPersistedFailureRecoveryInvocationReason(
+      cryptauthv2::ClientMetadata::PERIODIC);
+
+  // Second (successful) enrollment attempt bypasses GCM registration and
+  // ClientAppMetadata fetch because they were performed during the failed
+  // attempt.
+  fake_enrollment_scheduler()->RequestEnrollmentNow();
+  VerifyEnrollmentManagerObserversNotifiedOfStart(
+      2 /* expected_num_enrollment_started_notifications */);
+  EXPECT_TRUE(enrollment_manager()->IsRecoveringFromFailure());
+  expected_invocation_reason = cryptauthv2::ClientMetadata::PERIODIC;
+  EXPECT_EQ(cryptauthv2::kTestGcmRegistrationId,
+            fake_gcm_manager()->GetRegistrationId());
+  EXPECT_EQ(1u,
+            fake_client_app_metadata_provider()->metadata_requests().size());
+  EXPECT_EQ(
+      cryptauthv2::BuildClientMetadata(1 /* retry_count */,
+                                       expected_invocation_reason)
+          .SerializeAsString(),
+      fake_enroller(1u /* index */)->client_metadata()->SerializeAsString());
+
+  expected_enrollment_result = CryptAuthEnrollmentResult(
+      CryptAuthEnrollmentResult::ResultCode::kSuccessNoNewKeysNeeded,
+      cryptauthv2::GetClientDirectiveForTest());
+  fake_enroller(1u /* index */)->FinishAttempt(expected_enrollment_result);
+  VerifyEnrollmentResult(expected_enrollment_result);
+
+  // The persisted invocation reason to be used for failure recovery is cleared
+  // after a successful enrollment attempt.
+  VerifyPersistedFailureRecoveryInvocationReason(
+      cryptauthv2::ClientMetadata::INVOCATION_REASON_UNSPECIFIED);
+
+  EXPECT_EQ(test_clock()->Now(), enrollment_manager()->GetLastEnrollmentTime());
+  EXPECT_TRUE(enrollment_manager()->IsEnrollmentValid());
+  EXPECT_EQ(kFakeRefreshPeriod, enrollment_manager()->GetTimeToNextAttempt());
+  EXPECT_FALSE(enrollment_manager()->IsRecoveringFromFailure());
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       EnrollmentTriggeredByGcmMessage) {
+  CreateEnrollmentManager();
+  enrollment_manager()->Start();
+
+  fake_gcm_manager()->PushReenrollMessage();
+  EXPECT_TRUE(enrollment_manager()->IsEnrollmentInProgress());
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       V1UserKeyPairAddedToRegistryOnConstruction) {
+  AddV1UserKeyPairToV1Prefs(kFakeV1PublicKey, kFakeV1PrivateKey);
+  CryptAuthKey expected_user_key_pair_v1(
+      kFakeV1PublicKey, kFakeV1PrivateKey, CryptAuthKey::Status::kActive,
+      cryptauthv2::KeyType::P256, kCryptAuthFixedUserKeyPairHandle);
+
+  EXPECT_FALSE(
+      key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair));
+
+  CreateEnrollmentManager();
+
+  EXPECT_EQ(
+      expected_user_key_pair_v1,
+      *key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair));
+  EXPECT_EQ(expected_user_key_pair_v1.public_key(),
+            enrollment_manager()->GetUserPublicKey());
+  EXPECT_EQ(expected_user_key_pair_v1.private_key(),
+            enrollment_manager()->GetUserPrivateKey());
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest,
+       V1UserKeyPairOverwritesV2UserKeyPairOnConstruction) {
+  AddV1UserKeyPairToV1Prefs(kFakeV1PublicKey, kFakeV1PrivateKey);
+  CryptAuthKey expected_user_key_pair_v1(
+      kFakeV1PublicKey, kFakeV1PrivateKey, CryptAuthKey::Status::kActive,
+      cryptauthv2::KeyType::P256, kCryptAuthFixedUserKeyPairHandle);
+
+  // Add v2 user key pair to registry.
+  CryptAuthKey user_key_pair_v2(
+      kFakeV2PublicKey, kFakeV2PrivateKey, CryptAuthKey::Status::kActive,
+      cryptauthv2::KeyType::P256, kCryptAuthFixedUserKeyPairHandle);
+  key_registry()->AddEnrolledKey(CryptAuthKeyBundle::Name::kUserKeyPair,
+                                 user_key_pair_v2);
+  EXPECT_EQ(user_key_pair_v2, *key_registry()->GetActiveKey(
+                                  CryptAuthKeyBundle::Name::kUserKeyPair));
+
+  // A legacy v1 user key pair should overwrite any existing v2 user key pair
+  // when the enrollment manager is constructed. This can happen in the
+  // following rollback-->rollforward scenario:
+  //   - User never enrolled with v1
+  //   - User enrolls with v2, storing v2 user key pair locally in key registry
+  //     and in CryptAuth backend database
+  //   - Chromium rolls back to v1 enrollment flow
+  //   - User enrolls with v1, storing the v1 user key pair in prefs (not key
+  //     registry) and overwriting the v2 key in the CryptAuth backend database
+  //   - Chromium rolls forward to v2 enrollment flow, with different user key
+  //     pairs stored in v1 prefs and the v2 key registry.
+  CreateEnrollmentManager();
+
+  EXPECT_EQ(
+      expected_user_key_pair_v1,
+      *key_registry()->GetActiveKey(CryptAuthKeyBundle::Name::kUserKeyPair));
+  EXPECT_EQ(expected_user_key_pair_v1.public_key(),
+            enrollment_manager()->GetUserPublicKey());
+  EXPECT_EQ(expected_user_key_pair_v1.private_key(),
+            enrollment_manager()->GetUserPrivateKey());
+}
+
+TEST_F(DeviceSyncCryptAuthV2EnrollmentManagerImplTest, GetUserKeyPair) {
+  CreateEnrollmentManager();
+  EXPECT_TRUE(enrollment_manager()->GetUserPublicKey().empty());
+  EXPECT_TRUE(enrollment_manager()->GetUserPrivateKey().empty());
+
+  key_registry()->AddEnrolledKey(
+      CryptAuthKeyBundle::Name::kUserKeyPair,
+      CryptAuthKey(kFakeV2PublicKey, kFakeV2PrivateKey,
+                   CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256,
+                   kCryptAuthFixedUserKeyPairHandle));
+  EXPECT_EQ(kFakeV2PublicKey, enrollment_manager()->GetUserPublicKey());
+  EXPECT_EQ(kFakeV2PrivateKey, enrollment_manager()->GetUserPrivateKey());
+}
+
+}  // namespace device_sync
+
+}  // namespace chromeos
diff --git a/chromeos/services/device_sync/pref_names.cc b/chromeos/services/device_sync/pref_names.cc
index d9fa93f..9be44a8 100644
--- a/chromeos/services/device_sync/pref_names.cc
+++ b/chromeos/services/device_sync/pref_names.cc
@@ -30,6 +30,13 @@
 const char kCryptAuthDeviceSyncUnlockKeys[] =
     "cryptauth.device_sync.unlock_keys";
 
+// The CryptAuth v2 Enrollment invocation reason to use when retrying a failed
+// enrollment attempt. This should be one of the enum values of
+// cryptauth2::ClientMetadata::InvocationReason in
+// chromeos/services/device_sync/proto/cryptauth_common.proto.
+const char kCryptAuthEnrollmentFailureRecoveryInvocationReason[] =
+    "cryptauth.enrollment.failure_recovery_invocation_reason";
+
 // Whether the system is scheduling enrollments more aggressively to recover
 // from the previous enrollment failure.
 const char kCryptAuthEnrollmentIsRecoveringFromFailure[] =
diff --git a/chromeos/services/device_sync/pref_names.h b/chromeos/services/device_sync/pref_names.h
index a72ed6931..f5c5d55 100644
--- a/chromeos/services/device_sync/pref_names.h
+++ b/chromeos/services/device_sync/pref_names.h
@@ -15,6 +15,7 @@
 extern const char kCryptAuthDeviceSyncIsRecoveringFromFailure[];
 extern const char kCryptAuthDeviceSyncReason[];
 extern const char kCryptAuthDeviceSyncUnlockKeys[];
+extern const char kCryptAuthEnrollmentFailureRecoveryInvocationReason[];
 extern const char kCryptAuthEnrollmentIsRecoveringFromFailure[];
 extern const char kCryptAuthEnrollmentLastEnrollmentTimeSeconds[];
 extern const char kCryptAuthEnrollmentReason[];
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 1e4ee61..93dfb21 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -418,9 +418,6 @@
 }
 
 void AutofillAgent::TriggerRefillIfNeeded(const FormData& form) {
-  if (!base::FeatureList::IsEnabled(features::kAutofillDynamicForms))
-    return;
-
   ReplaceElementIfNowInvalid(form);
 
   FormFieldData field;
@@ -450,8 +447,7 @@
   was_last_action_fill_ = true;
 
   // If this is a re-fill, replace the triggering element if it's invalid.
-  if (base::FeatureList::IsEnabled(features::kAutofillDynamicForms) &&
-      id == kNoQueryId)
+  if (id == kNoQueryId)
     ReplaceElementIfNowInvalid(form);
 
   query_node_autofill_state_ = element_.GetAutofillState();
diff --git a/components/autofill/core/browser/autofill_assistant_unittest.cc b/components/autofill/core/browser/autofill_assistant_unittest.cc
index 40e1482..62230fa 100644
--- a/components/autofill/core/browser/autofill_assistant_unittest.cc
+++ b/components/autofill/core/browser/autofill_assistant_unittest.cc
@@ -70,9 +70,9 @@
 
   void SetUp() {
     payments::TestPaymentsClient* payments_client =
-        new payments::TestPaymentsClient(
-            autofill_driver_.GetURLLoaderFactory(), autofill_client_.GetPrefs(),
-            autofill_client_.GetIdentityManager(), &pdm_);
+        new payments::TestPaymentsClient(autofill_driver_.GetURLLoaderFactory(),
+                                         autofill_client_.GetIdentityManager(),
+                                         &pdm_);
     autofill_client_.set_test_payments_client(
         std::unique_ptr<payments::TestPaymentsClient>(payments_client));
     TestCreditCardSaveManager* credit_card_save_manager =
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index b2200008..559ad664 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -737,8 +737,7 @@
         profile, *form_structure, *autofill_field, sync_state_);
 
     // Set up the information needed for an eventual refill of this form.
-    if (base::FeatureList::IsEnabled(features::kAutofillDynamicForms) &&
-        !form_structure->GetIdentifierForRefill().empty()) {
+    if (!form_structure->GetIdentifierForRefill().empty()) {
       auto& entry =
           filling_contexts_map_[form_structure->GetIdentifierForRefill()];
       auto filling_context = std::make_unique<FillingContext>();
@@ -1403,7 +1402,6 @@
   if (itr != filling_contexts_map_.end())
     filling_context = itr->second.get();
   bool could_attempt_refill =
-      base::FeatureList::IsEnabled(features::kAutofillDynamicForms) &&
       filling_context != nullptr && !filling_context->attempted_refill &&
       !is_refill && !is_credit_card;
 
@@ -2015,9 +2013,6 @@
 }
 
 bool AutofillManager::ShouldTriggerRefill(const FormStructure& form_structure) {
-  if (!base::FeatureList::IsEnabled(features::kAutofillDynamicForms))
-    return false;
-
   // Should not refill if a form with the same name has not been filled before.
   auto itr =
       filling_contexts_map_.find(form_structure.GetIdentifierForRefill());
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index c0d504d..bc5d8e6 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -315,8 +315,7 @@
     payments::TestPaymentsClient* payments_client =
         new payments::TestPaymentsClient(
             autofill_driver_->GetURLLoaderFactory(),
-            autofill_client_.GetPrefs(), autofill_client_.GetIdentityManager(),
-            &personal_data_);
+            autofill_client_.GetIdentityManager(), &personal_data_);
     autofill_client_.set_test_payments_client(
         std::unique_ptr<payments::TestPaymentsClient>(payments_client));
     TestCreditCardSaveManager* credit_card_save_manager =
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index bea3ed2..07abd0eb 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -309,9 +309,9 @@
       std::make_unique<MockAutocompleteHistoryManager>();
 
   payments::TestPaymentsClient* payments_client =
-      new payments::TestPaymentsClient(
-          autofill_driver_->GetURLLoaderFactory(), autofill_client_.GetPrefs(),
-          autofill_client_.GetIdentityManager(), personal_data_.get());
+      new payments::TestPaymentsClient(autofill_driver_->GetURLLoaderFactory(),
+                                       autofill_client_.GetIdentityManager(),
+                                       personal_data_.get());
   autofill_client_.set_test_payments_client(
       std::unique_ptr<payments::TestPaymentsClient>(payments_client));
   TestCreditCardSaveManager* credit_card_save_manager =
@@ -8319,9 +8319,8 @@
 }
 
 TEST_F(AutofillMetricsTest, DynamicFormMetrics) {
-  scoped_feature_list_.InitWithFeatures(
-      {features::kAutofillDynamicForms},
-      {features::kAutofillRestrictUnownedFieldsToFormlessCheckout});
+  scoped_feature_list_.InitAndDisableFeature(
+      features::kAutofillRestrictUnownedFieldsToFormlessCheckout);
 
   // Set up our form data.
   FormData form;
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc
index e896f52..617e9fe 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -803,8 +803,7 @@
   // Payments account. Include a bit for existence of this account (NOT the id
   // itself), as it will help determine if a new Payments customer might need to
   // be created when save is accepted.
-  if (payments::GetBillingCustomerId(personal_data_manager_,
-                                     payments_client_->GetPrefService()) != 0) {
+  if (payments::GetBillingCustomerId(personal_data_manager_) != 0) {
     detected_values |= DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT;
   }
 
@@ -965,8 +964,8 @@
   if (observer_for_testing_)
     observer_for_testing_->OnSentUploadCardRequest();
   upload_request_.app_locale = app_locale_;
-  upload_request_.billing_customer_number = payments::GetBillingCustomerId(
-      personal_data_manager_, payments_client_->GetPrefService());
+  upload_request_.billing_customer_number =
+      payments::GetBillingCustomerId(personal_data_manager_);
 
   AutofillMetrics::LogUploadAcceptedCardOriginMetric(
       uploading_local_card_
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index 3e21079d..a574200 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -28,6 +28,7 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/payments/test_credit_card_save_manager.h"
 #include "components/autofill/core/browser/payments/test_credit_card_save_strike_database.h"
 #include "components/autofill/core/browser/payments/test_legacy_strike_database.h"
@@ -128,7 +129,7 @@
         base::ThreadTaskRunnerHandle::Get());
     autofill_driver_->SetURLRequestContext(request_context_.get());
     payments_client_ = new payments::TestPaymentsClient(
-        autofill_driver_->GetURLLoaderFactory(), autofill_client_.GetPrefs(),
+        autofill_driver_->GetURLLoaderFactory(),
         autofill_client_.GetIdentityManager(), &personal_data_);
     autofill_client_.set_test_payments_client(
         std::unique_ptr<payments::TestPaymentsClient>(payments_client_));
@@ -2302,10 +2303,10 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillUpstreamEditableCardholderName);
 
-  // Set the billing_customer_number Priority Preference to designate existence
-  // of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Create, fill and submit an address form in order to establish a recent
   // profile which can be selected for the upload request.
@@ -2350,10 +2351,10 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillUpstreamEditableCardholderName);
 
-  // Set the billing_customer_number Priority Preference to designate existence
-  // of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Create, fill and submit an address form in order to establish a recent
   // profile which can be selected for the upload request.
@@ -2515,10 +2516,11 @@
   // Verify the |credit_card_save_manager_| is requesting cardholder name.
   EXPECT_TRUE(credit_card_save_manager_->should_request_name_from_user_);
 
-  // Simulate a Chrome/Payments sync where billing_customer_number was newly
-  // set.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Run through the form submit in exactly the same way (but now Chrome knows
   // that the user is a Google Payments customer).
   personal_data_.ClearCreditCards();
@@ -3341,10 +3343,10 @@
 
 TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
        DetectHasGooglePaymentAccount) {
-  // Set the billing_customer_number Priority Preference to designate existence
-  // of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Set up our credit card form data.
   FormData credit_card_form;
diff --git a/components/autofill/core/browser/payments/full_card_request.cc b/components/autofill/core/browser/payments/full_card_request.cc
index 9aa14cbf..746db66 100644
--- a/components/autofill/core/browser/payments/full_card_request.cc
+++ b/components/autofill/core/browser/payments/full_card_request.cc
@@ -69,8 +69,7 @@
   if (should_unmask_card_) {
     payments_client_->Prepare();
     request_->billing_customer_number = GetBillingCustomerId(
-        personal_data_manager_, payments_client_->GetPrefService(),
-        /*should_log_validity=*/true);
+        personal_data_manager_, /*should_log_validity=*/true);
   }
 
   ui_delegate_->ShowUnmaskPrompt(request_->card, reason,
diff --git a/components/autofill/core/browser/payments/full_card_request_unittest.cc b/components/autofill/core/browser/payments/full_card_request_unittest.cc
index fc4486c..a1177a2b 100644
--- a/components/autofill/core/browser/payments/full_card_request_unittest.cc
+++ b/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -18,10 +18,6 @@
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/testing_pref_service.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -77,14 +73,9 @@
         test_shared_loader_factory_(
             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
                 &test_url_loader_factory_)) {
-    std::unique_ptr<TestingPrefServiceSimple> pref_service(
-        new TestingPrefServiceSimple());
-    pref_service->registry()->RegisterDoublePref(
-        prefs::kAutofillBillingCustomerNumber, 0.0);
-    autofill_client_.SetPrefs(std::move(pref_service));
     payments_client_ = std::make_unique<PaymentsClient>(
-        test_shared_loader_factory_, autofill_client_.GetPrefs(),
-        autofill_client_.GetIdentityManager(), &personal_data_);
+        test_shared_loader_factory_, autofill_client_.GetIdentityManager(),
+        &personal_data_);
     request_ = std::make_unique<FullCardRequest>(
         &autofill_client_, payments_client_.get(), &personal_data_);
     personal_data_.SetAccountInfoForPayments(
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager.cc b/components/autofill/core/browser/payments/local_card_migration_manager.cc
index b83dd82..d666966 100644
--- a/components/autofill/core/browser/payments/local_card_migration_manager.cc
+++ b/components/autofill/core/browser/payments/local_card_migration_manager.cc
@@ -208,8 +208,7 @@
           personal_data_manager_->GetAccountInfoForPaymentsServer().email);
 
   bool has_google_payments_account =
-      (payments::GetBillingCustomerId(personal_data_manager_,
-                                      payments_client_->GetPrefService()) != 0);
+      (payments::GetBillingCustomerId(personal_data_manager_) != 0);
 
   AutofillSyncSigninState sync_state =
       personal_data_manager_->GetSyncSigninState();
@@ -338,8 +337,8 @@
     observer_for_testing_->OnSentMigrateCardsRequest();
 
   migration_request_.app_locale = app_locale_;
-  migration_request_.billing_customer_number = payments::GetBillingCustomerId(
-      personal_data_manager_, payments_client_->GetPrefService());
+  migration_request_.billing_customer_number =
+      payments::GetBillingCustomerId(personal_data_manager_);
   payments_client_->MigrateCards(
       migration_request_, migratable_credit_cards_,
       base::BindOnce(&LocalCardMigrationManager::OnDidMigrateLocalCards,
@@ -391,8 +390,7 @@
 
   // Local card migration should ONLY be offered when the user already has a
   // Google Payments account.
-  DCHECK_NE(0, payments::GetBillingCustomerId(
-                   personal_data_manager_, payments_client_->GetPrefService()));
+  DCHECK_NE(0, payments::GetBillingCustomerId(personal_data_manager_));
   detected_values |=
       CreditCardSaveManager::DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT;
 
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
index 1cd6be1..00b217d4 100644
--- a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -27,6 +27,7 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/payments/test_credit_card_save_manager.h"
 #include "components/autofill/core/browser/payments/test_local_card_migration_manager.h"
 #include "components/autofill/core/browser/payments/test_payments_client.h"
@@ -72,7 +73,7 @@
         base::ThreadTaskRunnerHandle::Get());
     autofill_driver_->SetURLRequestContext(request_context_.get());
     payments_client_ = new payments::TestPaymentsClient(
-        autofill_driver_->GetURLLoaderFactory(), autofill_client_.GetPrefs(),
+        autofill_driver_->GetURLLoaderFactory(),
         autofill_client_.GetIdentityManager(), &personal_data_);
     autofill_client_.set_test_payments_client(
         std::unique_ptr<payments::TestPaymentsClient>(payments_client_));
@@ -189,10 +190,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -223,10 +225,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card (but it will not match what we will enter below).
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
                      test::NextYear().c_str(), "1", "guid1");
@@ -254,10 +257,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -301,10 +305,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -335,10 +340,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a masked server credit card whose |TypeAndLastFourDigits| matches what
   // we will enter below.
   CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123");
@@ -385,10 +391,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a masked credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123");
@@ -428,10 +435,11 @@
   scoped_feature_list_.InitAndDisableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -461,10 +469,10 @@
       // Disabled
       {features::kAutofillEnableLocalCardMigrationForNonSyncUser});
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Mock Chrome Sync is disabled.
   local_card_migration_manager_->ResetSyncState(
@@ -500,10 +508,10 @@
       // Disabled
       {});
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Mock Chrome Sync is disabled.
   local_card_migration_manager_->ResetSyncState(
@@ -562,10 +570,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a masked server card whose |TypeAndLastFourDigits| matches a local
   // card.
   CreditCard server_card(CreditCard::MASKED_SERVER_CARD, "a123");
@@ -600,10 +609,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a full server card whose number matches a local card.
   CreditCard server_card(CreditCard::FULL_SERVER_CARD, "a123");
   test::SetCreditCardInfo(&server_card, "Flo Master", "4111111111111111", "11",
@@ -633,10 +643,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -666,10 +677,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -698,10 +710,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -730,10 +743,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -764,10 +778,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -798,10 +813,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card. One migratable credit card will still trigger
   // migration on settings page.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -828,10 +844,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card. One migratable credit card will still trigger
   // migration on settings page.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -868,10 +885,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -900,10 +918,10 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Set that previously user rejected this prompt.
   prefs::SetLocalCardMigrationPromptPreviouslyCancelled(
@@ -938,10 +956,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card for migration.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
                      test::NextYear().c_str(), "1", "guid1");
@@ -980,10 +999,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card. One migratable credit card will still trigger
   // migration on settings page.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -1024,10 +1044,11 @@
   scoped_feature_list_.InitAndEnableFeature(
       features::kAutofillCreditCardLocalCardMigration);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card. One migratable credit card will still trigger
   // migration on settings page.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -1069,8 +1090,11 @@
                      test::NextYear().c_str(), "1", "guid1");
   AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11",
                      test::NextYear().c_str(), "1", "guid2");
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   local_card_migration_manager_->GetMigratableCreditCards();
 
   autofill_client_.set_migration_card_selections(
@@ -1118,10 +1142,11 @@
 
   EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 7);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
   // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
   // enter below.
   AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -1167,10 +1192,10 @@
 
   EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 7);
 
-  // Set the billing_customer_number Priority Preference to designate
-  // existence of a Payments account.
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
   // Add a masked server credit card whose |TypeAndLastFourDigits| matches what
   // we will enter below.
@@ -1223,8 +1248,10 @@
                      test::NextYear().c_str(), "1", "guid1");
   AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11",
                      test::NextYear().c_str(), "1", "guid2");
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
   local_card_migration_manager_->GetMigratableCreditCards();
 
   // Only select one of the two cards.
@@ -1249,8 +1276,10 @@
                      test::NextYear().c_str(), "1", "guid1");
   AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11",
                      test::NextYear().c_str(), "1", "guid2");
-  autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
-                                         12345);
+  // Set the billing_customer_number to designate existence of a Payments
+  // account.
+  personal_data_.SetPaymentsCustomerData(
+      std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
   local_card_migration_manager_->GetMigratableCreditCards();
 
   // Add 4 LocalCardMigration strikes.
diff --git a/components/autofill/core/browser/payments/payments_client.cc b/components/autofill/core/browser/payments/payments_client.cc
index a4f1fb5..bbe5bebf 100644
--- a/components/autofill/core/browser/payments/payments_client.cc
+++ b/components/autofill/core/browser/payments/payments_client.cc
@@ -732,12 +732,10 @@
 
 PaymentsClient::PaymentsClient(
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    PrefService* pref_service,
     identity::IdentityManager* identity_manager,
     AccountInfoGetter* account_info_getter,
     bool is_off_the_record)
     : url_loader_factory_(url_loader_factory),
-      pref_service_(pref_service),
       identity_manager_(identity_manager),
       account_info_getter_(account_info_getter),
       is_off_the_record_(is_off_the_record),
@@ -751,10 +749,6 @@
     StartTokenFetch(false);
 }
 
-PrefService* PaymentsClient::GetPrefService() const {
-  return pref_service_;
-}
-
 void PaymentsClient::UnmaskCard(
     const PaymentsClient::UnmaskRequestDetails& request_details,
     base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
diff --git a/components/autofill/core/browser/payments/payments_client.h b/components/autofill/core/browser/payments/payments_client.h
index 6af5be7..9f6d624 100644
--- a/components/autofill/core/browser/payments/payments_client.h
+++ b/components/autofill/core/browser/payments/payments_client.h
@@ -15,7 +15,6 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/payments/card_unmask_delegate.h"
-#include "components/prefs/pref_service.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "services/identity/public/cpp/access_token_fetcher.h"
 #include "services/identity/public/cpp/access_token_info.h"
@@ -134,13 +133,11 @@
   };
 
   // |url_loader_factory| is reference counted so it has no lifetime or
-  // ownership requirements. |pref_service| is used to get the registered
-  // preference value, |identity_manager| and |account_info_getter|
-  // must all outlive |this|. Either delegate might be nullptr.
-  // |is_off_the_record| denotes incognito mode.
+  // ownership requirements. |identity_manager| and |account_info_getter| must
+  // all outlive |this|. Either delegate might be nullptr. |is_off_the_record|
+  // denotes incognito mode.
   PaymentsClient(
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      PrefService* const pref_service,
       identity::IdentityManager* const identity_manager,
       AccountInfoGetter* const account_info_getter,
       bool is_off_the_record = false);
@@ -154,8 +151,6 @@
   // accepted an upload prompt.
   void Prepare();
 
-  PrefService* GetPrefService() const;
-
   // The user has attempted to unmask a card with the given cvc.
   void UnmaskCard(const UnmaskRequestDetails& request_details,
                   base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
@@ -247,9 +242,6 @@
   // The URL loader factory for the request.
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
-  // The pref service for this client.
-  PrefService* const pref_service_;
-
   // Provided in constructor; not owned by PaymentsClient.
   identity::IdentityManager* const identity_manager_;
 
diff --git a/components/autofill/core/browser/payments/payments_client_unittest.cc b/components/autofill/core/browser/payments/payments_client_unittest.cc
index 819bada1..cd3738b2 100644
--- a/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -24,8 +24,6 @@
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/autofill/core/common/autofill_switches.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/testing_pref_service.h"
 #include "components/variations/net/variations_http_headers.h"
 #include "components/variations/variations_associated_data.h"
 #include "components/variations/variations_http_header_provider.h"
@@ -78,10 +76,9 @@
     test_shared_loader_factory_ =
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
             &test_url_loader_factory_);
-    TestingPrefServiceSimple pref_service_;
     client_ = std::make_unique<PaymentsClient>(
-        test_shared_loader_factory_, &pref_service_,
-        identity_test_env_.identity_manager(), &test_personal_data_);
+        test_shared_loader_factory_, identity_test_env_.identity_manager(),
+        &test_personal_data_);
     test_personal_data_.SetAccountInfoForPayments(
         identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com"));
   }
diff --git a/components/autofill/core/browser/payments/payments_util.cc b/components/autofill/core/browser/payments/payments_util.cc
index 5f99b8d..ee230cb 100644
--- a/components/autofill/core/browser/payments/payments_util.cc
+++ b/components/autofill/core/browser/payments/payments_util.cc
@@ -4,59 +4,44 @@
 
 #include "components/autofill/core/browser/payments/payments_util.h"
 
-#include "base/feature_list.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_payments_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/prefs/pref_service.h"
 
 namespace autofill {
 namespace payments {
 
 int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
-                             PrefService* pref_service,
                              bool should_log_validity) {
   DCHECK(personal_data_manager);
-  DCHECK(pref_service);
 
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillUsePaymentsCustomerData) ||
-      base::FeatureList::IsEnabled(
-          features::kAutofillEnableAccountWalletStorage)) {
-    // Get billing customer ID from the synced PaymentsCustomerData.
-    PaymentsCustomerData* customer_data =
-        personal_data_manager->GetPaymentsCustomerData();
-    if (customer_data && !customer_data->customer_id.empty()) {
-      int64_t billing_customer_id = 0;
-      if (base::StringToInt64(base::StringPiece(customer_data->customer_id),
-                              &billing_customer_id)) {
-        if (should_log_validity) {
-          AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
-              AutofillMetrics::BillingIdStatus::VALID);
-        }
-        return billing_customer_id;
-      } else {
-        if (should_log_validity) {
-          AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
-              AutofillMetrics::BillingIdStatus::PARSE_ERROR);
-        }
+  // Get billing customer ID from the synced PaymentsCustomerData.
+  PaymentsCustomerData* customer_data =
+      personal_data_manager->GetPaymentsCustomerData();
+  if (customer_data && !customer_data->customer_id.empty()) {
+    int64_t billing_customer_id = 0;
+    if (base::StringToInt64(base::StringPiece(customer_data->customer_id),
+                            &billing_customer_id)) {
+      if (should_log_validity) {
+        AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
+            AutofillMetrics::BillingIdStatus::VALID);
       }
+      return billing_customer_id;
     } else {
       if (should_log_validity) {
         AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
-            AutofillMetrics::BillingIdStatus::MISSING);
+            AutofillMetrics::BillingIdStatus::PARSE_ERROR);
       }
     }
+  } else {
+    if (should_log_validity) {
+      AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
+          AutofillMetrics::BillingIdStatus::MISSING);
+    }
   }
-
-  // Get billing customer ID from priority preferences.
-  return static_cast<int64_t>(
-      pref_service->GetDouble(prefs::kAutofillBillingCustomerNumber));
+  return 0;
 }
 
 }  // namespace payments
diff --git a/components/autofill/core/browser/payments/payments_util.h b/components/autofill/core/browser/payments/payments_util.h
index aeca52b..b0cffea 100644
--- a/components/autofill/core/browser/payments/payments_util.h
+++ b/components/autofill/core/browser/payments/payments_util.h
@@ -7,8 +7,6 @@
 
 #include <stdint.h>
 
-class PrefService;
-
 namespace autofill {
 
 class PersonalDataManager;
@@ -20,7 +18,6 @@
 // if the customer ID was not found. If |should_log_validity| is true, will
 // report on the validity state of the customer ID in PaymentsCustomerData.
 int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
-                             PrefService* pref_service,
                              bool should_log_validity = false);
 
 }  // namespace payments
diff --git a/components/autofill/core/browser/payments/payments_util_unittest.cc b/components/autofill/core/browser/payments/payments_util_unittest.cc
index e461f6f..f2efffa 100644
--- a/components/autofill/core/browser/payments/payments_util_unittest.cc
+++ b/components/autofill/core/browser/payments/payments_util_unittest.cc
@@ -5,15 +5,9 @@
 #include "components/autofill/core/browser/payments/payments_util.h"
 
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_payments_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
@@ -25,30 +19,20 @@
   ~PaymentsUtilTest() override {}
 
  protected:
-  void SetUp() override {
-    pref_service_.registry()->RegisterDoublePref(
-        prefs::kAutofillBillingCustomerNumber, 0.0);
-  }
-
-  base::test::ScopedFeatureList scoped_feature_list_;
   TestPersonalDataManager personal_data_manager_;
-  TestingPrefServiceSimple pref_service_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PaymentsUtilTest);
 };
 
 TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_Normal) {
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillUsePaymentsCustomerData);
   base::HistogramTester histogram_tester;
 
   personal_data_manager_.SetPaymentsCustomerData(
       std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
 
-  EXPECT_EQ(123456,
-            GetBillingCustomerId(&personal_data_manager_, &pref_service_,
-                                 /*should_log_validity=*/true));
+  EXPECT_EQ(123456, GetBillingCustomerId(&personal_data_manager_,
+                                         /*should_log_validity=*/true));
 
   histogram_tester.ExpectUniqueSample(
       "Autofill.PaymentsCustomerDataBillingIdStatus",
@@ -56,14 +40,12 @@
 }
 
 TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_Garbage) {
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillUsePaymentsCustomerData);
   base::HistogramTester histogram_tester;
 
   personal_data_manager_.SetPaymentsCustomerData(
       std::make_unique<PaymentsCustomerData>(/*customer_id=*/"garbage"));
 
-  EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_, &pref_service_,
+  EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_,
                                     /*should_log_validity=*/true));
 
   histogram_tester.ExpectUniqueSample(
@@ -72,58 +54,16 @@
 }
 
 TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_NoData) {
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillUsePaymentsCustomerData);
   base::HistogramTester histogram_tester;
 
   // Explictly do not set PaymentsCustomerData. Nothing crashes and the returned
   // customer ID is 0.
-  EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_, &pref_service_,
+  EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_,
                                     /*should_log_validity=*/true));
   histogram_tester.ExpectUniqueSample(
       "Autofill.PaymentsCustomerDataBillingIdStatus",
       AutofillMetrics::BillingIdStatus::MISSING, 1);
 }
 
-TEST_F(PaymentsUtilTest,
-       GetBillingCustomerId_PaymentsCustomerData_NoDataFallback) {
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillUsePaymentsCustomerData);
-  base::HistogramTester histogram_tester;
-
-  // Explictly do not set PaymentsCustomerData but set a fallback to prefs.
-  pref_service_.SetDouble(prefs::kAutofillBillingCustomerNumber, 123456.0);
-
-  // We got the data from prefs and log that the PaymentsCustomerData is
-  // invalid.
-  EXPECT_EQ(123456,
-            GetBillingCustomerId(&personal_data_manager_, &pref_service_,
-                                 /*should_log_validity=*/true));
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.PaymentsCustomerDataBillingIdStatus",
-      AutofillMetrics::BillingIdStatus::MISSING, 1);
-}
-
-TEST_F(PaymentsUtilTest, GetBillingCustomerId_PriorityPrefs_Normal) {
-  scoped_feature_list_.InitAndDisableFeature(
-      features::kAutofillUsePaymentsCustomerData);
-
-  pref_service_.SetDouble(prefs::kAutofillBillingCustomerNumber, 123456.0);
-
-  EXPECT_EQ(123456,
-            GetBillingCustomerId(&personal_data_manager_, &pref_service_,
-                                 /*should_log_validity=*/true));
-}
-
-TEST_F(PaymentsUtilTest, GetBillingCustomerId_PriorityPrefs_NoData) {
-  scoped_feature_list_.InitAndDisableFeature(
-      features::kAutofillUsePaymentsCustomerData);
-
-  // Explictly do not set Prefs data. Nothing crashes and the returned customer
-  // ID is 0.
-  EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_, &pref_service_,
-                                    /*should_log_validity=*/true));
-}
-
 }  // namespace payments
 }  // namespace autofill
diff --git a/components/autofill/core/browser/payments/test_local_card_migration_manager.cc b/components/autofill/core/browser/payments/test_local_card_migration_manager.cc
index 4fd2f67..940a5a5 100644
--- a/components/autofill/core/browser/payments/test_local_card_migration_manager.cc
+++ b/components/autofill/core/browser/payments/test_local_card_migration_manager.cc
@@ -5,9 +5,9 @@
 #include "components/autofill/core/browser/payments/test_local_card_migration_manager.h"
 
 #include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/payments/payments_util.h"
 #include "components/autofill/core/browser/payments/test_payments_client.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
 
 namespace autofill {
 
@@ -30,8 +30,7 @@
       features::LocalCardMigrationExperimentalFlag::kMigrationDisabled;
 
   bool has_google_payments_account =
-      (static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
-           prefs::kAutofillBillingCustomerNumber)) != 0);
+      (payments::GetBillingCustomerId(personal_data_manager_) != 0);
 
   bool sync_feature_enabled =
       (personal_data_manager_->GetSyncSigninState() ==
diff --git a/components/autofill/core/browser/payments/test_payments_client.cc b/components/autofill/core/browser/payments/test_payments_client.cc
index e58fe67..ddcce624 100644
--- a/components/autofill/core/browser/payments/test_payments_client.cc
+++ b/components/autofill/core/browser/payments/test_payments_client.cc
@@ -13,11 +13,9 @@
 
 TestPaymentsClient::TestPaymentsClient(
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_,
-    PrefService* pref_service,
     identity::IdentityManager* identity_manager,
     PersonalDataManager* personal_data_manager)
     : PaymentsClient(url_loader_factory_,
-                     pref_service,
                      identity_manager,
                      personal_data_manager) {}
 
diff --git a/components/autofill/core/browser/payments/test_payments_client.h b/components/autofill/core/browser/payments/test_payments_client.h
index e7f6c928..779326c 100644
--- a/components/autofill/core/browser/payments/test_payments_client.h
+++ b/components/autofill/core/browser/payments/test_payments_client.h
@@ -22,7 +22,6 @@
  public:
   TestPaymentsClient(
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_,
-      PrefService* pref_service,
       identity::IdentityManager* identity_manager,
       PersonalDataManager* personal_data_manager);
 
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 816c180..be83667 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -61,10 +61,6 @@
 const base::Feature kAutofillDeleteDisusedCreditCards{
     "AutofillDeleteDisusedCreditCards", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Controls whether Autofill attemps to fill dynamically changing forms.
-const base::Feature kAutofillDynamicForms{"AutofillDynamicForms",
-                                          base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Controls whether we download server credit cards to the ephemeral
 // account-based storage when sync the transport is enabled.
 const base::Feature kAutofillEnableAccountWalletStorage{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 2a1d3f4..2d3bb30 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -31,7 +31,6 @@
 extern const base::Feature kAutofillCreditCardAssist;
 extern const base::Feature kAutofillDeleteDisusedAddresses;
 extern const base::Feature kAutofillDeleteDisusedCreditCards;
-extern const base::Feature kAutofillDynamicForms;
 extern const base::Feature kAutofillEnableAccountWalletStorage;
 extern const base::Feature kAutofillEnableAccountWalletStorageUpload;
 extern const base::Feature kAutofillEnableCompanyName;
diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/autofill/core/common/autofill_prefs.cc
index 6e37efe..9f721089 100644
--- a/components/autofill/core/common/autofill_prefs.cc
+++ b/components/autofill/core/common/autofill_prefs.cc
@@ -43,10 +43,6 @@
 const char kAutofillAcceptSaveCreditCardPromptState[] =
     "autofill.accept_save_credit_card_prompt_state";
 
-// Integer that is set to the billing customer number fetched from priority
-// preference.
-const char kAutofillBillingCustomerNumber[] = "billing_customer_number";
-
 // Boolean that is true if Autofill is enabled and allowed to save credit card
 // data.
 const char kAutofillCreditCardEnabled[] = "autofill.credit_card_enabled";
@@ -133,9 +129,6 @@
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
   // Synced prefs. Used for cross-device choices, e.g., credit card Autofill.
-  registry->RegisterDoublePref(
-      prefs::kAutofillBillingCustomerNumber, 0.0,
-      user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
   registry->RegisterBooleanPref(
       prefs::kAutofillEnabledDeprecated, true,
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
diff --git a/components/autofill/core/common/autofill_prefs.h b/components/autofill/core/common/autofill_prefs.h
index 47bd73a7..a33f91d 100644
--- a/components/autofill/core/common/autofill_prefs.h
+++ b/components/autofill/core/common/autofill_prefs.h
@@ -19,7 +19,6 @@
 // Alphabetical list of preference names specific to the Autofill
 // component. Keep alphabetized, and document each in the .cc file.
 extern const char kAutofillAcceptSaveCreditCardPromptState[];
-extern const char kAutofillBillingCustomerNumber[];
 // Do not get/set the value of this pref directly. Use provided getter/setter.
 extern const char kAutofillCreditCardEnabled[];
 extern const char kAutofillCreditCardSigninPromoImpressionCount[];
diff --git a/components/browser_sync/profile_sync_service_autofill_unittest.cc b/components/browser_sync/profile_sync_service_autofill_unittest.cc
index 0944b520..1656330b 100644
--- a/components/browser_sync/profile_sync_service_autofill_unittest.cc
+++ b/components/browser_sync/profile_sync_service_autofill_unittest.cc
@@ -106,8 +106,6 @@
                                 atoi(version_info::GetVersionNumber().c_str()));
   registry->RegisterIntegerPref(autofill::prefs::kAutofillLastVersionValidated,
                                 atoi(version_info::GetVersionNumber().c_str()));
-  registry->RegisterDoublePref(autofill::prefs::kAutofillBillingCustomerNumber,
-                               0.0);
   registry->RegisterBooleanPref(
       autofill::prefs::kAutofillJapanCityFieldMigrated, true);
   registry->RegisterBooleanPref(autofill::prefs::kAutofillOrphanRowsRemoved,
diff --git a/components/chrome_cleaner/test/test_name_helper.h b/components/chrome_cleaner/test/test_name_helper.h
index 080e7c8..bdc5a806 100644
--- a/components/chrome_cleaner/test/test_name_helper.h
+++ b/components/chrome_cleaner/test/test_name_helper.h
@@ -25,6 +25,10 @@
 //
 // * A string initialized with the literal L"wide string" is formatted as
 // Lwide_string. No known workaround.
+//
+// Note that long test names can cause problems because they can be used to
+// generate file names, which have a max length of 255 on Windows. So use this
+// judiciously.
 struct GetParamNameForTest {
   template <typename ParamType>
   std::string operator()(
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index 47a2f366..233043e 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -1624,7 +1624,8 @@
 #if defined(OS_ANDROID)
     // For content URIs, target file path is the same as the current path.
     if (full_path.IsContentUri()) {
-      SetDisplayName(GetTargetFilePath().BaseName());
+      if (display_name_.empty())
+        SetDisplayName(GetTargetFilePath().BaseName());
       destination_info_.target_path = full_path;
     }
 #endif  // defined(OS_ANDROID)
diff --git a/components/exo/wayland/wayland_keyboard_delegate.cc b/components/exo/wayland/wayland_keyboard_delegate.cc
index 80f82ca3..3344a33 100644
--- a/components/exo/wayland/wayland_keyboard_delegate.cc
+++ b/components/exo/wayland/wayland_keyboard_delegate.cc
@@ -8,6 +8,7 @@
 #include <wayland-server-protocol-core.h>
 
 #include "base/containers/flat_map.h"
+#include "ui/events/keycodes/dom/dom_code.h"
 
 namespace exo {
 namespace wayland {
@@ -80,6 +81,12 @@
       keyboard_resource_, serial, TimeTicksToMilliseconds(time_stamp),
       DomCodeToKey(key),
       pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
+  // Unlike normal wayland clients, the X11 server tries to maintain its own
+  // modifier state, which it updates based on key events. To prevent numlock
+  // presses from allowing numpad keys to be interpreted as directions, we
+  // re-send the modifier state after a numlock press.
+  if (key == ui::DomCode::NUM_LOCK)
+    SendKeyboardModifiers();
   wl_client_flush(client());
   return serial;
 }
@@ -89,17 +96,8 @@
   // key disabled, (i.e. chromeos apps specially handle numpad key events as
   // though numlock is on). In order to get the same result from the linux apps,
   // we need to ensure they always treat numlock as on.
-  modifier_flags |= ui::EF_NUM_LOCK_ON;
-  xkb_state_update_mask(xkb_state_.get(),
-                        ModifierFlagsToXkbModifiers(modifier_flags), 0, 0, 0, 0,
-                        0);
-  wl_keyboard_send_modifiers(
-      keyboard_resource_, next_serial(),
-      xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_DEPRESSED),
-      xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LOCKED),
-      xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LATCHED),
-      xkb_state_serialize_layout(xkb_state_.get(), XKB_STATE_LAYOUT_EFFECTIVE));
-  wl_client_flush(client());
+  modifier_flags_ = modifier_flags | ui::EF_NUM_LOCK_ON;
+  SendKeyboardModifiers();
 }
 
 #if defined(OS_CHROMEOS)
@@ -121,8 +119,7 @@
   return xkb_keycode - 8;
 }
 
-uint32_t WaylandKeyboardDelegate::ModifierFlagsToXkbModifiers(
-    int modifier_flags) {
+uint32_t WaylandKeyboardDelegate::ModifierFlagsToXkbModifiers() {
   struct {
     ui::EventFlags flag;
     const char* xkb_name;
@@ -138,7 +135,7 @@
   };
   uint32_t xkb_modifiers = 0;
   for (auto modifier : modifiers) {
-    if (modifier_flags & modifier.flag) {
+    if (modifier_flags_ & modifier.flag) {
       xkb_modifiers |=
           1 << xkb_keymap_mod_get_index(xkb_keymap_.get(), modifier.xkb_name);
     }
@@ -146,6 +143,18 @@
   return xkb_modifiers;
 }
 
+void WaylandKeyboardDelegate::SendKeyboardModifiers() {
+  xkb_state_update_mask(xkb_state_.get(), ModifierFlagsToXkbModifiers(), 0, 0,
+                        0, 0, 0);
+  wl_keyboard_send_modifiers(
+      keyboard_resource_, next_serial(),
+      xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_DEPRESSED),
+      xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LOCKED),
+      xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LATCHED),
+      xkb_state_serialize_layout(xkb_state_.get(), XKB_STATE_LAYOUT_EFFECTIVE));
+  wl_client_flush(client());
+}
+
 #if defined(OS_CHROMEOS)
 void WaylandKeyboardDelegate::SendNamedLayout(const std::string& layout_name) {
   std::string layout_id, layout_variant;
diff --git a/components/exo/wayland/wayland_keyboard_delegate.h b/components/exo/wayland/wayland_keyboard_delegate.h
index de5d7e78..ee5d447 100644
--- a/components/exo/wayland/wayland_keyboard_delegate.h
+++ b/components/exo/wayland/wayland_keyboard_delegate.h
@@ -72,8 +72,11 @@
   // Returns the corresponding key given a dom code.
   uint32_t DomCodeToKey(ui::DomCode code) const;
 
-  // Returns a set of Xkb modififers given a set of modifier flags.
-  uint32_t ModifierFlagsToXkbModifiers(int modifier_flags);
+  // Returns a set of Xkb modififers given the current |modifier_flags_|.
+  uint32_t ModifierFlagsToXkbModifiers();
+
+  // Sends the current |modifier_flags_| to the client.
+  void SendKeyboardModifiers();
 
 #if defined(OS_CHROMEOS)
   // Send the named keyboard layout to the client.
@@ -97,6 +100,10 @@
   std::unique_ptr<xkb_keymap, ui::XkbKeymapDeleter> xkb_keymap_;
   std::unique_ptr<xkb_state, ui::XkbStateDeleter> xkb_state_;
 
+  // The delegate will keep its clients updated with these modifiers. For CrOS
+  // we treat numlock as always on.
+  int modifier_flags_ = ui::EF_NUM_LOCK_ON;
+
   DISALLOW_COPY_AND_ASSIGN(WaylandKeyboardDelegate);
 #endif
 };
diff --git a/components/guest_view/renderer/guest_view_container.cc b/components/guest_view/renderer/guest_view_container.cc
index 1a15b9bc..e254682 100644
--- a/components/guest_view/renderer/guest_view_container.cc
+++ b/components/guest_view/renderer/guest_view_container.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "components/guest_view/common/guest_view_constants.h"
 #include "components/guest_view/common/guest_view_messages.h"
 #include "components/guest_view/renderer/guest_view_request.h"
@@ -248,8 +247,9 @@
   if (element_resize_callback_.IsEmpty())
     return;
 
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&GuestViewContainer::CallElementResizeCallback,
+  render_frame_->GetTaskRunner(blink::TaskType::kInternalDefault)
+      ->PostTask(FROM_HERE,
+                 base::BindOnce(&GuestViewContainer::CallElementResizeCallback,
                                 weak_ptr_factory_.GetWeakPtr(), new_size));
 }
 
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index 637f504..360911e 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -1372,7 +1372,7 @@
   // non-keyword suggestions if we're not confident that the user entered
   // keyword mode explicitly.
   return OmniboxFieldTrial::IsExperimentalKeywordModeEnabled() &&
-         !keyword_input_.text().empty() && keyword_input_.prefer_keyword() &&
+         keyword_input_.prefer_keyword() &&
          keyword_input_.keyword_mode_entry_method() !=
              OmniboxEventProto::SPACE_AT_END &&
          keyword_input_.keyword_mode_entry_method() !=
diff --git a/components/payments/core/autofill_payment_instrument_unittest.cc b/components/payments/core/autofill_payment_instrument_unittest.cc
index ea5b0b6..aff26be 100644
--- a/components/payments/core/autofill_payment_instrument_unittest.cc
+++ b/components/payments/core/autofill_payment_instrument_unittest.cc
@@ -69,7 +69,6 @@
             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
                 &test_url_loader_factory_)),
         payments_client_(test_shared_loader_factory_,
-                         /*pref_service=*/nullptr,
                          /*identity_manager=*/nullptr,
                          /*account_info_getter=*/nullptr),
         full_card_request_(&autofill_client_,
diff --git a/components/payments/core/test_payment_request_delegate.cc b/components/payments/core/test_payment_request_delegate.cc
index 3a00584..bc6a3bcb 100644
--- a/components/payments/core/test_payment_request_delegate.cc
+++ b/components/payments/core/test_payment_request_delegate.cc
@@ -18,7 +18,6 @@
           base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
               &test_url_loader_factory_)),
       payments_client_(test_shared_loader_factory_,
-                       /*pref_service=*/nullptr,
                        /*identity_manager=*/nullptr,
                        personal_data_manager),
       full_card_request_(&autofill_client_,
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index a54320f..222db5c 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -945,8 +945,10 @@
   DCHECK(!on_ready_.is_null());
   // Don't call callback here, because it can delete |this| and WebView that is
   // called didStopLoading.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&PrepareFrameAndViewForPrint::CallOnReady,
+  frame()
+      ->GetTaskRunner(blink::TaskType::kInternalDefault)
+      ->PostTask(FROM_HERE,
+                 base::BindOnce(&PrepareFrameAndViewForPrint::CallOnReady,
                                 weak_ptr_factory_.GetWeakPtr()));
 }
 
diff --git a/components/services/font/BUILD.gn b/components/services/font/BUILD.gn
index 891bf03..5ed757f 100644
--- a/components/services/font/BUILD.gn
+++ b/components/services/font/BUILD.gn
@@ -33,10 +33,6 @@
   if (is_linux && enable_plugins) {
     deps += [ ":ppapi_fontconfig_matching" ]
   }
-
-  if (is_linux) {
-    deps += [ "//base/test:fontconfig_util_linux" ]
-  }
 }
 
 if (is_linux && enable_plugins) {
diff --git a/components/services/font/font_service_app.cc b/components/services/font/font_service_app.cc
index b1a2850..f1bf0e7 100644
--- a/components/services/font/font_service_app.cc
+++ b/components/services/font/font_service_app.cc
@@ -21,10 +21,6 @@
 #include "components/services/font/ppapi_fontconfig_matching.h"  // nogncheck
 #endif
 
-#if defined(OS_LINUX)
-#include "base/test/fontconfig_util_linux.h"
-#endif
-
 static_assert(
     static_cast<uint32_t>(SkFontStyle::kUpright_Slant) ==
         static_cast<uint32_t>(font_service::mojom::TypefaceSlant::ROMAN),
diff --git a/components/viz/common/frame_sinks/begin_frame_args.h b/components/viz/common/frame_sinks/begin_frame_args.h
index faf8491..33fc0eb9 100644
--- a/components/viz/common/frame_sinks/begin_frame_args.h
+++ b/components/viz/common/frame_sinks/begin_frame_args.h
@@ -86,14 +86,18 @@
     return base::TimeDelta::FromMicroseconds(16666);
   }
 
-  // This is a hard-coded deadline adjustment that assumes 60Hz, to be used in
-  // cases where a good estimated draw time is not known. Using 1/3 of the vsync
-  // as the default adjustment gives the Browser the last 1/3 of a frame to
-  // produce output, the Renderer Impl thread the middle 1/3 of a frame to
-  // produce ouput, and the Renderer Main thread the first 1/3 of a frame to
-  // produce output.
-  static constexpr base::TimeDelta DefaultEstimatedParentDrawTime() {
-    return base::TimeDelta::FromMicroseconds(16666 / 3);
+  // This is a hard-coded deadline adjustment used by the display compositor.
+  // Using 1/3 of the vsync as the default adjustment gives the display
+  // compositor the last 1/3 of a frame to produce output, the client impl
+  // thread the middle 1/3 of a frame to produce output, and the client's main
+  // thread the first 1/3 of a frame to produce output.
+  static constexpr float kDefaultEstimatedDisplayDrawTimeRatio = 1.f / 3;
+
+  // Returns how much time the display should reserve for draw and swap if the
+  // BeginFrame interval is |interval|.
+  static base::TimeDelta DefaultEstimatedDisplayDrawTime(
+      base::TimeDelta interval) {
+    return interval * kDefaultEstimatedDisplayDrawTimeRatio;
   }
 
   bool IsValid() const { return interval >= base::TimeDelta(); }
diff --git a/components/viz/service/display/display_scheduler.cc b/components/viz/service/display/display_scheduler.cc
index 351a025..055624b 100644
--- a/components/viz/service/display/display_scheduler.cc
+++ b/components/viz/service/display/display_scheduler.cc
@@ -259,7 +259,7 @@
   // Schedule the deadline.
   current_begin_frame_args_ = save_args;
   current_begin_frame_args_.deadline -=
-      BeginFrameArgs::DefaultEstimatedParentDrawTime();
+      BeginFrameArgs::DefaultEstimatedDisplayDrawTime(save_args.interval);
   inside_begin_frame_deadline_interval_ = true;
   UpdateHasPendingSurfaces();
   ScheduleBeginFrameDeadline();
diff --git a/components/viz/service/display/display_scheduler_unittest.cc b/components/viz/service/display/display_scheduler_unittest.cc
index bd7f380..2abcfe07 100644
--- a/components/viz/service/display/display_scheduler_unittest.cc
+++ b/components/viz/service/display/display_scheduler_unittest.cc
@@ -687,7 +687,8 @@
   AdvanceTimeAndBeginFrameForTest({sid2});
   base::TimeTicks expected_deadline =
       scheduler_.LastUsedBeginFrameArgs().deadline -
-      BeginFrameArgs::DefaultEstimatedParentDrawTime();
+      BeginFrameArgs::DefaultEstimatedDisplayDrawTime(
+          scheduler_.LastUsedBeginFrameArgs().interval);
   EXPECT_EQ(expected_deadline,
             scheduler_.DesiredBeginFrameDeadlineTimeForTest());
   // Still waiting for surface 2. Once it updates, deadline should trigger
diff --git a/components/viz/test/begin_frame_args_test.cc b/components/viz/test/begin_frame_args_test.cc
index 5f7c777..e7733666 100644
--- a/components/viz/test/begin_frame_args_test.cc
+++ b/components/viz/test/begin_frame_args_test.cc
@@ -28,7 +28,8 @@
   return BeginFrameArgs::Create(
       location, source_id, sequence_number, frame_time,
       frame_time + BeginFrameArgs::DefaultInterval() -
-          BeginFrameArgs::DefaultEstimatedParentDrawTime(),
+          BeginFrameArgs::DefaultEstimatedDisplayDrawTime(
+              BeginFrameArgs::DefaultInterval()),
       BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
 }
 
@@ -70,7 +71,8 @@
   return BeginFrameArgs::Create(
       location, source_id, sequence_number, now,
       now + BeginFrameArgs::DefaultInterval() -
-          BeginFrameArgs::DefaultEstimatedParentDrawTime(),
+          BeginFrameArgs::DefaultEstimatedDisplayDrawTime(
+              BeginFrameArgs::DefaultInterval()),
       BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
 }
 
diff --git a/content/browser/accessibility/accessibility_event_recorder_uia_win.cc b/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
index 279ed65..ecf52314 100644
--- a/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
+++ b/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
@@ -5,6 +5,7 @@
 #include "content/browser/accessibility/accessibility_event_recorder_uia_win.h"
 
 #include <algorithm>
+#include <numeric>
 #include <utility>
 
 #include "base/strings/string_util.h"
@@ -135,6 +136,15 @@
   // Subscribe to focus events
   uia_->AddFocusChangedEventHandler(nullptr, uia_event_handler_.Get());
 
+  // Subscribe to all property-change events
+  static const PROPERTYID kMinProp = UIA_RuntimeIdPropertyId;
+  static const PROPERTYID kMaxProp = UIA_HeadingLevelPropertyId;
+  std::array<PROPERTYID, (kMaxProp - kMinProp) + 1> property_list;
+  std::iota(property_list.begin(), property_list.end(), kMinProp);
+  uia_->AddPropertyChangedEventHandlerNativeArray(
+      root_.Get(), TreeScope::TreeScope_Subtree, nullptr,
+      uia_event_handler_.Get(), &property_list[0], property_list.size());
+
   // Subscribe to all automation events
   static const EVENTID kMinEvent = UIA_ToolTipOpenedEventId;
   static const EVENTID kMaxEvent = UIA_NotificationEventId;
@@ -270,6 +280,25 @@
 }
 
 STDMETHODIMP
+AccessibilityEventRecorderUia::Thread::EventHandler::HandlePropertyChangedEvent(
+    IUIAutomationElement* sender,
+    PROPERTYID property_id,
+    VARIANT new_value) {
+  if (owner_) {
+    std::string prop_str = UiaIdentifierToStringPretty(property_id);
+    if (prop_str.empty()) {
+      VLOG(1) << "Ignoring UIA property-changed event " << property_id;
+      return S_OK;
+    }
+
+    std::string log = base::StringPrintf("%s changed %s", prop_str.c_str(),
+                                         GetSenderInfo(sender).c_str());
+    owner_->OnEvent(log);
+  }
+  return S_OK;
+}
+
+STDMETHODIMP
 AccessibilityEventRecorderUia::Thread::EventHandler::HandleAutomationEvent(
     IUIAutomationElement* sender,
     EVENTID event_id) {
diff --git a/content/browser/accessibility/accessibility_event_recorder_uia_win.h b/content/browser/accessibility/accessibility_event_recorder_uia_win.h
index f3d7389c..27da120b 100644
--- a/content/browser/accessibility/accessibility_event_recorder_uia_win.h
+++ b/content/browser/accessibility/accessibility_event_recorder_uia_win.h
@@ -82,6 +82,7 @@
     // notifications to the owning event recorder.
     class EventHandler : public CComObjectRootEx<CComMultiThreadModel>,
                          public IUIAutomationFocusChangedEventHandler,
+                         public IUIAutomationPropertyChangedEventHandler,
                          public IUIAutomationEventHandler {
      public:
       EventHandler();
@@ -93,12 +94,19 @@
 
       BEGIN_COM_MAP(EventHandler)
       COM_INTERFACE_ENTRY(IUIAutomationFocusChangedEventHandler)
+      COM_INTERFACE_ENTRY(IUIAutomationPropertyChangedEventHandler)
       COM_INTERFACE_ENTRY(IUIAutomationEventHandler)
       END_COM_MAP()
 
       // IUIAutomationFocusChangedEventHandler interface.
       STDMETHOD(HandleFocusChangedEvent)(IUIAutomationElement* sender) override;
 
+      // IUIAutomationPropertyChangedEventHandler interface.
+      STDMETHOD(HandlePropertyChangedEvent)
+      (IUIAutomationElement* sender,
+       PROPERTYID property_id,
+       VARIANT new_value) override;
+
       // IUIAutomationEventHandler interface.
       STDMETHOD(HandleAutomationEvent)
       (IUIAutomationElement* sender, EVENTID event_id) override;
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 3023cf5..1750b4e 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -1354,6 +1354,31 @@
       IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION);
 }
 
+base::string16 BrowserAccessibility::GetLocalizedStringForLandmarkType() const {
+  const ContentClient* content_client = content::GetContentClient();
+  const ui::AXNodeData& data = GetData();
+
+  switch (data.role) {
+    case ax::mojom::Role::kBanner:
+      return content_client->GetLocalizedString(IDS_AX_ROLE_BANNER);
+
+    case ax::mojom::Role::kComplementary:
+      return content_client->GetLocalizedString(IDS_AX_ROLE_COMPLEMENTARY);
+
+    case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
+      return content_client->GetLocalizedString(IDS_AX_ROLE_CONTENT_INFO);
+
+    case ax::mojom::Role::kRegion:
+      if (data.HasStringAttribute(ax::mojom::StringAttribute::kName))
+        return content_client->GetLocalizedString(IDS_AX_ROLE_REGION);
+      FALLTHROUGH;
+
+    default:
+      return {};
+  }
+}
+
 bool BrowserAccessibility::ShouldIgnoreHoveredStateForTesting() {
   BrowserAccessibilityStateImpl* accessibility_state =
       BrowserAccessibilityStateImpl::GetInstance();
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 90086a4..e58caa5 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -403,6 +403,7 @@
   base::string16 GetLocalizedStringForImageAnnotationStatus(
       ax::mojom::ImageAnnotationStatus status) const override;
   base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() const override;
+  base::string16 GetLocalizedStringForLandmarkType() const override;
   bool ShouldIgnoreHoveredStateForTesting() override;
   bool IsOffscreen() const override;
   bool IsWebContent() const override;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index 6f4ced3..9480d880 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/win/scoped_variant.h"
 #include "base/win/windows_version.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
 #include "content/browser/accessibility/browser_accessibility_win.h"
@@ -191,13 +192,22 @@
     case ui::AXEventGenerator::Event::SELECTED_CHANGED:
       HandleSelectedStateChanged(node);
       break;
-    case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
     case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
-    case ui::AXEventGenerator::Event::COLLAPSED:
-    case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
-    case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+      FireUiaPropertyChangedEvent(UIA_ToggleToggleStatePropertyId, node);
+      break;
     case ui::AXEventGenerator::Event::EXPANDED:
+    case ui::AXEventGenerator::Event::COLLAPSED:
+      FireUiaPropertyChangedEvent(
+          UIA_ExpandCollapseExpandCollapseStatePropertyId, node);
+      break;
+    case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
+      FireUiaPropertyChangedEvent(UIA_FullDescriptionPropertyId, node);
+      break;
     case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
+      FireUiaPropertyChangedEvent(UIA_IsDataValidForFormPropertyId, node);
+      break;
+    case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
+    case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
     case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
     case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
     case ui::AXEventGenerator::Event::LOAD_START:
@@ -247,6 +257,25 @@
                             uia_event);
 }
 
+void BrowserAccessibilityManagerWin::FireUiaPropertyChangedEvent(
+    LONG uia_property,
+    BrowserAccessibility* node) {
+  if (!ShouldFireEventForNode(node))
+    return;
+
+  // The old value is not used by the system
+  VARIANT old_value = {};
+  old_value.vt = VT_EMPTY;
+
+  auto* provider = ToBrowserAccessibilityWin(node)->GetCOM();
+  base::win::ScopedVariant new_value;
+  if (SUCCEEDED(
+          provider->GetPropertyValue(uia_property, new_value.Receive()))) {
+    ::UiaRaiseAutomationPropertyChangedEvent(provider, uia_property, old_value,
+                                             new_value);
+  }
+}
+
 bool BrowserAccessibilityManagerWin::CanFireEvents() {
   if (!BrowserAccessibilityManager::CanFireEvents())
     return false;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h
index 32819b2..ce30bb9 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -54,6 +54,8 @@
 
   void FireWinAccessibilityEvent(LONG win_event, BrowserAccessibility* node);
   void FireUiaAccessibilityEvent(LONG uia_event, BrowserAccessibility* node);
+  void FireUiaPropertyChangedEvent(LONG uia_property,
+                                   BrowserAccessibility* node);
 
   // Track this object and post a VISIBLE_DATA_CHANGED notification when
   // its container scrolls.
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 796327d..e935e7c 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -12,7 +12,10 @@
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -67,6 +70,12 @@
   void TearDownOnMainThread() override;
 
  protected:
+  BrowserAccessibilityManager* GetManager() {
+    WebContentsImpl* web_contents =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    return web_contents->GetRootBrowserAccessibilityManager();
+  }
+
   std::string GetAttr(const ui::AXNode* node,
                       const ax::mojom::StringAttribute attr);
   int GetIntAttr(const ui::AXNode* node, const ax::mojom::IntAttribute attr);
@@ -457,4 +466,80 @@
   EXPECT_EQ(-1, GetIntAttr(header5, ax::mojom::IntAttribute::kSortDirection));
 }
 
+IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
+                       LocalizedLandmarkType) {
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kLoadComplete);
+  GURL url(
+      "data:text/html,"
+      "<!doctype html>"
+      "<header aria-label='header'></header>"
+      "<aside aria-label='aside'></aside>"
+      "<footer aria-label='footer'></footer>"
+      "<form aria-label='form'></form>"
+      "<main aria-label='main'></main>"
+      "<nav aria-label='nav'></nav>"
+      "<section></section>"
+      "<section aria-label='section'></section>"
+      "<div role='banner' aria-label='banner'></div>"
+      "<div role='complementary' aria-label='complementary'></div>"
+      "<div role='contentinfo' aria-label='contentinfo'></div>"
+      "<div role='form' aria-label='role_form'></div>"
+      "<div role='main' aria-label='role_main'></div>"
+      "<div role='navigation' aria-label='role_nav'></div>"
+      "<div role='region'></div>"
+      "<div role='region' aria-label='region'></div>"
+      "<div role='search' aria-label='search'></div>");
+
+  NavigateToURL(shell(), url);
+  waiter.WaitForNotification();
+
+  BrowserAccessibility* root = GetManager()->GetRoot();
+  ASSERT_NE(nullptr, root);
+  ASSERT_EQ(17u, root->PlatformChildCount());
+
+  auto TestLocalizedLandmarkType =
+      [root](int child_index, ax::mojom::Role expected_role,
+             const std::string& expected_name,
+             const base::string16& expected_localized_landmark_type = {}) {
+        BrowserAccessibility* node = root->PlatformGetChild(child_index);
+        ASSERT_NE(nullptr, node);
+
+        EXPECT_EQ(expected_role, node->GetRole());
+        EXPECT_EQ(expected_name,
+                  node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+        EXPECT_EQ(expected_localized_landmark_type,
+                  node->GetLocalizedStringForLandmarkType());
+      };
+
+  // For testing purposes, assume we get en-US localized strings.
+  TestLocalizedLandmarkType(0, ax::mojom::Role::kBanner, "header",
+                            base::ASCIIToUTF16("banner"));
+  TestLocalizedLandmarkType(1, ax::mojom::Role::kComplementary, "aside",
+                            base::ASCIIToUTF16("complementary"));
+  TestLocalizedLandmarkType(2, ax::mojom::Role::kFooter, "footer",
+                            base::ASCIIToUTF16("content info"));
+  TestLocalizedLandmarkType(3, ax::mojom::Role::kForm, "form");
+  TestLocalizedLandmarkType(4, ax::mojom::Role::kMain, "main");
+  TestLocalizedLandmarkType(5, ax::mojom::Role::kNavigation, "nav");
+  TestLocalizedLandmarkType(6, ax::mojom::Role::kRegion, "");
+  TestLocalizedLandmarkType(7, ax::mojom::Role::kRegion, "section",
+                            base::ASCIIToUTF16("region"));
+
+  TestLocalizedLandmarkType(8, ax::mojom::Role::kBanner, "banner",
+                            base::ASCIIToUTF16("banner"));
+  TestLocalizedLandmarkType(9, ax::mojom::Role::kComplementary, "complementary",
+                            base::ASCIIToUTF16("complementary"));
+  TestLocalizedLandmarkType(10, ax::mojom::Role::kContentInfo, "contentinfo",
+                            base::ASCIIToUTF16("content info"));
+  TestLocalizedLandmarkType(11, ax::mojom::Role::kForm, "role_form");
+  TestLocalizedLandmarkType(12, ax::mojom::Role::kMain, "role_main");
+  TestLocalizedLandmarkType(13, ax::mojom::Role::kNavigation, "role_nav");
+  TestLocalizedLandmarkType(14, ax::mojom::Role::kRegion, "");
+  TestLocalizedLandmarkType(15, ax::mojom::Role::kRegion, "region",
+                            base::ASCIIToUTF16("region"));
+  TestLocalizedLandmarkType(16, ax::mojom::Role::kSearch, "search");
+}
+
 }  // namespace content
diff --git a/content/browser/appcache/appcache_backend_impl.cc b/content/browser/appcache/appcache_backend_impl.cc
index c8c75951..c72648f 100644
--- a/content/browser/appcache/appcache_backend_impl.cc
+++ b/content/browser/appcache/appcache_backend_impl.cc
@@ -51,6 +51,15 @@
     // here on.
     host->set_frontend(std::move(frontend), render_frame_id);
   } else {
+    if (id < 0) {
+      // Negative ids correspond to precreated hosts. We should be able to
+      // retrieve one, but currently we have a race between this IPC and
+      // browser removing the corresponding frame and precreated AppCacheHost.
+      // Instead of crashing the renderer or returning wrong host, we do not
+      // bind any host and let renderer do nothing until it is destroyed by
+      // the request from browser.
+      return;
+    }
     host = std::make_unique<AppCacheHost>(id, process_id(), render_frame_id,
                                           std::move(frontend), service_);
   }
diff --git a/content/browser/appcache/appcache_navigation_handle.h b/content/browser/appcache/appcache_navigation_handle.h
index c31bff3..61b5be8 100644
--- a/content/browser/appcache/appcache_navigation_handle.h
+++ b/content/browser/appcache/appcache_navigation_handle.h
@@ -28,27 +28,26 @@
 //   2) When the navigation request is sent to the IO thread, we include a
 //      pointer to the AppCacheNavigationHandleCore.
 //
-//   3. The AppCacheHost instance is created and its ownership is passed to the
-//      AppCacheNavigationHandleCore instance. Now the app cache host id is
-//      updated.
+//   3) The AppCacheHost instance is created and its ownership is passed to the
+//      AppCacheNavigationHandleCore instance.
 //
-//   4) The AppCacheNavigationHandleCore instance informs the
-//      AppCacheNavigationHandle instance on the UI thread that the app cache
-//      host id was updated.
-//
-//   5) When the navigation is ready to commit, the NavigationRequest will
+//   4) When the navigation is ready to commit, the NavigationRequest will
 //      update the CommitNavigationParams based on the id from the
 //      AppCacheNavigationHandle.
 //
-//   6) The commit leads to AppCache registrations happening from the renderer.
-//      This is via the IPC message AppCacheHostMsg_RegisterHost. The
-//      AppCacheDispatcherHost class which handles these IPCs will be informed
+//   5) The commit leads to AppCache registrations happening from the renderer.
+//      This is via the AppCacheBackend.RegisterHost mojo call. The
+//      AppCacheBackendImpl class which handles these calls will be informed
 //      about these hosts when the navigation commits. It will ignore the
 //      host registrations as they have already been registered. The
 //      ownership of the AppCacheHost is passed from the
-//      AppCacheNavigationHandle core to the AppCacheBackend.
-
-//   7) When the navigation finishes, the AppCacheNavigationHandle is
+//      AppCacheNavigationHandle core to the AppCacheBackendImpl.
+//
+//   6) Meanwhile, RenderFrameHostImpl takes ownership of
+//      AppCacheNavigationHandle once navigation commits, so that precreated
+//      AppCacheHost is not destroyed before IPC above reaches AppCacheBackend.
+//
+//   7) When the next navigation commits, previous AppCacheNavigationHandle is
 //      destroyed. The destructor of the AppCacheNavigationHandle posts a
 //      task to destroy the AppCacheNavigationHandleCore on the IO thread.
 
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index 369c219..8191262c 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -538,6 +538,11 @@
       appcache_service, ChildProcessHost::kInvalidUniqueID));
 }
 
+std::unique_ptr<AppCacheNavigationHandle>
+NavigationHandleImpl::TakeAppCacheHandle() {
+  return std::move(appcache_handle_);
+}
+
 void NavigationHandleImpl::WillStartRequest(
     ThrottleChecksFinishedCallback callback) {
   TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index ff063805..9fa4dbc8 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -214,6 +214,8 @@
     return appcache_handle_.get();
   }
 
+  std::unique_ptr<AppCacheNavigationHandle> TakeAppCacheHandle();
+
   typedef base::OnceCallback<void(NavigationThrottle::ThrottleCheckResult)>
       ThrottleChecksFinishedCallback;
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index cf701a9a..191e3f29 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -13,7 +13,6 @@
 #include "base/command_line.h"
 #include "base/containers/queue.h"
 #include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/hash.h"
 #include "base/lazy_instance.h"
 #include "base/memory/ptr_util.h"
@@ -34,6 +33,7 @@
 #include "cc/base/switches.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/appcache/appcache_navigation_handle.h"
 #include "content/browser/background_fetch/background_fetch_service_impl.h"
 #include "content/browser/bluetooth/web_bluetooth_service_impl.h"
 #include "content/browser/browser_main_loop.h"
@@ -4545,33 +4545,6 @@
       FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type) ||
       !IsURLHandledByNetworkStack(common_params.url));
 
-  // If this is an attempt to commit a URL in an incompatible process, capture a
-  // crash dump to diagnose why it is occurring.
-  // TODO(creis): Remove this check after we've gathered enough information to
-  // debug issues with browser-side security checks. https://crbug.com/931895.
-  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
-  const GURL& lock_url = GetSiteInstance()->lock_url();
-  if (lock_url != GURL(kUnreachableWebDataURL) &&
-      common_params.url.IsStandard() &&
-      !policy->CanAccessDataForOrigin(GetProcess()->GetID(),
-                                      common_params.url)) {
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("lock_url",
-                                            base::debug::CrashKeySize::Size64),
-        lock_url.spec());
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("commit_origin",
-                                            base::debug::CrashKeySize::Size64),
-        common_params.url.GetOrigin().spec());
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("is_main_frame",
-                                            base::debug::CrashKeySize::Size32),
-        frame_tree_node_->IsMainFrame() ? "true" : "false");
-    NOTREACHED() << "Commiting in incompatible process for URL: " << lock_url
-                 << " lock vs " << common_params.url.GetOrigin();
-    base::debug::DumpWithoutCrashing();
-  }
-
   const bool is_first_navigation = !has_committed_any_navigation_;
   has_committed_any_navigation_ = true;
 
@@ -6281,6 +6254,8 @@
        committed_request->GetMimeType() == "message/rfc822");
 
   accessibility_reset_count_ = 0;
+  appcache_handle_ =
+      committed_request->navigation_handle()->TakeAppCacheHandle();
   frame_tree_node()->navigator()->DidNavigate(this, *validated_params,
                                               std::move(committed_request),
                                               is_same_document_navigation);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index c8e8068..5454bce 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -129,6 +129,7 @@
 }  // namespace network
 
 namespace content {
+class AppCacheNavigationHandle;
 class AuthenticatorImpl;
 class FrameTree;
 class FrameTreeNode;
@@ -1743,6 +1744,11 @@
   // NavigationRequest is for a cross-document navigation.
   std::unique_ptr<NavigationRequest> navigation_request_;
 
+  // Holds AppCacheNavigationHandle after navigation request has been committed,
+  // which keeps corresponding AppCacheHost alive while renderer asks for it.
+  // See AppCacheNavigationHandle comment for more details.
+  std::unique_ptr<AppCacheNavigationHandle> appcache_handle_;
+
   // Holds the cross-document NavigationRequests that are waiting to commit,
   // indexed by IDs. These are navigations that have passed ReadyToCommit stage
   // and are waiting for the renderer to send back a matching
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 998cab75..ad9bf0b 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -710,37 +710,6 @@
     GetNavigatingWebUI()->RenderFrameCreated(navigation_rfh);
   }
 
-  // If this function picked an incompatible process for the URL, capture a
-  // crash dump to diagnose why it is occurring.
-  // TODO(creis): Remove this check after we've gathered enough information to
-  // debug issues with browser-side security checks. https://crbug.com/931895.
-  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
-  const GURL& lock_url = navigation_rfh->GetSiteInstance()->lock_url();
-  if (lock_url != GURL(kUnreachableWebDataURL) &&
-      request.common_params().url.IsStandard() &&
-      !policy->CanAccessDataForOrigin(navigation_rfh->GetProcess()->GetID(),
-                                      request.common_params().url)) {
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("lock_url",
-                                            base::debug::CrashKeySize::Size64),
-        lock_url.spec());
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("commit_origin",
-                                            base::debug::CrashKeySize::Size64),
-        request.common_params().url.GetOrigin().spec());
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("is_main_frame",
-                                            base::debug::CrashKeySize::Size32),
-        frame_tree_node_->IsMainFrame() ? "true" : "false");
-    base::debug::SetCrashKeyString(
-        base::debug::AllocateCrashKeyString("use_current_rfh",
-                                            base::debug::CrashKeySize::Size32),
-        use_current_rfh ? "true" : "false");
-    NOTREACHED() << "Picked an incompatible process for URL: " << lock_url
-                 << " lock vs " << request.common_params().url.GetOrigin();
-    base::debug::DumpWithoutCrashing();
-  }
-
   return navigation_rfh;
 }
 
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
index b4a0b81..e74bb82 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -65,17 +65,8 @@
 
   aura::Window* window = GetWindow();
   aura::WindowTreeHost* host = window->GetHost();
-
   for (const auto& event : events) {
     event->ConvertLocationToTarget(window, host->window());
-    // Apply the screen scale factor to the event location after it has been
-    // transformed to the target.
-    gfx::PointF device_location =
-        gfx::ScalePoint(event->location_f(), device_scale_factor_);
-    gfx::PointF device_root_location =
-        gfx::ScalePoint(event->root_location_f(), device_scale_factor_);
-    event->set_location_f(device_location);
-    event->set_root_location_f(device_root_location);
     ui::EventDispatchDetails details =
         event_injector_.Inject(host, event.get());
     if (details.dispatcher_destroyed)
@@ -107,10 +98,6 @@
 
   aura::Window* window = GetWindow();
   wheel_event.ConvertLocationToTarget(window, window->GetRootWindow());
-  wheel_event.set_location_f(
-      gfx::ScalePoint(wheel_event.location_f(), device_scale_factor_));
-  wheel_event.set_root_location_f(
-      gfx::ScalePoint(wheel_event.root_location_f(), device_scale_factor_));
   ui::EventDispatchDetails details =
       event_injector_.Inject(window->GetHost(), &wheel_event);
   if (details.dispatcher_destroyed)
@@ -137,10 +124,6 @@
                                  ui::EventTimeForNow(), pinch_details);
 
     pinch_event.ConvertLocationToTarget(window, window->GetRootWindow());
-    pinch_event.set_location_f(
-        gfx::ScalePoint(pinch_event.location_f(), device_scale_factor_));
-    pinch_event.set_root_location_f(
-        gfx::ScalePoint(pinch_event.root_location_f(), device_scale_factor_));
     event_injector_.Inject(window->GetHost(), &pinch_event);
     return;
   }
@@ -157,10 +140,6 @@
                                web_gesture.data.fling_start.velocity_y, 0, 0, 2,
                                momentum_phase, ui::ScrollEventPhase::kNone);
   scroll_event.ConvertLocationToTarget(window, window->GetRootWindow());
-  scroll_event.set_location_f(
-      gfx::ScalePoint(scroll_event.location_f(), device_scale_factor_));
-  scroll_event.set_root_location_f(
-      gfx::ScalePoint(scroll_event.root_location_f(), device_scale_factor_));
   event_injector_.Inject(window->GetHost(), &scroll_event);
 }
 
@@ -186,10 +165,6 @@
 
   aura::Window* window = GetWindow();
   mouse_event.ConvertLocationToTarget(window, window->GetRootWindow());
-  mouse_event.set_location_f(
-      gfx::ScalePoint(mouse_event.location_f(), device_scale_factor_));
-  mouse_event.set_root_location_f(
-      gfx::ScalePoint(mouse_event.root_location_f(), device_scale_factor_));
   mouse_event.SetClickCount(web_mouse_event.click_count);
   ui::EventDispatchDetails details =
       event_injector_.Inject(window->GetHost(), &mouse_event);
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 85a3ca8..e208dedd 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -489,6 +489,11 @@
     rwhv_mac_ = new RenderWidgetHostViewMac(host_.get(), false);
     rwhv_cocoa_.reset([rwhv_mac_->cocoa_view() retain]);
 
+    window_.reset([[CocoaTestHelperWindow alloc] init]);
+    window_.get().pretendIsKeyWindow = YES;
+    [[window_ contentView] addSubview:rwhv_cocoa_];
+    [rwhv_cocoa_ setFrame:[window_ contentView].bounds];
+
     base::RunLoop().RunUntilIdle();
     process_host_->sink().ClearMessages();
   }
@@ -536,6 +541,7 @@
   std::unique_ptr<MockRenderWidgetHostImpl> host_;
   RenderWidgetHostViewMac* rwhv_mac_ = nullptr;
   base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa_;
+  base::scoped_nsobject<CocoaTestHelperWindow> window_;
 
  private:
   // This class isn't derived from PlatformTest.
@@ -875,11 +881,6 @@
 
   NSRange actual_range = NSMakeRange(0, 0);
 
-  base::scoped_nsobject<CocoaTestHelperWindow> window(
-      [[CocoaTestHelperWindow alloc] init]);
-  [[window contentView] addSubview:rwhv_cocoa_];
-  [rwhv_cocoa_ setFrame:NSMakeRect(0, 0, 400, 400)];
-
   NSRect rect = [rwhv_cocoa_ firstRectForCharacterRange:range.ToNSRange()
                                             actualRange:&actual_range];
   EXPECT_EQ(30, rect.size.width);
@@ -897,12 +898,8 @@
 // Verify that |SetActive()| calls |RenderWidgetHostImpl::Blur()| and
 // |RenderWidgetHostImp::Focus()|.
 TEST_F(RenderWidgetHostViewMacTest, BlurAndFocusOnSetActive) {
-  base::scoped_nsobject<CocoaTestHelperWindow> window(
-      [[CocoaTestHelperWindow alloc] init]);
-  [[window contentView] addSubview:rwhv_mac_->cocoa_view()];
-
   EXPECT_CALL(*host_, Focus());
-  [window makeFirstResponder:rwhv_mac_->cocoa_view()];
+  [window_ makeFirstResponder:rwhv_mac_->cocoa_view()];
   testing::Mock::VerifyAndClearExpectations(host_.get());
 
   EXPECT_CALL(*host_, Blur());
@@ -915,7 +912,7 @@
 
   // Unsetting first responder should blur.
   EXPECT_CALL(*host_, Blur());
-  [window makeFirstResponder:nil];
+  [window_ makeFirstResponder:nil];
   testing::Mock::VerifyAndClearExpectations(host_.get());
 
   // |SetActive()| shoud not focus if view is not first responder.
@@ -997,7 +994,7 @@
   base::RunLoop().RunUntilIdle();
   MockWidgetInputHandler::MessageVector events =
       host_->GetAndResetDispatchedMessages();
-  ASSERT_EQ("MouseLeave", GetMessageNames(events));
+  ASSERT_EQ("MouseMove", GetMessageNames(events));
   EXPECT_EQ(blink::WebPointerProperties::PointerType::kEraser,
             GetPointerType(events));
 }
@@ -1017,7 +1014,7 @@
   base::RunLoop().RunUntilIdle();
   MockWidgetInputHandler::MessageVector events =
       host_->GetAndResetDispatchedMessages();
-  ASSERT_EQ("MouseLeave", GetMessageNames(events));
+  ASSERT_EQ("MouseMove", GetMessageNames(events));
   EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
             GetPointerType(events));
 }
@@ -1032,7 +1029,7 @@
   base::RunLoop().RunUntilIdle();
   MockWidgetInputHandler::MessageVector events =
       host_->GetAndResetDispatchedMessages();
-  ASSERT_EQ("MouseLeave", GetMessageNames(events));
+  ASSERT_EQ("MouseMove", GetMessageNames(events));
   EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
             GetPointerType(events));
   events.clear();
@@ -1041,15 +1038,11 @@
   [rwhv_mac_->cocoa_view() mouseEntered:event];
   base::RunLoop().RunUntilIdle();
   events = host_->GetAndResetDispatchedMessages();
-  ASSERT_EQ("MouseMove MouseMove", GetMessageNames(events));
+  ASSERT_EQ("MouseMove", GetMessageNames(events));
   EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
             static_cast<const blink::WebMouseEvent*>(
                 events[0]->ToEvent()->Event()->web_event.get())
                 ->pointer_type);
-  EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
-            static_cast<const blink::WebMouseEvent*>(
-                events[1]->ToEvent()->Event()->web_event.get())
-                ->pointer_type);
 }
 
 TEST_F(RenderWidgetHostViewMacTest, PointerEventWithMouseType) {
@@ -1061,7 +1054,7 @@
   base::RunLoop().RunUntilIdle();
   MockWidgetInputHandler::MessageVector events =
       host_->GetAndResetDispatchedMessages();
-  ASSERT_EQ("MouseLeave", GetMessageNames(events));
+  ASSERT_EQ("MouseMove", GetMessageNames(events));
   EXPECT_EQ(blink::WebPointerProperties::PointerType::kMouse,
             GetPointerType(events));
 }
@@ -1741,13 +1734,6 @@
   void SetUp() override {
     RenderWidgetHostViewMacTest::SetUp();
 
-    browser_context_ = std::make_unique<TestBrowserContext>();
-    process_host_ = new MockRenderProcessHost(browser_context_.get());
-    process_host_->Init();
-    widget_ = MockRenderWidgetHostImpl::Create(
-        &delegate_, process_host_, process_host_->GetNextRoutingID());
-    view_ = new RenderWidgetHostViewMac(widget_, false);
-
     // Initializing a child frame's view.
     child_browser_context_ = std::make_unique<TestBrowserContext>();
     child_process_host_ =
@@ -1761,12 +1747,8 @@
   }
 
   void TearDown() override {
-    widget_->ShutdownAndDestroyWidget(true);
     child_widget_->ShutdownAndDestroyWidget(true);
-
     child_browser_context_.reset();
-    browser_context_.reset();
-
     RenderWidgetHostViewMacTest::TearDown();
   }
 
@@ -1782,9 +1764,9 @@
   TextInputManager* text_input_manager() {
     return delegate_.GetTextInputManager();
   }
-  RenderWidgetHostViewBase* tab_view() { return view_; }
-  RenderWidgetHostImpl* tab_widget() { return widget_; }
-  RenderWidgetHostViewCocoa* tab_cocoa_view() { return view_->cocoa_view(); }
+  RenderWidgetHostViewMac* tab_view() { return rwhv_mac_; }
+  RenderWidgetHostImpl* tab_widget() { return host_.get(); }
+  RenderWidgetHostViewCocoa* tab_cocoa_view() { return rwhv_cocoa_.get(); }
 
   API_AVAILABLE(macos(10.12.2))
   NSCandidateListTouchBarItem* candidate_list_item() {
@@ -1793,17 +1775,11 @@
   }
 
  protected:
-  MockRenderProcessHost* process_host_;
-  MockRenderWidgetHostImpl* widget_;
-  MockRenderWidgetHostDelegate delegate_;
-  RenderWidgetHostViewMac* view_;
-
   MockRenderProcessHost* child_process_host_;
   MockRenderWidgetHostImpl* child_widget_;
   TestRenderWidgetHostView* child_view_;
 
  private:
-  std::unique_ptr<TestBrowserContext> browser_context_;
   std::unique_ptr<TestBrowserContext> child_browser_context_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodMacTest);
@@ -1829,7 +1805,7 @@
   EXPECT_EQ(tab_widget(), text_input_manager()->GetActiveWidget());
   [tab_cocoa_view() unmarkText];
   base::RunLoop().RunUntilIdle();
-  events = widget_->GetAndResetDispatchedMessages();
+  events = host_->GetAndResetDispatchedMessages();
   EXPECT_EQ("FinishComposingText", GetMessageNames(events));
 }
 
@@ -1861,7 +1837,7 @@
                     selectedRange:selectedRange
                  replacementRange:replacementRange];
   base::RunLoop().RunUntilIdle();
-  events = widget_->GetAndResetDispatchedMessages();
+  events = host_->GetAndResetDispatchedMessages();
   EXPECT_EQ("SetComposition", GetMessageNames(events));
 }
 
@@ -1888,7 +1864,7 @@
   EXPECT_EQ(tab_widget(), text_input_manager()->GetActiveWidget());
   [tab_cocoa_view() insertText:text replacementRange:replacementRange];
   base::RunLoop().RunUntilIdle();
-  events = widget_->GetAndResetDispatchedMessages();
+  events = host_->GetAndResetDispatchedMessages();
   EXPECT_EQ("CommitText", GetMessageNames(events));
 }
 
@@ -1926,39 +1902,35 @@
                  replacementRange:replacementRange];
   [tab_cocoa_view() finishComposingText];
   base::RunLoop().RunUntilIdle();
-  events = widget_->GetAndResetDispatchedMessages();
+  events = host_->GetAndResetDispatchedMessages();
   EXPECT_EQ("SetComposition FinishComposingText", GetMessageNames(events));
 }
 
 TEST_F(InputMethodMacTest, SecurePasswordInput) {
   ASSERT_FALSE(ui::ScopedPasswordInputEnabler::IsPasswordInputEnabled());
-  ASSERT_EQ(text_input_manager(), view_->GetTextInputManager());
-
-  base::scoped_nsobject<CocoaTestHelperWindow> window(
-      [[CocoaTestHelperWindow alloc] init]);
-  [[window contentView] addSubview:view_->cocoa_view()];
+  ASSERT_EQ(text_input_manager(), tab_view()->GetTextInputManager());
 
   // RenderWidgetHostViewMacTest.BlurAndFocusOnSetActive checks the
   // Focus()/Blur() rules, just silence the warnings here.
-  EXPECT_CALL(*widget_, Focus()).Times(::testing::AnyNumber());
-  EXPECT_CALL(*widget_, Blur()).Times(::testing::AnyNumber());
+  EXPECT_CALL(*host_, Focus()).Times(::testing::AnyNumber());
+  EXPECT_CALL(*host_, Blur()).Times(::testing::AnyNumber());
 
-  [window makeFirstResponder:view_->cocoa_view()];
+  [window_ makeFirstResponder:tab_view()->cocoa_view()];
 
   // Shouldn't enable secure input if it's not a password textfield.
-  view_->SetActive(true);
+  tab_view()->SetActive(true);
   EXPECT_FALSE(ui::ScopedPasswordInputEnabler::IsPasswordInputEnabled());
 
   SetTextInputType(child_view_, ui::TEXT_INPUT_TYPE_PASSWORD);
   ASSERT_EQ(child_widget_, text_input_manager()->GetActiveWidget());
-  ASSERT_EQ(text_input_manager(), view_->GetTextInputManager());
-  ASSERT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, view_->GetTextInputType());
+  ASSERT_EQ(text_input_manager(), tab_view()->GetTextInputManager());
+  ASSERT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, tab_view()->GetTextInputType());
 
   // Single matched calls immediately update IsPasswordInputEnabled().
-  view_->SetActive(true);
+  tab_view()->SetActive(true);
   EXPECT_TRUE(ui::ScopedPasswordInputEnabler::IsPasswordInputEnabled());
 
-  view_->SetActive(false);
+  tab_view()->SetActive(false);
   EXPECT_FALSE(ui::ScopedPasswordInputEnabler::IsPasswordInputEnabled());
 }
 
@@ -2015,21 +1987,18 @@
   // method RWHVMac::HasFocus() returns true. Then we can make sure that as long
   // as there is some TextInputState of non-NONE, the corresponding widget will
   // be asked to start monitoring composition info.
-  base::scoped_nsobject<CocoaTestHelperWindow> window(
-      [[CocoaTestHelperWindow alloc] init]);
-  [[window contentView] addSubview:tab_cocoa_view()];
-  [window makeFirstResponder:tab_cocoa_view()];
-  EXPECT_TRUE(view_->HasFocus());
+  [window_ makeFirstResponder:tab_cocoa_view()];
+  EXPECT_TRUE(tab_view()->HasFocus());
 
   TextInputState state;
   state.type = ui::TEXT_INPUT_TYPE_TEXT;
 
   // Make the tab's widget active.
-  view_->TextInputStateChanged(state);
+  tab_view()->TextInputStateChanged(state);
 
   base::RunLoop().RunUntilIdle();
   MockWidgetInputHandler::MessageVector events =
-      widget_->GetAndResetDispatchedMessages();
+      host_->GetAndResetDispatchedMessages();
   // The tab's widget must have received an IPC regarding composition updates.
   EXPECT_EQ("SetFocus RequestCompositionUpdates", GetMessageNames(events));
 
@@ -2044,7 +2013,7 @@
 
   // The tab should receive another IPC for composition updates.
   base::RunLoop().RunUntilIdle();
-  events = widget_->GetAndResetDispatchedMessages();
+  events = host_->GetAndResetDispatchedMessages();
   // The tab's widget must have received an IPC regarding composition updates.
   EXPECT_EQ("RequestCompositionUpdates", GetMessageNames(events));
   // This time, the tab should have been asked to stop monitoring (and no
@@ -2064,7 +2033,7 @@
   EXPECT_TRUE(message->monitor_request());
 
   // Make the tab view active again.
-  view_->TextInputStateChanged(state);
+  tab_view()->TextInputStateChanged(state);
 
   base::RunLoop().RunUntilIdle();
   events = child_widget_->GetAndResetDispatchedMessages();
@@ -2144,7 +2113,7 @@
     [tab_cocoa_view() candidateListTouchBarItem:candidate_list_item()
                    endSelectingCandidateAtIndex:0];
     base::RunLoop().RunUntilIdle();
-    events = widget_->GetAndResetDispatchedMessages();
+    events = host_->GetAndResetDispatchedMessages();
     ASSERT_EQ("CommitText", GetMessageNames(events));
   }
 }
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
new file mode 100644
index 0000000..71080c8b
--- /dev/null
+++ b/content/browser/webauth/authenticator_common.cc
@@ -0,0 +1,1370 @@
+// Copyright 2019 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 "content/browser/webauth/authenticator_common.h"
+
+#include <array>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/base64url.h"
+#include "base/bind.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "base/strings/string_piece.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/webauth/authenticator_type_converters.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/origin_util.h"
+#include "content/public/common/service_manager_connection.h"
+#include "crypto/sha2.h"
+#include "device/base/features.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/fido/attestation_statement.h"
+#include "device/fido/authenticator_selection_criteria.h"
+#include "device/fido/ctap_get_assertion_request.h"
+#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/features.h"
+#include "device/fido/fido_authenticator.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_transport_protocol.h"
+#include "device/fido/get_assertion_request_handler.h"
+#include "device/fido/make_credential_request_handler.h"
+#include "device/fido/public_key_credential_descriptor.h"
+#include "device/fido/public_key_credential_params.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cert/asn1_util.h"
+#include "net/der/input.h"
+#include "net/der/parse_values.h"
+#include "net/der/parser.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "url/url_constants.h"
+#include "url/url_util.h"
+
+#if defined(OS_MACOSX)
+#include "device/fido/mac/authenticator.h"
+#endif
+
+#if defined(OS_WIN)
+#include "device/fido/win/authenticator.h"
+#endif
+
+namespace content {
+
+namespace client_data {
+const char kCreateType[] = "webauthn.create";
+const char kGetType[] = "webauthn.get";
+const char kU2fSignType[] = "navigator.id.getAssertion";
+const char kU2fRegisterType[] = "navigator.id.finishEnrollment";
+}  // namespace client_data
+
+namespace {
+
+constexpr char kCryptotokenOrigin[] =
+    "chrome-extension://kmendfapggjehodndflmmgagdbamhnfd";
+
+// AttestationPromptResult enumerates events related to attestation prompts.
+// These values are recorded in an UMA histogram and so should not be
+// reassigned.
+enum class AttestationPromptResult {
+  // kQueried indicates that the embedder was queried in order to determine
+  // whether attestation information should be returned to the origin.
+  kQueried = 0,
+  // kTimeout indicates that a timeout occured while awaiting the result of an
+  // attestation query.
+  kTimeout = 1,
+  // kAllowed indicates that the query to the embedder was resolved positively.
+  // (E.g. the user clicked to allow, or the embedded allowed immediately by
+  // policy.)
+  kAllowed = 2,
+  // kBlocked indicates that the query to the embedder was resolved negatively.
+  // (E.g. the user clicked to block, or closed the dialog.)
+  kBlocked = 3,
+  // kAbandoned indications that the user closed the tab or navigated away while
+  // the attestation prompt was showing.
+  kAbandoned = 4,
+  kMaxValue = kAbandoned,
+};
+
+// The following enums correspond to UMA histograms and should not be
+// reassigned.
+enum class RelyingPartySecurityCheckFailure {
+  kOpaqueOrNonSecureOrigin = 0,
+  kRelyingPartyIdInvalid = 1,
+  kAppIdExtensionInvalid = 2,
+  kAppIdExtensionDomainMismatch = 3,
+  kMaxValue = kAppIdExtensionDomainMismatch,
+};
+
+void ReportSecurityCheckFailure(RelyingPartySecurityCheckFailure error) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "WebAuthentication.RelyingPartySecurityCheckFailure", error);
+}
+
+bool OriginIsCryptoTokenExtension(const url::Origin& origin) {
+  auto cryptotoken_origin = url::Origin::Create(GURL(kCryptotokenOrigin));
+  return cryptotoken_origin == origin;
+}
+
+// Ensure that the origin's effective domain is a valid domain.
+// Only the domain format of host is valid.
+// Reference https://url.spec.whatwg.org/#valid-domain-string and
+// https://html.spec.whatwg.org/multipage/origin.html#concept-origin-effective-domain.
+bool HasValidEffectiveDomain(url::Origin caller_origin) {
+  // For calls originating in the CryptoToken U2F extension, allow CryptoToken
+  // to validate domain.
+  if (OriginIsCryptoTokenExtension(caller_origin) &&
+      base::FeatureList::IsEnabled(device::kWebAuthProxyCryptotoken))
+    return true;
+
+  return !caller_origin.opaque() &&
+         !url::HostIsIPAddress(caller_origin.host()) &&
+         content::IsOriginSecure(caller_origin.GetURL()) &&
+         // Additionally, the scheme is required to be HTTP(S). Other schemes
+         // may be supported in the future but the webauthn relying party is
+         // just the domain of the origin so we would have to define how the
+         // authority part of other schemes maps to a "domain" without
+         // collisions. Given the |IsOriginSecure| check, just above, HTTP is
+         // effectively restricted to just "localhost".
+         (caller_origin.scheme() == url::kHttpScheme ||
+          caller_origin.scheme() == url::kHttpsScheme);
+}
+
+// Ensure the relying party ID is a registrable domain suffix of or equal
+// to the origin's effective domain. Reference:
+// https://html.spec.whatwg.org/multipage/origin.html#is-a-registrable-domain-suffix-of-or-is-equal-to.
+bool IsRelyingPartyIdValid(const std::string& relying_party_id,
+                           url::Origin caller_origin) {
+  if (OriginIsCryptoTokenExtension(caller_origin) &&
+      base::FeatureList::IsEnabled(device::kWebAuthProxyCryptotoken))
+    return true;
+
+  if (relying_party_id.empty())
+    return false;
+
+  if (caller_origin.host() == relying_party_id)
+    return true;
+
+  if (!caller_origin.DomainIs(relying_party_id))
+    return false;
+  if (!net::registry_controlled_domains::HostHasRegistryControlledDomain(
+          caller_origin.host(),
+          net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
+    return false;
+  if (!net::registry_controlled_domains::HostHasRegistryControlledDomain(
+          relying_party_id,
+          net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
+    // TODO(crbug.com/803414): Accept corner-case situations like the following
+    // origin: "https://login.awesomecompany",
+    // relying_party_id: "awesomecompany".
+    return false;
+  return true;
+}
+
+// Validates whether the given origin is authorized to use the provided App
+// ID value, mostly according to the rules in
+// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-appid-and-facets-v1.2-ps-20170411.html#determining-if-a-caller-s-facetid-is-authorized-for-an-appid.
+//
+// Returns the App ID to use for the request, or base::nullopt if the origin
+// is not authorized to use the provided value.
+base::Optional<std::string> ProcessAppIdExtension(std::string appid,
+                                                  const url::Origin& origin) {
+  // The CryptoToken U2F extension checks the appid before calling the WebAuthn
+  // API so there is no need to validate it here.
+  if (OriginIsCryptoTokenExtension(origin) &&
+      base::FeatureList::IsEnabled(device::kWebAuthProxyCryptotoken)) {
+    if (!GURL(appid).is_valid()) {
+      DCHECK(false) << "cryptotoken request did not set a valid App ID";
+      return base::nullopt;
+    }
+    return appid;
+  }
+
+  // Step 1: "If the AppID is not an HTTPS URL, and matches the FacetID of the
+  // caller, no additional processing is necessary and the operation may
+  // proceed."
+
+  // Webauthn is only supported on secure origins and |HasValidEffectiveDomain|
+  // has already checked this property of |origin| before this call. Thus this
+  // step is moot.
+  DCHECK(content::IsOriginSecure(origin.GetURL()));
+
+  // Step 2: "If the AppID is null or empty, the client must set the AppID to be
+  // the FacetID of the caller, and the operation may proceed without additional
+  // processing."
+  if (appid.empty()) {
+    // While the U2F spec says to default the App ID to the Facet ID, which is
+    // the origin plus a trailing forward slash [1], cryptotoken and Firefox
+    // just use the site's Origin without trailing slash. We follow their
+    // implementations rather than the spec.
+    //
+    // [1]https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html#determining-the-facetid-of-a-calling-application
+    appid = origin.Serialize();
+  }
+
+  // Step 3: "If the caller's FacetID is an https:// Origin sharing the same
+  // host as the AppID, (e.g. if an application hosted at
+  // https://fido.example.com/myApp set an AppID of
+  // https://fido.example.com/myAppId), no additional processing is necessary
+  // and the operation may proceed."
+  GURL appid_url = GURL(appid);
+  if (!appid_url.is_valid() || appid_url.scheme() != url::kHttpsScheme ||
+      appid_url.scheme_piece() != origin.scheme()) {
+    ReportSecurityCheckFailure(
+        RelyingPartySecurityCheckFailure::kAppIdExtensionInvalid);
+    return base::nullopt;
+  }
+
+  // This check is repeated inside |SameDomainOrHost|, just after this. However
+  // it's cheap and mirrors the structure of the spec.
+  if (appid_url.host_piece() == origin.host()) {
+    return appid;
+  }
+
+  // At this point we diverge from the specification in order to avoid the
+  // complexity of making a network request which isn't believed to be
+  // neccessary in practice. See also
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1244959#c8
+  if (net::registry_controlled_domains::SameDomainOrHost(
+          appid_url, origin,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+    return appid;
+  }
+
+  // As a compatibility hack, sites within google.com are allowed to assert two
+  // special-case AppIDs. Firefox also does this:
+  // https://groups.google.com/forum/#!msg/mozilla.dev.platform/Uiu3fwnA2xw/201ynAiPAQAJ
+  const GURL kGstatic1 =
+      GURL("https://www.gstatic.com/securitykey/origins.json");
+  const GURL kGstatic2 =
+      GURL("https://www.gstatic.com/securitykey/a/google.com/origins.json");
+  DCHECK(kGstatic1.is_valid() && kGstatic2.is_valid());
+
+  if (origin.DomainIs("google.com") && !appid_url.has_ref() &&
+      (appid_url.EqualsIgnoringRef(kGstatic1) ||
+       appid_url.EqualsIgnoringRef(kGstatic2))) {
+    return appid;
+  }
+
+  ReportSecurityCheckFailure(
+      RelyingPartySecurityCheckFailure::kAppIdExtensionDomainMismatch);
+
+  return base::nullopt;
+}
+
+device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
+    const std::string& client_data_json,
+    const blink::mojom::PublicKeyCredentialCreationOptionsPtr& options,
+    bool is_incognito) {
+  auto credential_params = mojo::ConvertTo<
+      std::vector<device::PublicKeyCredentialParams::CredentialInfo>>(
+      options->public_key_parameters);
+
+  device::CtapMakeCredentialRequest make_credential_param(
+      client_data_json,
+      mojo::ConvertTo<device::PublicKeyCredentialRpEntity>(
+          options->relying_party),
+      mojo::ConvertTo<device::PublicKeyCredentialUserEntity>(options->user),
+      device::PublicKeyCredentialParams(std::move(credential_params)));
+
+  auto exclude_list =
+      mojo::ConvertTo<std::vector<device::PublicKeyCredentialDescriptor>>(
+          options->exclude_credentials);
+
+  make_credential_param.SetExcludeList(std::move(exclude_list));
+  make_credential_param.SetHmacSecret(options->hmac_create_secret);
+  make_credential_param.set_is_incognito_mode(is_incognito);
+  return make_credential_param;
+}
+
+device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
+    const std::string& client_data_json,
+    const blink::mojom::PublicKeyCredentialRequestOptionsPtr& options,
+    base::Optional<std::string> app_id,
+    bool is_incognito) {
+  device::CtapGetAssertionRequest request_parameter(options->relying_party_id,
+                                                    client_data_json);
+
+  auto allowed_list =
+      mojo::ConvertTo<std::vector<device::PublicKeyCredentialDescriptor>>(
+          options->allow_credentials);
+
+  request_parameter.SetAllowList(std::move(allowed_list));
+  request_parameter.SetUserVerification(
+      mojo::ConvertTo<device::UserVerificationRequirement>(
+          options->user_verification));
+
+  if (app_id) {
+    request_parameter.SetAppId(std::move(*app_id));
+  }
+
+  if (!options->cable_authentication_data.empty()) {
+    request_parameter.SetCableExtension(
+        mojo::ConvertTo<std::vector<device::CableDiscoveryData>>(
+            options->cable_authentication_data));
+  }
+  request_parameter.set_is_incognito_mode(is_incognito);
+  return request_parameter;
+}
+
+// The application parameter is the SHA-256 hash of the UTF-8 encoding of
+// the application identity (i.e. relying_party_id) of the application
+// requesting the registration.
+std::array<uint8_t, crypto::kSHA256Length> CreateApplicationParameter(
+    const std::string& relying_party_id) {
+  std::array<uint8_t, crypto::kSHA256Length> application_parameter;
+  crypto::SHA256HashString(relying_party_id, application_parameter.data(),
+                           application_parameter.size());
+  return application_parameter;
+}
+
+// Parses the FIDO transport types extension from the DER-encoded, X.509
+// certificate in |der_cert| and appends any unique transport types found to
+// |out_transports|.
+void AppendUniqueTransportsFromCertificate(
+    base::span<const uint8_t> der_cert,
+    std::vector<device::FidoTransportProtocol>* out_transports) {
+  // See
+  // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-authenticator-transports-extension-v1.2-ps-20170411.html#fido-u2f-certificate-transports-extension
+  static constexpr uint8_t kTransportTypesOID[] = {
+      0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xe5, 0x1c, 0x02, 0x01, 0x01};
+  bool present, critical;
+  base::StringPiece contents;
+  if (!net::asn1::ExtractExtensionFromDERCert(
+          base::StringPiece(reinterpret_cast<const char*>(der_cert.data()),
+                            der_cert.size()),
+          base::StringPiece(reinterpret_cast<const char*>(kTransportTypesOID),
+                            sizeof(kTransportTypesOID)),
+          &present, &critical, &contents) ||
+      !present) {
+    return;
+  }
+
+  const net::der::Input contents_der(contents);
+  net::der::Parser contents_parser(contents_der);
+  net::der::BitString transport_bits;
+  if (!contents_parser.ReadBitString(&transport_bits)) {
+    return;
+  }
+
+  // The certificate extension contains a BIT STRING where different bits
+  // indicate support for different transports. The following array maps
+  // between these bit indexes and the FidoTransportProtocol enum.
+  static constexpr struct {
+    uint8_t bit_index;
+    device::FidoTransportProtocol transport;
+  } kTransportMapping[] = {
+      // Bit 0 is "Bluetooth Classic", not BLE. Since webauthn doesn't define a
+      // transport type for this we ignore it.
+      {1, device::FidoTransportProtocol::kBluetoothLowEnergy},
+      {2, device::FidoTransportProtocol::kUsbHumanInterfaceDevice},
+      {3, device::FidoTransportProtocol::kNearFieldCommunication},
+      {4, device::FidoTransportProtocol::kInternal},
+  };
+
+  for (const auto& mapping : kTransportMapping) {
+    if (transport_bits.AssertsBit(mapping.bit_index) &&
+        !base::ContainsValue(*out_transports, mapping.transport)) {
+      out_transports->push_back(mapping.transport);
+    }
+  }
+}
+
+enum class AttestationErasureOption {
+  kIncludeAttestation,
+  kEraseAttestationButIncludeAaguid,
+  kEraseAttestationAndAaguid,
+};
+
+blink::mojom::MakeCredentialAuthenticatorResponsePtr
+CreateMakeCredentialResponse(
+    const std::string& client_data_json,
+    device::AuthenticatorMakeCredentialResponse response_data,
+    AttestationErasureOption attestation_erasure) {
+  auto response = blink::mojom::MakeCredentialAuthenticatorResponse::New();
+  auto common_info = blink::mojom::CommonCredentialInfo::New();
+  common_info->client_data_json.assign(client_data_json.begin(),
+                                       client_data_json.end());
+  common_info->raw_id = response_data.raw_credential_id();
+  common_info->id = response_data.GetId();
+  response->info = std::move(common_info);
+
+  // The transport list must not contain duplicates but the order doesn't matter
+  // because Blink will sort the resulting strings before returning them.
+  std::vector<device::FidoTransportProtocol> transports;
+  if (response_data.transport_used()) {
+    transports.push_back(*response_data.transport_used());
+  }
+  // If the attestation certificate specifies that the token supports any other
+  // transports, include them in the list.
+  base::Optional<base::span<const uint8_t>> leaf_cert =
+      response_data.attestation_object()
+          .attestation_statement()
+          .GetLeafCertificate();
+  if (leaf_cert) {
+    AppendUniqueTransportsFromCertificate(*leaf_cert, &transports);
+  }
+
+  for (auto transport : transports) {
+    response->transports.push_back(
+        mojo::ConvertTo<blink::mojom::AuthenticatorTransport>(transport));
+  }
+
+  const base::Optional<cbor::Value>& maybe_extensions =
+      response_data.attestation_object().authenticator_data().extensions();
+  if (maybe_extensions) {
+    DCHECK(maybe_extensions->is_map());
+    const cbor::Value::MapValue& extensions = maybe_extensions->GetMap();
+    const auto hmac_secret_it =
+        extensions.find(cbor::Value(device::kExtensionHmacSecret));
+    if (hmac_secret_it != extensions.end() &&
+        hmac_secret_it->second.is_bool()) {
+      response->echo_hmac_create_secret = true;
+      response->hmac_create_secret = hmac_secret_it->second.GetBool();
+    }
+  }
+
+  switch (attestation_erasure) {
+    case AttestationErasureOption::kIncludeAttestation:
+      break;
+    case AttestationErasureOption::kEraseAttestationButIncludeAaguid:
+      response_data.EraseAttestationStatement(
+          device::AttestationObject::AAGUID::kInclude);
+      break;
+    case AttestationErasureOption::kEraseAttestationAndAaguid:
+      response_data.EraseAttestationStatement(
+          device::AttestationObject::AAGUID::kErase);
+      break;
+  }
+  response->attestation_object =
+      response_data.GetCBOREncodedAttestationObject();
+
+  return response;
+}
+
+blink::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
+    const std::string& client_data_json,
+    device::AuthenticatorGetAssertionResponse response_data,
+    base::Optional<bool> echo_appid_extension) {
+  auto response = blink::mojom::GetAssertionAuthenticatorResponse::New();
+  auto common_info = blink::mojom::CommonCredentialInfo::New();
+  common_info->client_data_json.assign(client_data_json.begin(),
+                                       client_data_json.end());
+  common_info->raw_id = response_data.raw_credential_id();
+  common_info->id = response_data.GetId();
+  response->info = std::move(common_info);
+  response->authenticator_data =
+      response_data.auth_data().SerializeToByteArray();
+  response->signature = response_data.signature();
+  if (echo_appid_extension) {
+    response->echo_appid_extension = true;
+    response->appid_extension = *echo_appid_extension;
+  }
+  response_data.user_entity()
+      ? response->user_handle.emplace(response_data.user_entity()->user_id())
+      : response->user_handle.emplace();
+  return response;
+}
+
+std::string Base64UrlEncode(const base::span<const uint8_t> input) {
+  std::string ret;
+  base::Base64UrlEncode(
+      base::StringPiece(reinterpret_cast<const char*>(input.data()),
+                        input.size()),
+      base::Base64UrlEncodePolicy::OMIT_PADDING, &ret);
+  return ret;
+}
+
+base::flat_set<device::FidoTransportProtocol> GetTransportsEnabledByFlags() {
+  base::flat_set<device::FidoTransportProtocol> transports;
+  transports.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
+  transports.insert(device::FidoTransportProtocol::kInternal);
+
+  // TODO(crbug.com/885165): We should not directly access the BLE stack here.
+  // It is used by //device/fido, so its availability should be checked there.
+  if (!device::BluetoothAdapterFactory::Get().IsLowEnergySupported())
+    return transports;
+
+  if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
+    transports.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
+  }
+
+  // caBLE is independent of the BLE transport.
+  if (base::FeatureList::IsEnabled(features::kWebAuthCable)) {
+    transports.insert(
+        device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
+  }
+
+  return transports;
+}
+
+}  // namespace
+
+AuthenticatorCommon::AuthenticatorCommon(RenderFrameHost* render_frame_host)
+    : AuthenticatorCommon(render_frame_host,
+                        nullptr /* connector */,
+                        std::make_unique<base::OneShotTimer>()) {}
+
+AuthenticatorCommon::AuthenticatorCommon(RenderFrameHost* render_frame_host,
+                                     service_manager::Connector* connector,
+                                     std::unique_ptr<base::OneShotTimer> timer)
+    : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
+      render_frame_host_(render_frame_host),
+      connector_(connector),
+      transports_(GetTransportsEnabledByFlags()),
+      timer_(std::move(timer)),
+      binding_(this),
+      weak_factory_(this) {
+  DCHECK(render_frame_host_);
+  DCHECK(timer_);
+}
+
+AuthenticatorCommon::~AuthenticatorCommon() {
+  // This call exists to assert that |render_frame_host_| outlives this object.
+  // If this is violated, ASAN should notice.
+  render_frame_host_->GetRoutingID();
+}
+
+void AuthenticatorCommon::Bind(blink::mojom::AuthenticatorRequest request) {
+  // If |render_frame_host_| is being unloaded then binding requests are
+  // rejected.
+  if (!render_frame_host_->IsCurrent()) {
+    return;
+  }
+
+  DCHECK(!binding_.is_bound());
+  binding_.Bind(std::move(request));
+}
+
+void AuthenticatorCommon::UpdateRequestDelegate() {
+  DCHECK(!request_delegate_);
+  request_delegate_ =
+      GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
+          render_frame_host_);
+}
+
+bool AuthenticatorCommon::IsFocused() const {
+  return render_frame_host_->IsCurrent() && request_delegate_->IsFocused();
+}
+
+// static
+std::string AuthenticatorCommon::SerializeCollectedClientDataToJson(
+    const std::string& type,
+    const std::string& origin,
+    base::span<const uint8_t> challenge,
+    bool use_legacy_u2f_type_key /* = false */) {
+  static constexpr char kChallengeKey[] = "challenge";
+  static constexpr char kOriginKey[] = "origin";
+
+  base::DictionaryValue client_data;
+  client_data.SetKey(use_legacy_u2f_type_key ? "typ" : "type",
+                     base::Value(type));
+  client_data.SetKey(kChallengeKey, base::Value(Base64UrlEncode(challenge)));
+  client_data.SetKey(kOriginKey, base::Value(origin));
+
+  if (base::RandDouble() < 0.2) {
+    // An extra key is sometimes added to ensure that RPs do not make
+    // unreasonably specific assumptions about the clientData JSON. This is
+    // done in the fashion of
+    // https://tools.ietf.org/html/draft-davidben-tls-grease-01
+    client_data.SetKey("new_keys_may_be_added_here",
+                       base::Value("do not compare clientDataJSON against a "
+                                   "template. See https://goo.gl/yabPex"));
+  }
+
+  std::string json;
+  base::JSONWriter::Write(client_data, &json);
+  return json;
+}
+
+// mojom::Authenticator
+void AuthenticatorCommon::MakeCredential(
+    blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
+    MakeCredentialCallback callback) {
+  if (request_) {
+    if (OriginIsCryptoTokenExtension(
+            render_frame_host_->GetLastCommittedOrigin())) {
+      // Requests originating from cryptotoken will generally outlive any
+      // navigation events on the tab of the request's sender. Evict pending
+      // requests if cryptotoken sends a new one such that requests from before
+      // a navigation event do not prevent new requests. See
+      // https://crbug.com/935480.
+      Cancel();
+    } else {
+      std::move(callback).Run(
+          blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+      return;
+    }
+  }
+  DCHECK(!request_);
+
+  UpdateRequestDelegate();
+  if (!request_delegate_) {
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
+                             nullptr, Focus::kDontCheck);
+    return;
+  }
+
+  if (!IsFocused()) {
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::NOT_FOCUSED,
+                             nullptr, Focus::kDontCheck);
+    return;
+  }
+
+  caller_origin_ = render_frame_host_->GetLastCommittedOrigin();
+  relying_party_id_ = options->relying_party->id;
+
+  if (!HasValidEffectiveDomain(caller_origin_)) {
+    ReportSecurityCheckFailure(
+        RelyingPartySecurityCheckFailure::kOpaqueOrNonSecureOrigin);
+    bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
+                                    bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN);
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+                             nullptr, Focus::kDontCheck);
+    return;
+  }
+
+  if (!IsRelyingPartyIdValid(relying_party_id_, caller_origin_)) {
+    ReportSecurityCheckFailure(
+        RelyingPartySecurityCheckFailure::kRelyingPartyIdInvalid);
+    bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
+                                    bad_message::AUTH_INVALID_RELYING_PARTY);
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+                             nullptr, Focus::kDontCheck);
+    return;
+  }
+
+  if (options->authenticator_selection &&
+      options->authenticator_selection->require_resident_key) {
+    // Disallow the creation of resident credentials.
+    InvokeCallbackAndCleanup(
+        std::move(callback),
+        blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED,
+        nullptr, Focus::kDontCheck);
+    return;
+  }
+
+  DCHECK(make_credential_response_callback_.is_null());
+  make_credential_response_callback_ = std::move(callback);
+
+  timer_->Start(
+      FROM_HERE, options->adjusted_timeout,
+      base::BindOnce(&AuthenticatorCommon::OnTimeout, base::Unretained(this)));
+  if (!connector_)
+    connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
+
+  // Save client data to return with the authenticator response.
+  // TODO(kpaulhamus): Fetch and add the Channel ID/Token Binding ID public key
+  // used to communicate with the origin.
+  if (OriginIsCryptoTokenExtension(caller_origin_)) {
+    // Cryptotoken requests should be proxied without UI.
+    request_delegate_->DisableUI();
+    // As Cryptotoken validates the origin, accept the relying party id as the
+    // origin from requests originating from Cryptotoken. The origin is provided
+    // in Cryptotoken requests as the relying party name, which should be used
+    // as part of client data.
+    client_data_json_ = SerializeCollectedClientDataToJson(
+        client_data::kU2fRegisterType, options->relying_party->name,
+        std::move(options->challenge), true /* use_legacy_u2f_type_key */);
+  } else {
+    client_data_json_ = SerializeCollectedClientDataToJson(
+        client_data::kCreateType, caller_origin_.Serialize(),
+        std::move(options->challenge));
+  }
+
+  UMA_HISTOGRAM_COUNTS_100(
+      "WebAuthentication.MakeCredentialExcludeCredentialsCount",
+      options->exclude_credentials.size());
+
+  // U2F requests proxied from the cryptotoken extension are limited to USB
+  // devices.
+  const auto transports =
+      OriginIsCryptoTokenExtension(caller_origin_)
+          ? base::flat_set<device::FidoTransportProtocol>(
+                {device::FidoTransportProtocol::kUsbHumanInterfaceDevice})
+          : transports_;
+
+  auto authenticator_selection_criteria =
+      options->authenticator_selection
+          ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
+                options->authenticator_selection)
+          : device::AuthenticatorSelectionCriteria();
+
+  auto ctap_request = CreateCtapMakeCredentialRequest(
+      client_data_json_, options, browser_context()->IsOffTheRecord());
+  // On dual protocol CTAP2/U2F devices, force credential creation over U2F.
+  ctap_request.set_is_u2f_only(OriginIsCryptoTokenExtension(caller_origin_));
+
+  // Compute the effective attestation conveyance preference and set
+  // |attestation_requested_| for showing the attestation consent prompt later.
+  auto attestation = mojo::ConvertTo<::device::AttestationConveyancePreference>(
+      options->attestation);
+  if (attestation == ::device::AttestationConveyancePreference::ENTERPRISE &&
+      !request_delegate_->ShouldPermitIndividualAttestation(
+          relying_party_id_)) {
+    attestation = ::device::AttestationConveyancePreference::DIRECT;
+  }
+  ctap_request.set_attestation_preference(attestation);
+  attestation_requested_ =
+      attestation != ::device::AttestationConveyancePreference::NONE;
+
+  request_ = std::make_unique<device::MakeCredentialRequestHandler>(
+      connector_, transports, std::move(ctap_request),
+      std::move(authenticator_selection_criteria),
+      base::BindOnce(&AuthenticatorCommon::OnRegisterResponse,
+                     weak_factory_.GetWeakPtr()));
+
+  request_delegate_->RegisterActionCallbacks(
+      base::BindOnce(&AuthenticatorCommon::Cancel,
+                     weak_factory_.GetWeakPtr()) /* cancel_callback */,
+      base::BindRepeating(
+          &device::FidoRequestHandlerBase::StartAuthenticatorRequest,
+          request_->GetWeakPtr()) /* request_callback */,
+      base::BindRepeating(
+          &device::FidoRequestHandlerBase::PowerOnBluetoothAdapter,
+          request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */,
+      base::BindRepeating(
+          &device::FidoRequestHandlerBase::InitiatePairingWithDevice,
+          request_->GetWeakPtr()) /* ble_pairing_callback */);
+  request_->set_observer(request_delegate_.get());
+
+  request_->SetPlatformAuthenticatorOrMarkUnavailable(
+      CreatePlatformAuthenticatorIfAvailable());
+}
+
+// mojom:Authenticator
+void AuthenticatorCommon::GetAssertion(
+    blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
+    GetAssertionCallback callback) {
+  if (request_) {
+    if (OriginIsCryptoTokenExtension(
+            render_frame_host_->GetLastCommittedOrigin())) {
+      // Requests originating from cryptotoken will generally outlive any
+      // navigation events on the tab of the request's sender. Evict pending
+      // requests if cryptotoken sends a new one such that requests from before
+      // a navigation event do not prevent new requests. See
+      // https://crbug.com/935480.
+      Cancel();
+    } else {
+      std::move(callback).Run(
+          blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+      return;
+    }
+  }
+  DCHECK(!request_);
+
+  UpdateRequestDelegate();
+  if (!request_delegate_) {
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
+                             nullptr);
+    return;
+  }
+
+  caller_origin_ = render_frame_host_->GetLastCommittedOrigin();
+
+  // Save client data to return with the authenticator response.
+  // TODO(kpaulhamus): Fetch and add the Channel ID/Token Binding ID public key
+  // used to communicate with the origin.
+  if (OriginIsCryptoTokenExtension(caller_origin_)) {
+    request_delegate_->DisableUI();
+
+    // As Cryptotoken validates the origin, accept the relying party id as the
+    // origin from requests originating from Cryptotoken.
+    client_data_json_ = SerializeCollectedClientDataToJson(
+        client_data::kU2fSignType, options->relying_party_id,
+        std::move(options->challenge), true /* use_legacy_u2f_type_key */);
+  } else {
+    client_data_json_ = SerializeCollectedClientDataToJson(
+        client_data::kGetType, caller_origin_.Serialize(),
+        std::move(options->challenge));
+  }
+
+  if (!HasValidEffectiveDomain(caller_origin_)) {
+    ReportSecurityCheckFailure(
+        RelyingPartySecurityCheckFailure::kOpaqueOrNonSecureOrigin);
+    bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
+                                    bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN);
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+                             nullptr);
+    return;
+  }
+
+  if (!IsRelyingPartyIdValid(options->relying_party_id, caller_origin_)) {
+    ReportSecurityCheckFailure(
+        RelyingPartySecurityCheckFailure::kRelyingPartyIdInvalid);
+    bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(),
+                                    bad_message::AUTH_INVALID_RELYING_PARTY);
+    InvokeCallbackAndCleanup(std::move(callback),
+                             blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+                             nullptr);
+    return;
+  }
+
+  if (options->allow_credentials.empty()) {
+    // Chrome currently does not support any resident keys.
+    InvokeCallbackAndCleanup(
+        std::move(callback),
+        blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED,
+        nullptr);
+    return;
+  }
+
+  if (options->appid) {
+    app_id_ = ProcessAppIdExtension(*options->appid, caller_origin_);
+    if (!app_id_) {
+      std::move(callback).Run(blink::mojom::AuthenticatorStatus::INVALID_DOMAIN,
+                              nullptr);
+      return;
+    }
+  }
+
+  // U2F requests proxied from the cryptotoken extension are limited to USB
+  // devices.
+  const auto transports =
+      OriginIsCryptoTokenExtension(caller_origin_)
+          ? base::flat_set<device::FidoTransportProtocol>(
+                {device::FidoTransportProtocol::kUsbHumanInterfaceDevice})
+          : transports_;
+
+  UMA_HISTOGRAM_COUNTS_100(
+      "WebAuthentication.CredentialRequestAllowCredentialsCount",
+      options->allow_credentials.size());
+
+  DCHECK(get_assertion_response_callback_.is_null());
+  get_assertion_response_callback_ = std::move(callback);
+
+  timer_->Start(
+      FROM_HERE, options->adjusted_timeout,
+      base::BindOnce(&AuthenticatorCommon::OnTimeout, base::Unretained(this)));
+
+  if (!connector_)
+    connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
+
+  auto ctap_request = CreateCtapGetAssertionRequest(
+      client_data_json_, std::move(options), app_id_,
+      browser_context()->IsOffTheRecord());
+  auto opt_platform_authenticator_info =
+      CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
+          ctap_request);
+  request_ = std::make_unique<device::GetAssertionRequestHandler>(
+      connector_, transports, std::move(ctap_request),
+      base::BindOnce(&AuthenticatorCommon::OnSignResponse,
+                     weak_factory_.GetWeakPtr()));
+
+  request_delegate_->RegisterActionCallbacks(
+      base::BindOnce(&AuthenticatorCommon::Cancel,
+                     weak_factory_.GetWeakPtr()) /* cancel_callback */,
+      base::BindRepeating(
+          &device::FidoRequestHandlerBase::StartAuthenticatorRequest,
+          request_->GetWeakPtr()) /* request_callback */,
+      base::BindRepeating(
+          &device::FidoRequestHandlerBase::PowerOnBluetoothAdapter,
+          request_->GetWeakPtr()) /* bluetooth_adapter_power_on_callback */,
+      base::BindRepeating(
+          &device::FidoRequestHandlerBase::InitiatePairingWithDevice,
+          request_->GetWeakPtr()) /* ble_pairing_callback*/);
+  request_->set_observer(request_delegate_.get());
+
+  request_->SetPlatformAuthenticatorOrMarkUnavailable(
+      std::move(opt_platform_authenticator_info));
+}
+
+void AuthenticatorCommon::IsUserVerifyingPlatformAuthenticatorAvailable(
+    IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) {
+  const bool result = IsUserVerifyingPlatformAuthenticatorAvailableImpl();
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), result));
+}
+
+bool AuthenticatorCommon::IsUserVerifyingPlatformAuthenticatorAvailableImpl() {
+  //  N.B. request_delegate_ may be nullptr at this point.
+  // All platform authenticators are disabled in incognito mode.
+  // TODO(martinkr): Revisit incognito handling (crbug/908622).
+  if (browser_context()->IsOffTheRecord())
+    return false;
+
+#if defined(OS_MACOSX)
+  // Touch ID is disabled, regardless of hardware support, if the embedder
+  // doesn't support it.
+  if (!GetContentClient()
+           ->browser()
+           ->IsWebAuthenticationTouchIdAuthenticatorSupported())
+    return false;
+
+  return device::fido::mac::TouchIdAuthenticator::IsAvailable();
+#elif defined(OS_WIN)
+  return base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi) &&
+         device::WinWebAuthnApiAuthenticator::
+             IsUserVerifyingPlatformAuthenticatorAvailable();
+#else
+  return false;
+#endif
+}
+
+void AuthenticatorCommon::DidFinishNavigation(
+    NavigationHandle* navigation_handle) {
+  // If the RenderFrameHost itself is navigated then this function will cause
+  // request state to be cleaned up. It's also possible for a navigation in the
+  // same frame to use a fresh RenderFrameHost. In this case,
+  // |render_frame_host_->IsCurrent()| will start returning false, causing all
+  // focus checks to fail if any Mojo requests are made in that state.
+  if (!navigation_handle->HasCommitted() ||
+      navigation_handle->IsSameDocument() ||
+      navigation_handle->GetRenderFrameHost() != render_frame_host_) {
+    return;
+  }
+
+  binding_.Close();
+  Cleanup();
+}
+
+// Callback to handle the async registration response from a U2fDevice.
+void AuthenticatorCommon::OnRegisterResponse(
+    device::FidoReturnCode status_code,
+    base::Optional<device::AuthenticatorMakeCredentialResponse> response_data,
+    base::Optional<device::FidoTransportProtocol> transport_used) {
+  if (!request_) {
+    // Either the callback was called immediately and |request_| has not yet
+    // been assigned (this is a bug), or a navigation caused the request to be
+    // canceled while a callback was enqueued.
+    return;
+  }
+
+  switch (status_code) {
+    case device::FidoReturnCode::kUserConsentButCredentialExcluded:
+      // Duplicate registration: the new credential would be created on an
+      // authenticator that already contains one of the credentials in
+      // |exclude_credentials|.
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kKeyAlreadyRegistered);
+      return;
+    case device::FidoReturnCode::kAuthenticatorResponseInvalid:
+      // The response from the authenticator was corrupted.
+      InvokeCallbackAndCleanup(
+          std::move(make_credential_response_callback_),
+          blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+          Focus::kDoCheck);
+      return;
+    case device::FidoReturnCode::kUserConsentButCredentialNotRecognized:
+      // TODO(crbug/876109): This isn't strictly unreachable.
+      NOTREACHED();
+      return;
+    case device::FidoReturnCode::kUserConsentDenied:
+      InvokeCallbackAndCleanup(
+          std::move(make_credential_response_callback_),
+          blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+          Focus::kDoCheck);
+      return;
+    case device::FidoReturnCode::kSoftPINBlock:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kSoftPINBlock);
+      return;
+    case device::FidoReturnCode::kHardPINBlock:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kHardPINBlock);
+      return;
+    case device::FidoReturnCode::kAuthenticatorRemovedDuringPINEntry:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kAuthenticatorRemovedDuringPINEntry);
+      return;
+    case device::FidoReturnCode::kSuccess:
+      DCHECK(response_data.has_value());
+
+      if (transport_used) {
+        request_delegate_->UpdateLastTransportUsed(*transport_used);
+      }
+
+      if (attestation_requested_) {
+        // Cryptotoken requests may bypass the attestation prompt because the
+        // extension implements its own. Invoking the attestation prompt code
+        // here would not work anyway, because the WebContents associated with
+        // the extension is not associated with any tab and therefore cannot
+        // draw modal dialogs for the UI.
+        //
+        // Note that for AttestationConveyancePreference::NONE, attestation
+        // erasure is still performed as usual.
+        if (OriginIsCryptoTokenExtension(caller_origin_)) {
+          InvokeCallbackAndCleanup(
+              std::move(make_credential_response_callback_),
+              blink::mojom::AuthenticatorStatus::SUCCESS,
+              CreateMakeCredentialResponse(
+                  std::move(client_data_json_), std::move(*response_data),
+                  AttestationErasureOption::kIncludeAttestation),
+              Focus::kDoCheck);
+          return;
+        }
+
+        UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+                                  AttestationPromptResult::kQueried);
+        awaiting_attestation_response_ = true;
+        request_delegate_->ShouldReturnAttestation(
+            relying_party_id_,
+            base::BindOnce(
+                &AuthenticatorCommon::OnRegisterResponseAttestationDecided,
+                weak_factory_.GetWeakPtr(), std::move(*response_data)));
+        return;
+      }
+
+      AttestationErasureOption attestation_erasure =
+          AttestationErasureOption::kEraseAttestationAndAaguid;
+      if (response_data->IsSelfAttestation()) {
+        attestation_erasure = AttestationErasureOption::kIncludeAttestation;
+      } else if (transport_used &&
+                 *transport_used == device::FidoTransportProtocol::kInternal) {
+        // Contrary to what the WebAuthn spec says, for internal (platform)
+        // authenticators we do not erase the AAGUID from authenticatorData,
+        // even if requested attestationConveyancePreference is "none".
+        attestation_erasure =
+            AttestationErasureOption::kEraseAttestationButIncludeAaguid;
+      }
+
+      InvokeCallbackAndCleanup(
+          std::move(make_credential_response_callback_),
+          blink::mojom::AuthenticatorStatus::SUCCESS,
+          CreateMakeCredentialResponse(std::move(client_data_json_),
+                                       std::move(*response_data),
+                                       attestation_erasure),
+          Focus::kDoCheck);
+      return;
+  }
+  NOTREACHED();
+}
+
+void AuthenticatorCommon::OnRegisterResponseAttestationDecided(
+    device::AuthenticatorMakeCredentialResponse response_data,
+    bool attestation_permitted) {
+  awaiting_attestation_response_ = false;
+  if (!request_) {
+    // The request has already been cleaned up, probably because a navigation
+    // occured while the permissions prompt was pending.
+    return;
+  }
+
+  DCHECK(attestation_requested_);
+
+  if (!attestation_permitted) {
+    UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+                              AttestationPromptResult::kBlocked);
+    InvokeCallbackAndCleanup(
+        std::move(make_credential_response_callback_),
+        blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr,
+        Focus::kDoCheck);
+    return;
+  }
+
+  UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+                            AttestationPromptResult::kAllowed);
+  AttestationErasureOption attestation_erasure =
+      AttestationErasureOption::kIncludeAttestation;
+
+  // The check for IsAttestationCertificateInappropriatelyIdentifying is
+  // performed after the permissions prompt, even though we know the answer
+  // before, because this still effectively discloses the make & model of
+  // the authenticator: If an RP sees a "none" attestation from Chrome after
+  // requesting direct attestation then it knows that it was one of the
+  // tokens with inappropriate certs.
+  if (response_data.IsAttestationCertificateInappropriatelyIdentifying() &&
+      !request_delegate_->ShouldPermitIndividualAttestation(
+          relying_party_id_)) {
+    // The attestation response is incorrectly individually identifiable, but
+    // the consent is for make & model information about a token, not for
+    // individually-identifiable information. Erase the attestation to stop it
+    // begin a tracking signal.
+
+    // The only way to get the underlying attestation will be to list the RP ID
+    // in the enterprise policy, because that enables the individual attestation
+    // bit in the register request and permits individual attestation generally.
+    attestation_erasure = AttestationErasureOption::kEraseAttestationAndAaguid;
+  }
+
+  InvokeCallbackAndCleanup(std::move(make_credential_response_callback_),
+                           blink::mojom::AuthenticatorStatus::SUCCESS,
+                           CreateMakeCredentialResponse(
+                               std::move(client_data_json_),
+                               std::move(response_data), attestation_erasure),
+                           Focus::kDoCheck);
+}
+
+void AuthenticatorCommon::OnSignResponse(
+    device::FidoReturnCode status_code,
+    base::Optional<std::vector<device::AuthenticatorGetAssertionResponse>>
+        response_data,
+    base::Optional<device::FidoTransportProtocol> transport_used) {
+  DCHECK(!response_data || !response_data->empty());  // empty vector is invalid
+
+  if (!request_) {
+    // Either the callback was called immediately and |request_| has not yet
+    // been assigned (this is a bug), or a navigation caused the request to be
+    // canceled while a callback was enqueued.
+    return;
+  }
+
+  switch (status_code) {
+    case device::FidoReturnCode::kUserConsentButCredentialNotRecognized:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kKeyNotRegistered);
+      return;
+    case device::FidoReturnCode::kAuthenticatorResponseInvalid:
+      // The response from the authenticator was corrupted.
+      InvokeCallbackAndCleanup(
+          std::move(get_assertion_response_callback_),
+          blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+      return;
+    case device::FidoReturnCode::kUserConsentButCredentialExcluded:
+      // TODO(crbug/876109): This isn't strictly unreachable.
+      NOTREACHED();
+      return;
+    case device::FidoReturnCode::kUserConsentDenied:
+      InvokeCallbackAndCleanup(
+          std::move(get_assertion_response_callback_),
+          blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+      return;
+    case device::FidoReturnCode::kSoftPINBlock:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kSoftPINBlock);
+      return;
+    case device::FidoReturnCode::kHardPINBlock:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kHardPINBlock);
+      return;
+    case device::FidoReturnCode::kAuthenticatorRemovedDuringPINEntry:
+      SignalFailureToRequestDelegate(
+          AuthenticatorRequestClientDelegate::InterestingFailureReason::
+              kAuthenticatorRemovedDuringPINEntry);
+      return;
+    case device::FidoReturnCode::kSuccess:
+      DCHECK(response_data.has_value());
+      // Resident keys are not yet supported so there must be a single response.
+      DCHECK_EQ(1u, response_data->size());
+      auto& response = response_data.value()[0];
+
+      if (transport_used) {
+        request_delegate_->UpdateLastTransportUsed(*transport_used);
+      }
+
+      base::Optional<bool> echo_appid_extension;
+      if (app_id_) {
+        echo_appid_extension =
+            (response.GetRpIdHash() == CreateApplicationParameter(*app_id_));
+      }
+      InvokeCallbackAndCleanup(std::move(get_assertion_response_callback_),
+                               blink::mojom::AuthenticatorStatus::SUCCESS,
+                               CreateGetAssertionResponse(
+                                   std::move(client_data_json_),
+                                   std::move(response), echo_appid_extension));
+      return;
+  }
+  NOTREACHED();
+}
+
+void AuthenticatorCommon::SignalFailureToRequestDelegate(
+    AuthenticatorRequestClientDelegate::InterestingFailureReason reason) {
+  blink::mojom::AuthenticatorStatus status =
+      blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+
+  switch (reason) {
+    case AuthenticatorRequestClientDelegate::InterestingFailureReason::
+        kKeyAlreadyRegistered:
+      status = blink::mojom::AuthenticatorStatus::CREDENTIAL_EXCLUDED;
+      break;
+    case AuthenticatorRequestClientDelegate::InterestingFailureReason::
+        kKeyNotRegistered:
+      status = blink::mojom::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED;
+      break;
+    case AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout:
+      status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+      break;
+    case AuthenticatorRequestClientDelegate::InterestingFailureReason::
+        kSoftPINBlock:
+      status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+      break;
+    case AuthenticatorRequestClientDelegate::InterestingFailureReason::
+        kHardPINBlock:
+      status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+      break;
+    case AuthenticatorRequestClientDelegate::InterestingFailureReason::
+        kAuthenticatorRemovedDuringPINEntry:
+      status = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+      break;
+  }
+
+  error_awaiting_user_acknowledgement_ = status;
+
+  // If WebAuthnUi is enabled, this error blocks until after receiving user
+  // acknowledgement. Otherwise, the error is returned right away.
+  if (request_delegate_->DoesBlockRequestOnFailure(reason)) {
+    // Cancel pending authenticator requests before the error dialog is shown.
+    request_->CancelActiveAuthenticators();
+    return;
+  }
+
+  FailWithErrorAndCleanup();
+}  // namespace content
+
+void AuthenticatorCommon::FailWithErrorAndCleanup() {
+  DCHECK(make_credential_response_callback_ ||
+         get_assertion_response_callback_);
+  if (make_credential_response_callback_) {
+    InvokeCallbackAndCleanup(std::move(make_credential_response_callback_),
+                             error_awaiting_user_acknowledgement_, nullptr,
+                             Focus::kDontCheck);
+  } else if (get_assertion_response_callback_) {
+    InvokeCallbackAndCleanup(std::move(get_assertion_response_callback_),
+                             error_awaiting_user_acknowledgement_, nullptr);
+  }
+}
+
+// TODO(crbug.com/814418): Add web tests to verify timeouts are
+// indistinguishable from NOT_ALLOWED_ERROR cases.
+void AuthenticatorCommon::OnTimeout() {
+  DCHECK(request_delegate_);
+  if (awaiting_attestation_response_) {
+    UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+                              AttestationPromptResult::kTimeout);
+    awaiting_attestation_response_ = false;
+  }
+
+  SignalFailureToRequestDelegate(
+      AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout);
+}
+
+void AuthenticatorCommon::Cancel() {
+  // If response callback is invoked already, then ignore cancel request.
+  if (!make_credential_response_callback_ && !get_assertion_response_callback_)
+    return;
+
+  FailWithErrorAndCleanup();
+}
+
+void AuthenticatorCommon::InvokeCallbackAndCleanup(
+    MakeCredentialCallback callback,
+    blink::mojom::AuthenticatorStatus status,
+    blink::mojom::MakeCredentialAuthenticatorResponsePtr response,
+    Focus check_focus) {
+  if (check_focus != Focus::kDontCheck && !(request_delegate_ && IsFocused())) {
+    std::move(callback).Run(blink::mojom::AuthenticatorStatus::NOT_FOCUSED,
+                            nullptr);
+  } else {
+    std::move(callback).Run(status, std::move(response));
+  }
+
+  Cleanup();
+}
+
+void AuthenticatorCommon::InvokeCallbackAndCleanup(
+    GetAssertionCallback callback,
+    blink::mojom::AuthenticatorStatus status,
+    blink::mojom::GetAssertionAuthenticatorResponsePtr response) {
+  std::move(callback).Run(status, std::move(response));
+  Cleanup();
+}
+
+void AuthenticatorCommon::Cleanup() {
+  if (awaiting_attestation_response_) {
+    UMA_HISTOGRAM_ENUMERATION("WebAuthentication.AttestationPromptResult",
+                              AttestationPromptResult::kAbandoned);
+    awaiting_attestation_response_ = false;
+  }
+
+  timer_->Stop();
+  request_.reset();
+  request_delegate_.reset();
+  make_credential_response_callback_.Reset();
+  get_assertion_response_callback_.Reset();
+  client_data_json_.clear();
+  app_id_.reset();
+  attestation_requested_ = false;
+  error_awaiting_user_acknowledgement_ =
+      blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+}
+
+BrowserContext* AuthenticatorCommon::browser_context() const {
+  return content::WebContents::FromRenderFrameHost(render_frame_host_)
+      ->GetBrowserContext();
+}
+
+#if defined(OS_MACOSX)
+namespace {
+std::unique_ptr<device::fido::mac::TouchIdAuthenticator>
+CreateTouchIdAuthenticatorIfAvailable(
+    const AuthenticatorRequestClientDelegate* request_delegate) {
+  // Not all embedders may provide an authenticator config.
+  auto opt_authenticator_config =
+      request_delegate->GetTouchIdAuthenticatorConfig();
+  if (!opt_authenticator_config) {
+    return nullptr;
+  }
+  return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
+      std::move(opt_authenticator_config->keychain_access_group),
+      std::move(opt_authenticator_config->metadata_secret));
+}
+}  // namespace
+#endif
+
+base::Optional<device::PlatformAuthenticatorInfo>
+AuthenticatorCommon::CreatePlatformAuthenticatorIfAvailable() {
+  // Incognito mode disables platform authenticators, so check for availability
+  // first.
+  if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) {
+    return base::nullopt;
+  }
+#if defined(OS_MACOSX)
+  return device::PlatformAuthenticatorInfo(
+      CreateTouchIdAuthenticatorIfAvailable(request_delegate_.get()), false);
+#else
+  return base::nullopt;
+#endif
+}
+
+base::Optional<device::PlatformAuthenticatorInfo> AuthenticatorCommon::
+    CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
+        const device::CtapGetAssertionRequest& request) {
+  // Incognito mode disables platform authenticators, so check for availability
+  // first.
+  if (!IsUserVerifyingPlatformAuthenticatorAvailableImpl()) {
+    return base::nullopt;
+  }
+#if defined(OS_MACOSX)
+  std::unique_ptr<device::fido::mac::TouchIdAuthenticator> authenticator =
+      CreateTouchIdAuthenticatorIfAvailable(request_delegate_.get());
+  const bool has_credential =
+      authenticator->HasCredentialForGetAssertionRequest(request);
+  return device::PlatformAuthenticatorInfo(std::move(authenticator),
+                                           has_credential);
+#else
+  return base::nullopt;
+#endif
+}
+
+}  // namespace content
diff --git a/content/browser/webauth/authenticator_common.h b/content/browser/webauth/authenticator_common.h
new file mode 100644
index 0000000..63c1d28e
--- /dev/null
+++ b/content/browser/webauth/authenticator_common.h
@@ -0,0 +1,219 @@
+// Copyright 2019 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 CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
+#define CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/authenticator_request_client_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "crypto/sha2.h"
+#include "device/fido/authenticator_get_assertion_response.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_transport_protocol.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h"
+#include "url/origin.h"
+
+namespace base {
+class OneShotTimer;
+}
+
+namespace device {
+
+struct PlatformAuthenticatorInfo;
+class CtapGetAssertionRequest;
+class FidoRequestHandlerBase;
+
+enum class FidoReturnCode : uint8_t;
+
+}  // namespace device
+
+namespace service_manager {
+class Connector;
+}  // namespace service_manager
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+class BrowserContext;
+class RenderFrameHost;
+
+namespace client_data {
+// These enumerate the possible values for the `type` member of
+// CollectedClientData. See
+// https://w3c.github.io/webauthn/#dom-collectedclientdata-type
+CONTENT_EXPORT extern const char kCreateType[];
+CONTENT_EXPORT extern const char kGetType[];
+}  // namespace client_data
+
+// Implementation of the public Authenticator interface.
+class CONTENT_EXPORT AuthenticatorCommon : public blink::mojom::Authenticator,
+                                         public WebContentsObserver {
+ public:
+  explicit AuthenticatorCommon(RenderFrameHost* render_frame_host);
+
+  // Permits setting connector and timer for testing. Using this constructor
+  // will also empty out the protocol set, since no device discovery will take
+  // place during tests.
+  AuthenticatorCommon(RenderFrameHost* render_frame_host,
+                    service_manager::Connector*,
+                    std::unique_ptr<base::OneShotTimer>);
+  ~AuthenticatorCommon() override;
+
+  // Creates a binding between this implementation and |request|.
+  //
+  // Note that one AuthenticatorCommon instance can be bound to exactly one
+  // interface connection at a time, and disconnected when the frame navigates
+  // to a new active document.
+  void Bind(blink::mojom::AuthenticatorRequest request);
+
+  base::flat_set<device::FidoTransportProtocol> enabled_transports_for_testing()
+      const {
+    return transports_;
+  }
+  void set_transports_for_testing(
+      base::flat_set<device::FidoTransportProtocol> transports) {
+    transports_ = transports;
+  }
+
+ protected:
+  virtual void UpdateRequestDelegate();
+
+  std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
+
+ private:
+  friend class AuthenticatorCommonTest;
+
+  // Enumerates whether or not to check that the WebContents has focus.
+  enum class Focus {
+    kDoCheck,
+    kDontCheck,
+  };
+
+  bool IsFocused() const;
+
+  // Builds the CollectedClientData[1] dictionary with the given values,
+  // serializes it to JSON, and returns the resulting string. For legacy U2F
+  // requests coming from the CryptoToken U2F extension, modifies the object key
+  // 'type' as required[2].
+  // [1] https://w3c.github.io/webauthn/#dictdef-collectedclientdata
+  // [2]
+  // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#client-data
+  static std::string SerializeCollectedClientDataToJson(
+      const std::string& type,
+      const std::string& origin,
+      base::span<const uint8_t> challenge,
+      bool use_legacy_u2f_type_key = false);
+
+  // mojom:Authenticator
+  void MakeCredential(
+      blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
+      MakeCredentialCallback callback) override;
+  void GetAssertion(blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
+                    GetAssertionCallback callback) override;
+  void IsUserVerifyingPlatformAuthenticatorAvailable(
+      IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) override;
+
+  // Synchronous implementation of IsUserVerfyingPlatformAuthenticatorAvailable.
+  bool IsUserVerifyingPlatformAuthenticatorAvailableImpl();
+
+  // WebContentsObserver:
+  void DidFinishNavigation(NavigationHandle* navigation_handle) override;
+
+  // Callback to handle the async response from a U2fDevice.
+  void OnRegisterResponse(
+      device::FidoReturnCode status_code,
+      base::Optional<device::AuthenticatorMakeCredentialResponse> response_data,
+      base::Optional<device::FidoTransportProtocol> transport_used);
+
+  // Callback to complete the registration process once a decision about
+  // whether or not to return attestation data has been made.
+  void OnRegisterResponseAttestationDecided(
+      device::AuthenticatorMakeCredentialResponse response_data,
+      bool attestation_permitted);
+
+  // Callback to handle the async response from a U2fDevice.
+  void OnSignResponse(
+      device::FidoReturnCode status_code,
+      base::Optional<std::vector<device::AuthenticatorGetAssertionResponse>>
+          response_data,
+      base::Optional<device::FidoTransportProtocol> transport_used);
+
+  void FailWithErrorAndCleanup();
+
+  // Runs when timer expires and cancels all issued requests to a U2fDevice.
+  void OnTimeout();
+  // Runs when the user cancels WebAuthN request via UI dialog.
+  void Cancel();
+
+  // Decides whether or not UI is present that needs to block on user
+  // acknowledgement before returning the error, and handles the error
+  // appropriately.
+  void SignalFailureToRequestDelegate(
+      AuthenticatorRequestClientDelegate::InterestingFailureReason reason);
+
+  void InvokeCallbackAndCleanup(
+      MakeCredentialCallback callback,
+      blink::mojom::AuthenticatorStatus status,
+      blink::mojom::MakeCredentialAuthenticatorResponsePtr response,
+      Focus focus_check);
+  void InvokeCallbackAndCleanup(
+      GetAssertionCallback callback,
+      blink::mojom::AuthenticatorStatus status,
+      blink::mojom::GetAssertionAuthenticatorResponsePtr response);
+  void Cleanup();
+
+  base::Optional<device::PlatformAuthenticatorInfo>
+  CreatePlatformAuthenticatorIfAvailable();
+  base::Optional<device::PlatformAuthenticatorInfo>
+  CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
+      const device::CtapGetAssertionRequest& request);
+
+  BrowserContext* browser_context() const;
+
+  RenderFrameHost* const render_frame_host_;
+  service_manager::Connector* connector_ = nullptr;
+  base::flat_set<device::FidoTransportProtocol> transports_;
+
+  std::unique_ptr<device::FidoRequestHandlerBase> request_;
+  MakeCredentialCallback make_credential_response_callback_;
+  GetAssertionCallback get_assertion_response_callback_;
+  std::string client_data_json_;
+  bool attestation_requested_;
+  url::Origin caller_origin_;
+  std::string relying_party_id_;
+  std::unique_ptr<base::OneShotTimer> timer_;
+  base::Optional<std::string> app_id_;
+  // awaiting_attestation_response_ is true if the embedder has been queried
+  // about an attestsation decision and the response is still pending.
+  bool awaiting_attestation_response_ = false;
+  blink::mojom::AuthenticatorStatus error_awaiting_user_acknowledgement_ =
+      blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+
+  // Owns pipes to this Authenticator from |render_frame_host_|.
+  mojo::Binding<blink::mojom::Authenticator> binding_;
+
+  base::WeakPtrFactory<AuthenticatorCommon> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(AuthenticatorCommon);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc
index ddeabf2..2e079e4 100644
--- a/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -64,7 +64,7 @@
   base::ScopedAllowBlockingForTesting allow_blocking;
 
   std::string contents;
-  if (base::EndsWith(id, ".mojom.js", base::CompareCase::SENSITIVE)) {
+  if (base::EndsWith(id, ".mojom-lite.js", base::CompareCase::SENSITIVE)) {
     CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents))
         << id;
   } else {
@@ -300,7 +300,7 @@
 // it from the browser to the page and back.
 IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
   if (!IsGeneratedResourceAvailable(
-          "content/test/data/web_ui_test_mojo_bindings.mojom.js"))
+          "content/test/data/web_ui_test_mojo_bindings.mojom-lite.js"))
     return;
 
   g_got_message = false;
diff --git a/content/public/renderer/associated_resource_fetcher.h b/content/public/renderer/associated_resource_fetcher.h
index d83fd72..8cbf01a1 100644
--- a/content/public/renderer/associated_resource_fetcher.h
+++ b/content/public/renderer/associated_resource_fetcher.h
@@ -63,7 +63,6 @@
       blink::mojom::RequestContextType request_context,
       network::mojom::FetchRequestMode fetch_request_mode,
       network::mojom::FetchCredentialsMode fetch_credentials_mode,
-      network::mojom::RequestContextFrameType frame_type,
       const Callback& callback) = 0;
 
   // Manually cancel the request.
diff --git a/content/renderer/fetchers/associated_resource_fetcher_impl.cc b/content/renderer/fetchers/associated_resource_fetcher_impl.cc
index 9e67bcee..daa8c557a7 100644
--- a/content/renderer/fetchers/associated_resource_fetcher_impl.cc
+++ b/content/renderer/fetchers/associated_resource_fetcher_impl.cc
@@ -157,7 +157,6 @@
     blink::mojom::RequestContextType request_context,
     network::mojom::FetchRequestMode fetch_request_mode,
     network::mojom::FetchCredentialsMode fetch_credentials_mode,
-    network::mojom::RequestContextFrameType frame_type,
     const Callback& callback) {
   DCHECK(!loader_);
   DCHECK(!client_);
@@ -166,7 +165,6 @@
     DCHECK_NE("GET", request_.HttpMethod().Utf8()) << "GETs can't have bodies.";
 
   request_.SetRequestContext(request_context);
-  request_.SetFrameType(frame_type);
   request_.SetSiteForCookies(frame->GetDocument().SiteForCookies());
   request_.SetFetchRequestMode(fetch_request_mode);
   request_.SetFetchCredentialsMode(fetch_credentials_mode);
diff --git a/content/renderer/fetchers/associated_resource_fetcher_impl.h b/content/renderer/fetchers/associated_resource_fetcher_impl.h
index 9dba3c9..2a7dff38 100644
--- a/content/renderer/fetchers/associated_resource_fetcher_impl.h
+++ b/content/renderer/fetchers/associated_resource_fetcher_impl.h
@@ -36,7 +36,6 @@
              blink::mojom::RequestContextType request_context,
              network::mojom::FetchRequestMode request_mode,
              network::mojom::FetchCredentialsMode fetch_credentials_mode,
-             network::mojom::RequestContextFrameType frame_type,
              const Callback& callback) override;
 
  private:
diff --git a/content/renderer/fetchers/manifest_fetcher.cc b/content/renderer/fetchers/manifest_fetcher.cc
index 942e3d5..8c45f2e 100644
--- a/content/renderer/fetchers/manifest_fetcher.cc
+++ b/content/renderer/fetchers/manifest_fetcher.cc
@@ -39,7 +39,6 @@
       network::mojom::FetchRequestMode::kCors,
       use_credentials ? network::mojom::FetchCredentialsMode::kInclude
                       : network::mojom::FetchCredentialsMode::kOmit,
-      network::mojom::RequestContextFrameType::kNone,
       base::Bind(&ManifestFetcher::OnLoadComplete, base::Unretained(this)));
 }
 
diff --git a/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
index 9dfc626..bde6f72 100644
--- a/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
+++ b/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -57,7 +57,6 @@
   fetcher_->Start(
       frame, request_context, network::mojom::FetchRequestMode::kNoCors,
       network::mojom::FetchCredentialsMode::kInclude,
-      network::mojom::RequestContextFrameType::kNone,
       base::Bind(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
                  base::Unretained(this)));
 }
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc
index d599f85..0c2ae21 100644
--- a/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -469,7 +469,6 @@
   const GURL kRequestURL = GURL(kTestURL);
   const std::string kMimeType = "application/javascript";
   blink::WebURLRequest request(kRequestURL);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kNone);
   request.SetRequestContext(blink::mojom::RequestContextType::SCRIPT);
   std::unique_ptr<NavigationResponseOverrideParameters> response_override(
       new NavigationResponseOverrideParameters());
diff --git a/content/renderer/media/android/media_player_renderer_client.cc b/content/renderer/media/android/media_player_renderer_client.cc
index 2c1fb90..2502de6 100644
--- a/content/renderer/media/android/media_player_renderer_client.cc
+++ b/content/renderer/media/android/media_player_renderer_client.cc
@@ -15,7 +15,7 @@
     std::unique_ptr<media::MojoRenderer> mojo_renderer,
     media::ScopedStreamTextureWrapper stream_texture_wrapper,
     media::VideoRendererSink* sink)
-    : mojo_renderer_(std::move(mojo_renderer)),
+    : MojoRendererWrapper(std::move(mojo_renderer)),
       stream_texture_wrapper_(std::move(stream_texture_wrapper)),
       client_(nullptr),
       sink_(sink),
@@ -56,6 +56,13 @@
                  weak_factory_.GetWeakPtr(), media_resource));
 }
 
+void MediaPlayerRendererClient::SetCdm(
+    media::CdmContext* cdm_context,
+    const media::CdmAttachedCB& cdm_attached_cb) {
+  // MediaPlayerRenderer does not support encrypted media.
+  NOTREACHED();
+}
+
 void MediaPlayerRendererClient::OnStreamTextureWrapperInitialized(
     media::MediaResource* media_resource,
     bool success) {
@@ -66,7 +73,7 @@
     return;
   }
 
-  mojo_renderer_->Initialize(
+  MojoRendererWrapper::Initialize(
       media_resource, this,
       base::Bind(&MediaPlayerRendererClient::OnRemoteRendererInitialized,
                  weak_factory_.GetWeakPtr()));
@@ -98,32 +105,6 @@
   base::ResetAndReturn(&init_cb_).Run(status);
 }
 
-void MediaPlayerRendererClient::SetCdm(
-    media::CdmContext* cdm_context,
-    const media::CdmAttachedCB& cdm_attached_cb) {
-  NOTREACHED();
-}
-
-void MediaPlayerRendererClient::Flush(const base::Closure& flush_cb) {
-  mojo_renderer_->Flush(flush_cb);
-}
-
-void MediaPlayerRendererClient::StartPlayingFrom(base::TimeDelta time) {
-  mojo_renderer_->StartPlayingFrom(time);
-}
-
-void MediaPlayerRendererClient::SetPlaybackRate(double playback_rate) {
-  mojo_renderer_->SetPlaybackRate(playback_rate);
-}
-
-void MediaPlayerRendererClient::SetVolume(float volume) {
-  mojo_renderer_->SetVolume(volume);
-}
-
-base::TimeDelta MediaPlayerRendererClient::GetMediaTime() {
-  return mojo_renderer_->GetMediaTime();
-}
-
 void MediaPlayerRendererClient::OnFrameAvailable() {
   DCHECK(compositor_task_runner_->BelongsToCurrentThread());
   sink_->PaintSingleFrame(stream_texture_wrapper_->GetCurrentFrame(), true);
diff --git a/content/renderer/media/android/media_player_renderer_client.h b/content/renderer/media/android/media_player_renderer_client.h
index 3e90a1e..4d208f6f3 100644
--- a/content/renderer/media/android/media_player_renderer_client.h
+++ b/content/renderer/media/android/media_player_renderer_client.h
@@ -18,15 +18,16 @@
 #include "media/base/renderer_client.h"
 #include "media/base/video_renderer_sink.h"
 #include "media/mojo/clients/mojo_renderer.h"
+#include "media/mojo/clients/mojo_renderer_wrapper.h"
 
 namespace content {
 
 // MediaPlayerRendererClient lives in Renderer process and mirrors a
 // MediaPlayerRenderer living in the Browser process.
 //
-// It is responsible for forwarding media::Renderer calls from WMPI to the
-// MediaPlayerRenderer, using |mojo_renderer|. It also manages a StreamTexture,
-// (via |stream_texture_wrapper_|) and notifies the VideoRendererSink when new
+// It is primarily used as a media::Renderer that forwards calls from WMPI to
+// the MediaPlayerRenderer, by inheriting from MojoRendererWrapper.
+// It also manages a StreamTexture, and notifies the VideoRendererSink when new
 // frames are available.
 //
 // This class handles all calls on |media_task_runner_|, except for
@@ -35,8 +36,9 @@
 // N.B: This class implements media::RendererClient, in order to intercept
 // OnVideoNaturalSizeChange() events, to update StreamTextureWrapper. All events
 // (including OnVideoNaturalSizeChange()) are bubbled up to |client_|.
-class CONTENT_EXPORT MediaPlayerRendererClient : public media::Renderer,
-                                                 public media::RendererClient {
+class CONTENT_EXPORT MediaPlayerRendererClient
+    : public media::RendererClient,
+      public media::MojoRendererWrapper {
  public:
   MediaPlayerRendererClient(
       scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
@@ -47,17 +49,14 @@
 
   ~MediaPlayerRendererClient() override;
 
-  // media::Renderer implementation.
+  // media::Renderer implementation (inherited from media::MojoRendererWrapper).
+  // We override normal initialization to set up |stream_texture_wrapper_|,
+  // and do not support encrypted media.
   void Initialize(media::MediaResource* media_resource,
                   media::RendererClient* client,
                   const media::PipelineStatusCB& init_cb) override;
   void SetCdm(media::CdmContext* cdm_context,
               const media::CdmAttachedCB& cdm_attached_cb) override;
-  void Flush(const base::Closure& flush_cb) override;
-  void StartPlayingFrom(base::TimeDelta time) override;
-  void SetPlaybackRate(double playback_rate) override;
-  void SetVolume(float volume) override;
-  base::TimeDelta GetMediaTime() override;
 
   // media::RendererClient implementation.
   void OnError(media::PipelineStatus status) override;
diff --git a/content/renderer/pepper/pepper_websocket_host.cc b/content/renderer/pepper/pepper_websocket_host.cc
index b52762b7..b0aa5db 100644
--- a/content/renderer/pepper/pepper_websocket_host.cc
+++ b/content/renderer/pepper/pepper_websocket_host.cc
@@ -142,8 +142,7 @@
                                PpapiPluginMsg_WebSocket_ErrorReply());
 }
 
-void PepperWebSocketHost::DidUpdateBufferedAmount(
-    unsigned long buffered_amount) {
+void PepperWebSocketHost::DidUpdateBufferedAmount(uint64_t buffered_amount) {
   // Send an IPC to update buffered amount.
   host()->SendUnsolicitedReply(
       pp_resource(),
@@ -159,7 +158,7 @@
       PpapiPluginMsg_WebSocket_StateReply(PP_WEBSOCKETREADYSTATE_CLOSING));
 }
 
-void PepperWebSocketHost::DidClose(unsigned long unhandled_buffered_amount,
+void PepperWebSocketHost::DidClose(uint64_t unhandled_buffered_amount,
                                    ClosingHandshakeCompletionStatus status,
                                    uint16_t code,
                                    const blink::WebString& reason) {
diff --git a/content/renderer/pepper/pepper_websocket_host.h b/content/renderer/pepper/pepper_websocket_host.h
index a77b452a..17ea26f 100644
--- a/content/renderer/pepper/pepper_websocket_host.h
+++ b/content/renderer/pepper/pepper_websocket_host.h
@@ -41,9 +41,9 @@
   void DidReceiveMessage(const blink::WebString& message) override;
   void DidReceiveArrayBuffer(const blink::WebArrayBuffer& binaryData) override;
   void DidReceiveMessageError() override;
-  void DidUpdateBufferedAmount(unsigned long buffered_amount) override;
+  void DidUpdateBufferedAmount(uint64_t buffered_amount) override;
   void DidStartClosingHandshake() override;
-  void DidClose(unsigned long unhandled_buffered_amount,
+  void DidClose(uint64_t unhandled_buffered_amount,
                 ClosingHandshakeCompletionStatus status,
                 uint16_t code,
                 const blink::WebString& reason) override;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 1aab1f8..3a133a9 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5161,10 +5161,11 @@
 }
 
 void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
-  WillSendRequestInternal(request);
+  WillSendRequestInternal(request, WebURLRequestToResourceType(request));
 }
 
-void RenderFrameImpl::WillSendRequestInternal(blink::WebURLRequest& request) {
+void RenderFrameImpl::WillSendRequestInternal(blink::WebURLRequest& request,
+                                              ResourceType resource_type) {
   if (render_view_->renderer_preferences_.enable_do_not_track)
     request.SetHTTPHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader),
                                "1");
@@ -5226,35 +5227,6 @@
   // present.
   request.SetHTTPOriginIfNeeded(WebSecurityOrigin::CreateUnique());
 
-  WebFrame* parent = frame_->Parent();
-
-  ResourceType resource_type = RESOURCE_TYPE_SUB_RESOURCE;
-  network::mojom::RequestContextFrameType frame_type = request.GetFrameType();
-  if (frame_type != network::mojom::RequestContextFrameType::kNone) {
-    DCHECK(request.GetRequestContext() ==
-               blink::mojom::RequestContextType::FORM ||
-           request.GetRequestContext() ==
-               blink::mojom::RequestContextType::FRAME ||
-           request.GetRequestContext() ==
-               blink::mojom::RequestContextType::HYPERLINK ||
-           request.GetRequestContext() ==
-               blink::mojom::RequestContextType::IFRAME ||
-           request.GetRequestContext() ==
-               blink::mojom::RequestContextType::INTERNAL ||
-           request.GetRequestContext() ==
-               blink::mojom::RequestContextType::LOCATION);
-    if (frame_type == network::mojom::RequestContextFrameType::kTopLevel ||
-        frame_type == network::mojom::RequestContextFrameType::kAuxiliary) {
-      resource_type = RESOURCE_TYPE_MAIN_FRAME;
-    } else if (frame_type == network::mojom::RequestContextFrameType::kNested) {
-      resource_type = RESOURCE_TYPE_SUB_FRAME;
-    } else {
-      NOTREACHED();
-    }
-  } else {
-    resource_type = WebURLRequestToResourceType(request);
-  }
-
   WebDocument frame_document = frame_->GetDocument();
   if (!request.GetExtraData())
     request.SetExtraData(std::make_unique<RequestExtraData>());
@@ -5263,7 +5235,7 @@
       GetContentClient()->renderer()->IsPrerenderingFrame(this));
   extra_data->set_custom_user_agent(custom_user_agent);
   extra_data->set_render_frame_id(routing_id_);
-  extra_data->set_is_main_frame(!parent);
+  extra_data->set_is_main_frame(IsMainFrame());
   extra_data->set_allow_download(
       navigation_state->common_params().download_policy.IsDownloadAllowed());
   extra_data->set_transition_type(transition_type);
@@ -6994,8 +6966,7 @@
 
   // Set SiteForCookies.
   WebDocument frame_document = frame_->GetDocument();
-  if (request.GetFrameType() ==
-      network::mojom::RequestContextFrameType::kTopLevel)
+  if (info->frame_type == network::mojom::RequestContextFrameType::kTopLevel)
     request.SetSiteForCookies(request.Url());
   else
     request.SetSiteForCookies(frame_document.SiteForCookies());
@@ -7010,7 +6981,8 @@
   // TODO(clamy): Apply devtools override.
   // TODO(clamy): Make sure that navigation requests are not modified somewhere
   // else in blink.
-  WillSendRequestInternal(request);
+  WillSendRequestInternal(request, frame_->Parent() ? RESOURCE_TYPE_SUB_FRAME
+                                                    : RESOURCE_TYPE_MAIN_FRAME);
 
   // Update the transition type of the request for client side redirects.
   if (!info->url_request.GetExtraData())
@@ -7034,11 +7006,10 @@
   DCHECK_EQ(network::mojom::FetchRedirectMode::kManual,
             info->url_request.GetFetchRedirectMode());
   DCHECK(frame_->Parent() ||
-         info->url_request.GetFrameType() ==
+         info->frame_type ==
              network::mojom::RequestContextFrameType::kTopLevel);
   DCHECK(!frame_->Parent() ||
-         info->url_request.GetFrameType() ==
-             network::mojom::RequestContextFrameType::kNested);
+         info->frame_type == network::mojom::RequestContextFrameType::kNested);
 
   bool is_form_submission =
       info->navigation_type == blink::kWebNavigationTypeFormSubmitted ||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 888410ee..08550bf 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1275,7 +1275,8 @@
   bool ShouldDisplayErrorPageForFailedLoad(int error_code,
                                            const GURL& unreachable_url);
 
-  void WillSendRequestInternal(blink::WebURLRequest& request);
+  void WillSendRequestInternal(blink::WebURLRequest& request,
+                               ResourceType resource_type);
 
   // Returns the URL being loaded by the |frame_|'s request.
   GURL GetLoadingUrl() const;
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index b4236f8d..b026f79 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -656,11 +656,12 @@
   request.SetFetchCredentialsMode(
       network::mojom::FetchCredentialsMode::kInclude);
   request.SetFetchRedirectMode(network::mojom::FetchRedirectMode::kManual);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kTopLevel);
   request.SetRequestContext(blink::mojom::RequestContextType::INTERNAL);
   request.SetRequestorOrigin(requestor_origin);
   auto navigation_info = std::make_unique<blink::WebNavigationInfo>();
   navigation_info->url_request = request;
+  navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   navigation_info->navigation_type = blink::kWebNavigationTypeLinkClicked;
   navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
   DCHECK(!navigation_info->url_request.RequestorOrigin().IsNull());
@@ -675,6 +676,8 @@
       blink::WebURLRequest(GURL("chrome://foo"));
   form_navigation_info->url_request.SetHTTPMethod("POST");
   form_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
+  form_navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   form_navigation_info->navigation_type =
       blink::kWebNavigationTypeFormSubmitted;
   form_navigation_info->navigation_policy =
@@ -690,6 +693,8 @@
   popup_navigation_info->url_request =
       blink::WebURLRequest(GURL("chrome://foo"));
   popup_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
+  popup_navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kAuxiliary;
   popup_navigation_info->navigation_type = blink::kWebNavigationTypeLinkClicked;
   popup_navigation_info->navigation_policy =
       blink::kWebNavigationPolicyNewForegroundTab;
@@ -718,6 +723,8 @@
     navigation_info->url_request = blink::WebURLRequest(GURL("http://foo.com"));
     navigation_info->url_request.SetRequestorOrigin(
         blink::WebSecurityOrigin::Create(GURL("http://foo.com")));
+    navigation_info->frame_type =
+        network::mojom::RequestContextFrameType::kTopLevel;
     navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
     navigation_info->navigation_type = kNavTypes[i];
 
@@ -739,6 +746,8 @@
   auto navigation_info = std::make_unique<blink::WebNavigationInfo>();
   navigation_info->url_request = blink::WebURLRequest(GURL("http://foo.com"));
   navigation_info->url_request.SetRequestorOrigin(requestor_origin);
+  navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   navigation_info->navigation_type = blink::kWebNavigationTypeLinkClicked;
   navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
 
@@ -752,6 +761,8 @@
   webui_navigation_info->url_request =
       blink::WebURLRequest(GURL("chrome://foo"));
   webui_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
+  webui_navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   webui_navigation_info->navigation_type = blink::kWebNavigationTypeLinkClicked;
   webui_navigation_info->navigation_policy =
       blink::kWebNavigationPolicyCurrentTab;
@@ -766,6 +777,8 @@
       blink::WebURLRequest(GURL("data:text/html,foo"));
   data_navigation_info->url_request.SetRequestorOrigin(requestor_origin);
   data_navigation_info->url_request.SetHTTPMethod("POST");
+  data_navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   data_navigation_info->navigation_type =
       blink::kWebNavigationTypeFormSubmitted;
   data_navigation_info->navigation_policy =
@@ -788,6 +801,8 @@
   RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view);
   auto popup_navigation_info = std::make_unique<blink::WebNavigationInfo>();
   popup_navigation_info->url_request = popup_request;
+  popup_navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kAuxiliary;
   popup_navigation_info->navigation_type = blink::kWebNavigationTypeLinkClicked;
   popup_navigation_info->navigation_policy =
       blink::kWebNavigationPolicyNewForegroundTab;
@@ -832,6 +847,8 @@
   // Empty url should never fork.
   auto navigation_info = std::make_unique<blink::WebNavigationInfo>();
   navigation_info->url_request = blink::WebURLRequest(empty_url);
+  navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
   frame()->BeginNavigation(std::move(navigation_info));
   EXPECT_FALSE(render_thread_->sink().GetUniqueMessageMatching(
@@ -849,6 +866,8 @@
   // About blank should never fork.
   auto navigation_info = std::make_unique<blink::WebNavigationInfo>();
   navigation_info->url_request = blink::WebURLRequest(blank_url);
+  navigation_info->frame_type =
+      network::mojom::RequestContextFrameType::kTopLevel;
   navigation_info->navigation_policy = blink::kWebNavigationPolicyCurrentTab;
   frame()->BeginNavigation(std::move(navigation_info));
   EXPECT_FALSE(render_thread_->sink().GetUniqueMessageMatching(
diff --git a/content/test/data/accessibility/aria/aria-banner-expected-win.txt b/content/test/data/accessibility/aria/aria-banner-expected-win.txt
index f901211e..71fef080 100644
--- a/content/test/data/accessibility/aria/aria-banner-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-banner-expected-win.txt
@@ -1,3 +1,3 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++IA2_ROLE_HEADER xml-roles:banner
+++IA2_ROLE_LANDMARK xml-roles:banner
 ++++ROLE_SYSTEM_STATICTEXT name='Chromium Browser'
diff --git a/content/test/data/accessibility/event/aria-combo-box-collapse-expected-uia-win.txt b/content/test/data/accessibility/event/aria-combo-box-collapse-expected-uia-win.txt
index 50c9f72..310fec1 100644
--- a/content/test/data/accessibility/event/aria-combo-box-collapse-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-collapse-expected-uia-win.txt
@@ -1 +1,2 @@
 AutomationFocusChanged on role=combobox
+ExpandCollapseExpandCollapseState changed on role=combobox
diff --git a/content/test/data/accessibility/event/aria-combo-box-expand-expected-uia-win.txt b/content/test/data/accessibility/event/aria-combo-box-expand-expected-uia-win.txt
index cf51261..2ee2453 100644
--- a/content/test/data/accessibility/event/aria-combo-box-expand-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-expand-expected-uia-win.txt
@@ -1,2 +1,3 @@
 AutomationFocusChanged on role=option, name=Apple
+ExpandCollapseExpandCollapseState changed on role=combobox
 SelectionItem_ElementSelected on role=option, name=Apple
diff --git a/content/test/data/accessibility/event/checked-state-changed-expected-uia-win.txt b/content/test/data/accessibility/event/checked-state-changed-expected-uia-win.txt
new file mode 100644
index 0000000..90f4d03
--- /dev/null
+++ b/content/test/data/accessibility/event/checked-state-changed-expected-uia-win.txt
@@ -0,0 +1,2 @@
+ToggleToggleState changed on role=checkbox, name=My Checkbox
+ToggleToggleState changed on role=treeitem, name=Treeitem
diff --git a/content/test/data/accessibility/event/description-change-expected-uia-win.txt b/content/test/data/accessibility/event/description-change-expected-uia-win.txt
new file mode 100644
index 0000000..367dbfc
--- /dev/null
+++ b/content/test/data/accessibility/event/description-change-expected-uia-win.txt
@@ -0,0 +1 @@
+FullDescription changed on role=heading, name=Before
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt b/content/test/data/accessibility/event/description-change-expected-uia-win7.txt
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt
rename to content/test/data/accessibility/event/description-change-expected-uia-win7.txt
diff --git a/content/test/data/accessibility/event/description-change-indirect-expected-uia-win.txt b/content/test/data/accessibility/event/description-change-indirect-expected-uia-win.txt
new file mode 100644
index 0000000..4ba19bd
--- /dev/null
+++ b/content/test/data/accessibility/event/description-change-indirect-expected-uia-win.txt
@@ -0,0 +1 @@
+FullDescription changed on role=main
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt b/content/test/data/accessibility/event/description-change-indirect-expected-uia-win7.txt
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt
copy to content/test/data/accessibility/event/description-change-indirect-expected-uia-win7.txt
diff --git a/content/test/data/accessibility/event/invalid-status-change-expected-uia-win.txt b/content/test/data/accessibility/event/invalid-status-change-expected-uia-win.txt
new file mode 100644
index 0000000..0629984
--- /dev/null
+++ b/content/test/data/accessibility/event/invalid-status-change-expected-uia-win.txt
@@ -0,0 +1 @@
+IsDataValidForForm changed on role=textbox, name=Field
diff --git a/content/test/data/accessibility/html/footer-expected-auralinux.txt b/content/test/data/accessibility/html/footer-expected-auralinux.txt
index a127933..86b85ab9 100644
--- a/content/test/data/accessibility/html/footer-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/footer-expected-auralinux.txt
@@ -1,3 +1,3 @@
 [document web]
-++[footer]
+++[landmark] xml-roles:contentinfo
 ++++[text] name='Footer element'
diff --git a/content/test/data/accessibility/html/footer-expected-mac.txt b/content/test/data/accessibility/html/footer-expected-mac.txt
index 831f0bb..b7c96cc 100644
--- a/content/test/data/accessibility/html/footer-expected-mac.txt
+++ b/content/test/data/accessibility/html/footer-expected-mac.txt
@@ -1,3 +1,3 @@
-AXWebArea
+AXWebArea AXRoleDescription='HTML content'
 ++AXGroup AXSubrole=AXLandmarkContentInfo AXRoleDescription='footer'
-++++AXStaticText AXValue='Footer element'
+++++AXStaticText AXRoleDescription='text' AXValue='Footer element'
diff --git a/content/test/data/accessibility/html/footer-expected-win.txt b/content/test/data/accessibility/html/footer-expected-win.txt
index 2f76d283..dff5d39 100644
--- a/content/test/data/accessibility/html/footer-expected-win.txt
+++ b/content/test/data/accessibility/html/footer-expected-win.txt
@@ -1,3 +1,3 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++IA2_ROLE_FOOTER
+++IA2_ROLE_LANDMARK xml-roles:contentinfo
 ++++ROLE_SYSTEM_STATICTEXT name='Footer element'
diff --git a/content/test/data/accessibility/html/footer.html b/content/test/data/accessibility/html/footer.html
index 16d7044..4087ce2 100644
--- a/content/test/data/accessibility/html/footer.html
+++ b/content/test/data/accessibility/html/footer.html
@@ -1,6 +1,8 @@
 <!--
-@MAC-ALLOW:AXRoleDescription='footer'
+@MAC-ALLOW:AXRole*
 @MAC-ALLOW:AXSubrole*
+@WIN-ALLOW:xml-roles:*
+@AURALINUX-ALLOW:xml-roles:*
 -->
 <html>
 <body>
diff --git a/content/test/data/accessibility/html/header-expected-win.txt b/content/test/data/accessibility/html/header-expected-win.txt
index f901211e..71fef080 100644
--- a/content/test/data/accessibility/html/header-expected-win.txt
+++ b/content/test/data/accessibility/html/header-expected-win.txt
@@ -1,3 +1,3 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++IA2_ROLE_HEADER xml-roles:banner
+++IA2_ROLE_LANDMARK xml-roles:banner
 ++++ROLE_SYSTEM_STATICTEXT name='Chromium Browser'
diff --git a/content/test/data/accessibility/html/landmark-expected-auralinux.txt b/content/test/data/accessibility/html/landmark-expected-auralinux.txt
index 01e583e3..93e1550 100644
--- a/content/test/data/accessibility/html/landmark-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/landmark-expected-auralinux.txt
@@ -5,7 +5,7 @@
 ++++[text] name='This is an aside element.'
 ++[section]
 ++++[text] name='This is an address element.'
-++[footer] xml-roles:contentinfo
+++[landmark] xml-roles:contentinfo
 ++++[text] name='This is a footer element.'
 ++[form]
 ++++[text] name='This is a form element.'
diff --git a/content/test/data/accessibility/html/landmark-expected-win.txt b/content/test/data/accessibility/html/landmark-expected-win.txt
index d3a879c..1ca76d59 100644
--- a/content/test/data/accessibility/html/landmark-expected-win.txt
+++ b/content/test/data/accessibility/html/landmark-expected-win.txt
@@ -1,11 +1,11 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++IA2_ROLE_HEADER xml-roles:banner
+++IA2_ROLE_LANDMARK xml-roles:banner
 ++++ROLE_SYSTEM_STATICTEXT name='This is a header element.'
 ++IA2_ROLE_LANDMARK xml-roles:complementary
 ++++ROLE_SYSTEM_STATICTEXT name='This is an aside element.'
 ++IA2_ROLE_SECTION
 ++++ROLE_SYSTEM_STATICTEXT name='This is an address element.'
-++IA2_ROLE_FOOTER xml-roles:contentinfo
+++IA2_ROLE_LANDMARK xml-roles:contentinfo
 ++++ROLE_SYSTEM_STATICTEXT name='This is a footer element.'
 ++IA2_ROLE_FORM
 ++++ROLE_SYSTEM_STATICTEXT name='This is a form element.'
@@ -15,7 +15,7 @@
 ++++ROLE_SYSTEM_STATICTEXT name='This is a nav element.'
 ++ROLE_SYSTEM_APPLICATION xml-roles:application
 ++++ROLE_SYSTEM_STATICTEXT name='This is an ARIA application landmark.'
-++IA2_ROLE_HEADER xml-roles:banner
+++IA2_ROLE_LANDMARK xml-roles:banner
 ++++ROLE_SYSTEM_STATICTEXT name='This is an ARIA banner landmark.'
 ++IA2_ROLE_LANDMARK xml-roles:complementary
 ++++ROLE_SYSTEM_STATICTEXT name='This is an ARIA complementary landmark.'
diff --git a/content/test/data/web_ui_mojo.html b/content/test/data/web_ui_mojo.html
index 6467469a..519cda1 100644
--- a/content/test/data/web_ui_mojo.html
+++ b/content/test/data/web_ui_mojo.html
@@ -1,7 +1,7 @@
 <html>
 <head>
-  <script src="chrome://resources/js/mojo_bindings.js"></script>
-  <script src="content/test/data/web_ui_test_mojo_bindings.mojom.js"></script>
+  <script src="chrome://resources/js/mojo_bindings_lite.js"></script>
+  <script src="content/test/data/web_ui_test_mojo_bindings.mojom-lite.js"></script>
   <script src="web_ui_mojo.js"></script>
 </head>
 <body>
diff --git a/content/test/data/web_ui_mojo.js b/content/test/data/web_ui_mojo.js
index d5f8bc580..497cc79b 100644
--- a/content/test/data/web_ui_mojo.js
+++ b/content/test/data/web_ui_mojo.js
@@ -2,10 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var browserTarget = new content.mojom.BrowserTargetPtr;
-Mojo.bindInterface(content.mojom.BrowserTarget.name,
-                   mojo.makeRequest(browserTarget).handle);
+var browserTarget = content.mojom.BrowserTarget.getProxy();
 
 browserTarget.start().then(function() {
   browserTarget.stop();
-});
\ No newline at end of file
+});
diff --git a/docs/memory-infra/heap_profiler.md b/docs/memory-infra/heap_profiler.md
index b7df04b..6e0c635 100644
--- a/docs/memory-infra/heap_profiler.md
+++ b/docs/memory-infra/heap_profiler.md
@@ -4,41 +4,29 @@
 allocations (calls to new or malloc without a subsequent call to delete or free)
 along with sufficient metadata to identify the code that made the allocation.
 
+By default, MemoryInfra traces will not contain heap dumps. Heap profiling must
+be enabled via chrome://memory-internals or about://flags.
+
 [TOC]
 
 ## How to obtain a heap dump (M66+, Linux, macOS, Windows)
 
- 1. Navigate to chrome://flags and search for `memlog`.
-
- 2. Choose the process types you want to profile with the `memlog` flag. The
-    most common setting is `Only Browser`.
-
- 3. You can control resolution of sampling with `memlog-sampling-rate`.
-    By default samples are collected with the average interval of 100KB.
-    On versions prior Chrome 75 you can enable `memlog-keep-small-allocations`
-    to record all the allocations, however this option has a significant
-    performance and memory overhead.
-
- 4. By default, stack traces use native stack traces, which does not contain any
-    thread information. To include the thread at time of allocation, set
-    `memlog-stack-mode` to `native with thread names`.
-
- 5. Restart Chrome.
-
- 6. Grab a [MemoryInfra][memory-infra] trace.
-
- 7. Save the trace.
-
- 8. To symbolize the trace:
+ 1. Navigate to chrome://memory-internals.
+    * There will be an error message at the top if heap-profiling is not
+      supported on the current configuration
+ 2. Enable heap profiling for the relevant processes. Future allocations will be
+    tracked. Refresh the page to view tracked processes.
+    * To enable tracking at process start, navigate to chrome://flags and search
+      for `memlog`.
+ 3. To take a heap dump, click `save dump`. This is stored as a
+    [MemoryInfra][memory-infra] trace.
+ 4. To symbolize the trace:
    * Windows only: build `addr2line-pdb` from the chromium repository. For subsequent commands, add the flag `--addr2line-executable=<path_to_addr2lin-pdb>`
    * If this is a local build, run the command `./third_party/catapult/tracing/bin/symbolize_trace --is-local-build <path_to_trace>`
    * If this is an official Chrome build,  run `./third_party/catapult/tracing/bin/symbolize_trace <path_to_trace>`. This will request authentication with google cloud storage to obtain symbol files [googlers only].
    * If this is an official macOS or Linux Chrome build, add the flag `--use-breakpad-symbols`.
    * If the trace is from a different device, add the flag `--only-symbolize-chrome-symbols`.
-
- 9. Turn off heap profiling in chrome://flags. Restart Chrome.
-
- 10. Load the (now symbolized) trace in chrome://tracing.
+ 5. Load the (now symbolized) trace in chrome://tracing.
 
 ## How to obtain a heap dump (M66+, Android)
 
diff --git a/gpu/command_buffer/service/service_font_manager.cc b/gpu/command_buffer/service/service_font_manager.cc
index 53bcf21..7453d18 100644
--- a/gpu/command_buffer/service/service_font_manager.cc
+++ b/gpu/command_buffer/service/service_font_manager.cc
@@ -166,6 +166,10 @@
   if (!deserializer.Read<uint32_t>(&num_locked_handles))
     return false;
 
+  // Loosely avoid extremely large (but fake) numbers of locked handles.
+  if (memory_size / sizeof(SkDiscardableHandleId) < num_locked_handles)
+    return false;
+
   locked_handles->resize(num_locked_handles);
   for (uint32_t i = 0; i < num_locked_handles; ++i) {
     if (!deserializer.Read<SkDiscardableHandleId>(&locked_handles->at(i)))
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index 14581ef..072234b 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -65,6 +65,8 @@
 SharedContextState::~SharedContextState() {
   if (gr_context_)
     gr_context_->abandonContext();
+  if (context_->IsCurrent(nullptr))
+    context_->ReleaseCurrent(nullptr);
   base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
       this);
 }
diff --git a/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc
index 9f2e84a..2f33475 100644
--- a/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc
@@ -50,11 +50,11 @@
       return;
     }
 
-    // Antialiasing won't be enabled if framebuffer CMAA is disabled via GPU
-    // driver workarounds 'disable_framebuffer_cmaa'.
-    available_ = !gl_.workarounds().disable_framebuffer_cmaa;
+    // Antialiasing will be enabled if framebuffer CMAA is enabled via GPU
+    // driver workarounds 'use_framebuffer_cmaa'.
+    available_ = gl_.workarounds().use_framebuffer_cmaa;
     if (!available_) {
-      LOG(INFO) << "'disable_framebuffer_cmaa' workaround applied. "
+      LOG(INFO) << "'use_framebuffer_cmaa' workaround not applied. "
                    "Skipping test...";
       return;
     }
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index c02208ca..25bff8ed 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -1612,23 +1612,19 @@
       "id": 172,
       "description": "Use GL_INTEL_framebuffer_CMAA on ChromeOS",
       "cr_bugs": [535198],
-      "exceptions" : [
-        {
-          "os": {
-            "type" : "chromeos"
-          },
-          "vendor_id": "0x8086",
-          "driver_vendor": "Mesa",
-          "gl_vendor": "Intel.*",
-          "gl_type": "gles",
-          "gl_version": {
-            "op": ">=",
-            "value": "3.1"
-          }
-        }
-      ],
+      "os": {
+        "type" : "chromeos"
+      },
+      "vendor_id": "0x8086",
+      "driver_vendor": "Mesa",
+      "gl_vendor": "Intel.*",
+      "gl_type": "gles",
+      "gl_version": {
+        "op": ">=",
+        "value": "3.1"
+      },
       "features": [
-        "disable_framebuffer_cmaa"
+        "use_framebuffer_cmaa"
       ]
     },
     {
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt
index b8bb9cf..800131e 100644
--- a/gpu/config/gpu_workaround_list.txt
+++ b/gpu/config/gpu_workaround_list.txt
@@ -28,7 +28,6 @@
 disable_es3_gl_context
 disable_es3_gl_context_for_testing
 disable_ext_draw_buffers
-disable_framebuffer_cmaa
 disable_gl_rgb_format
 disable_larger_than_screen_overlays
 disable_non_empty_post_sub_buffers_for_onscreen_surfaces
@@ -101,6 +100,7 @@
 unpack_overlapping_rows_separately_unpack_buffer
 use_client_side_arrays_for_stream_buffers
 use_es2_for_oopr
+use_framebuffer_cmaa
 use_gpu_driver_workaround_for_testing
 use_intermediary_for_copy_texture_image
 use_non_zero_size_for_client_side_stream_buffers
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 32aaa0f..ef9c51ce 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -330,7 +330,7 @@
 gpu::ContextResult InProcessCommandBuffer::Initialize(
     scoped_refptr<gl::GLSurface> surface,
     bool is_offscreen,
-    SurfaceHandle window,
+    SurfaceHandle surface_handle,
     const ContextCreationAttribs& attribs,
     InProcessCommandBuffer* share_group,
     GpuMemoryBufferManager* gpu_memory_buffer_manager,
@@ -343,6 +343,7 @@
   DCHECK(!share_group || task_executor_ == share_group->task_executor_);
   TRACE_EVENT0("gpu", "InProcessCommandBuffer::Initialize")
 
+  is_offscreen_ = is_offscreen;
   gpu_memory_buffer_manager_ = gpu_memory_buffer_manager;
   gpu_channel_manager_delegate_ = gpu_channel_manager_delegate;
 
@@ -362,8 +363,8 @@
   }
 
   Capabilities capabilities;
-  InitializeOnGpuThreadParams params(is_offscreen, window, attribs,
-                                     &capabilities, share_group, image_factory,
+  InitializeOnGpuThreadParams params(surface_handle, attribs, &capabilities,
+                                     share_group, image_factory,
                                      gr_shader_cache, activity_flags);
 
   base::OnceCallback<gpu::ContextResult(void)> init_task =
@@ -455,7 +456,7 @@
       this, context_group_->memory_tracker());
 
   if (!surface_) {
-    if (params.is_offscreen) {
+    if (is_offscreen_) {
       // TODO(crbug.com/832243): GLES2CommandBufferStub has additional logic for
       // offscreen surfaces that might be needed here.
       surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
@@ -497,7 +498,7 @@
           break;
       }
       surface_ = ImageTransportSurface::CreateNativeSurface(
-          gpu_thread_weak_ptr_factory_.GetWeakPtr(), params.window,
+          gpu_thread_weak_ptr_factory_.GetWeakPtr(), params.surface_handle,
           surface_format);
       if (!surface_ || !surface_->Initialize(surface_format)) {
         DestroyOnGpuThread();
@@ -648,7 +649,7 @@
   }
 
   gles2::DisallowedFeatures disallowed_features;
-  auto result = decoder_->Initialize(surface_, context_, params.is_offscreen,
+  auto result = decoder_->Initialize(surface_, context_, is_offscreen_,
                                      disallowed_features, params.attribs);
   if (result != gpu::ContextResult::kSuccess) {
     DestroyOnGpuThread();
@@ -761,6 +762,14 @@
   // error and make the race benign.
   UpdateLastStateOnGpuThread();
 
+  // Tell the browser about this context loss so it can determine whether client
+  // APIs like WebGL need to be blocked from automatically running.
+  if (gpu_channel_manager_delegate_) {
+    CommandBuffer::State state = command_buffer_->GetState();
+    gpu_channel_manager_delegate_->DidLoseContext(
+        is_offscreen_, state.context_lost_reason, active_url_.url());
+  }
+
   bool was_lost_by_robustness =
       decoder_ && decoder_->WasContextLostByRobustnessExtension();
 
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h
index 95d8e07..869d11c4 100644
--- a/gpu/ipc/in_process_command_buffer.h
+++ b/gpu/ipc/in_process_command_buffer.h
@@ -97,7 +97,7 @@
   gpu::ContextResult Initialize(
       scoped_refptr<gl::GLSurface> surface,
       bool is_offscreen,
-      SurfaceHandle window,
+      SurfaceHandle surface_handle,
       const ContextCreationAttribs& attribs,
       InProcessCommandBuffer* share_group,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
@@ -195,8 +195,7 @@
   class SharedImageInterface;
 
   struct InitializeOnGpuThreadParams {
-    bool is_offscreen;
-    SurfaceHandle window;
+    SurfaceHandle surface_handle;
     const ContextCreationAttribs& attribs;
     Capabilities* capabilities;  // Ouptut.
     InProcessCommandBuffer* share_command_buffer;
@@ -204,16 +203,14 @@
     gpu::raster::GrShaderCache* gr_shader_cache;
     GpuProcessActivityFlags* activity_flags;
 
-    InitializeOnGpuThreadParams(bool is_offscreen,
-                                SurfaceHandle window,
+    InitializeOnGpuThreadParams(SurfaceHandle surface_handle,
                                 const ContextCreationAttribs& attribs,
                                 Capabilities* capabilities,
                                 InProcessCommandBuffer* share_command_buffer,
                                 ImageFactory* image_factory,
                                 gpu::raster::GrShaderCache* gr_shader_cache,
                                 GpuProcessActivityFlags* activity_flags)
-        : is_offscreen(is_offscreen),
-          window(window),
+        : surface_handle(surface_handle),
           attribs(attribs),
           capabilities(capabilities),
           share_command_buffer(share_command_buffer),
@@ -319,6 +316,8 @@
   const CommandBufferId command_buffer_id_;
   const ContextUrl active_url_;
 
+  bool is_offscreen_ = false;
+
   // Members accessed on the gpu thread (possibly with the exception of
   // creation):
   bool use_virtualized_gl_context_ = false;
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index 65958317..0c86b101 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -973,8 +973,7 @@
   DCHECK(!swap_chain_size.IsEmpty());
 
   Microsoft::WRL::ComPtr<IDXGIResource> decode_resource;
-  image_dxgi->texture()->QueryInterface(
-      IID_PPV_ARGS(decode_resource.GetAddressOf()));
+  image_dxgi->texture().As(&decode_resource);
   DCHECK(decode_resource);
 
   if (!decode_swap_chain_ || decode_resource_ != decode_resource) {
@@ -988,13 +987,13 @@
     swap_chain_handle_.Set(handle);
 
     Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
-    d3d11_device_.CopyTo(dxgi_device.GetAddressOf());
+    d3d11_device_.As(&dxgi_device);
     DCHECK(dxgi_device);
     Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
-    dxgi_device->GetAdapter(dxgi_adapter.GetAddressOf());
+    dxgi_device->GetAdapter(&dxgi_adapter);
     DCHECK(dxgi_adapter);
     Microsoft::WRL::ComPtr<IDXGIFactoryMedia> media_factory;
-    dxgi_adapter->GetParent(IID_PPV_ARGS(media_factory.GetAddressOf()));
+    dxgi_adapter->GetParent(IID_PPV_ARGS(&media_factory));
     DCHECK(media_factory);
 
     DXGI_DECODE_SWAP_CHAIN_DESC desc = {};
@@ -1002,8 +1001,7 @@
     HRESULT hr =
         media_factory->CreateDecodeSwapChainForCompositionSurfaceHandle(
             d3d11_device_.Get(), swap_chain_handle_.Get(), &desc,
-            decode_resource_.Get(), nullptr,
-            decode_swap_chain_.ReleaseAndGetAddressOf());
+            decode_resource_.Get(), nullptr, &decode_swap_chain_);
     base::UmaHistogramSparse(
         "GPU.DirectComposition.DecodeSwapChainCreationResult", hr);
     if (FAILED(hr)) {
@@ -1015,13 +1013,11 @@
     DCHECK(decode_swap_chain_);
 
     Microsoft::WRL::ComPtr<IDCompositionDesktopDevice> desktop_device;
-    dcomp_device_.CopyTo(desktop_device.GetAddressOf());
+    dcomp_device_.As(&desktop_device);
     DCHECK(desktop_device);
 
-    desktop_device->CreateSurfaceFromHandle(
-        swap_chain_handle_.Get(), decode_surface_.ReleaseAndGetAddressOf());
-    base::UmaHistogramSparse(
-        "GPU.DirectComposition.DecodeSwapChainSurfaceCreationResult", hr);
+    desktop_device->CreateSurfaceFromHandle(swap_chain_handle_.Get(),
+                                            &decode_surface_);
     if (FAILED(hr)) {
       DLOG(ERROR) << "CreateSurfaceFromHandle failed with error 0x" << std::hex
                   << hr;
@@ -1068,8 +1064,6 @@
       static_cast<DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS>(flags));
 
   HRESULT hr = decode_swap_chain_->PresentBuffer(image_dxgi->level(), 1, 0);
-  base::UmaHistogramSparse("GPU.DirectComposition.DecodeSwapChainPresentResult",
-                           hr);
   // Ignore DXGI_STATUS_OCCLUDED since that's not an error but only indicates
   // that the window is occluded and we can stop rendering.
   if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) {
@@ -1292,6 +1286,8 @@
       is_yuv_swapchain_ ? g_overlay_format_used : OverlayFormat::kBGRA;
   UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.SwapChainFormat2",
                             swap_chain_format);
+  UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.DecodeSwapChainUsed",
+                        !!decode_swap_chain_);
   TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("gpu.service"),
                        "SwapChain::Present", TRACE_EVENT_SCOPE_THREAD,
                        "PixelFormat", swap_chain_format, "ZeroCopy",
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg
index 09a1cdb..10fa78da 100644
--- a/infra/config/cr-buildbucket.cfg
+++ b/infra/config/cr-buildbucket.cfg
@@ -1395,12 +1395,14 @@
     builders {
       name: "Mac10.10 Tests"
       mixins: "mac-ci"
-      dimensions:"os:Mac-10.10"
+      # The build runs on 10.13, but triggers tests on 10.10 bots.
+      dimensions:"os:Mac-10.13"
     }
     builders {
       name: "Mac10.11 Tests"
       mixins: "mac-ci"
-      dimensions:"os:Mac-10.11"
+      # The build runs on 10.13, but triggers tests on 10.11 bots.
+      dimensions:"os:Mac-10.13"
     }
     builders {
       name: "Mac10.12 Tests"
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index c952010..53d1b8d 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -306,9 +306,6 @@
     {"unified-consent", flag_descriptions::kUnifiedConsentName,
      flag_descriptions::kUnifiedConsentDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(unified_consent::kUnifiedConsent)},
-    {"autofill-dynamic-forms", flag_descriptions::kAutofillDynamicFormsName,
-     flag_descriptions::kAutofillDynamicFormsDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(autofill::features::kAutofillDynamicForms)},
     {"autofill-prefilled-fields",
      flag_descriptions::kAutofillPrefilledFieldsName,
      flag_descriptions::kAutofillPrefilledFieldsDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm b/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm
index 7df1683..9898f3bf 100644
--- a/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm
+++ b/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm
@@ -68,8 +68,8 @@
 
 void InfobarBadgeTabHelper::OnInfoBarAdded(infobars::InfoBar* infobar) {
   this->UpdateBadgeForInfobar(infobar, true);
-  // Set the badgeState to selected since the InfobarBanner has be presented on
-  // OnInfoBarAdded.
+  // Set the badgeState to selected since the InfobarBanner has to be presented
+  // on OnInfoBarAdded.
   delegate_.badgeState = InfobarBadgeStateSelected;
 }
 
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
index 374999c..942d771 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -138,10 +138,6 @@
     "also Apps will launch asynchronously and there will be no logic that"
     "depends on the success or the failure of launching an app.";
 
-const char kAutofillDynamicFormsName[] = "Autofill dynamic forms";
-const char kAutofillDynamicFormsDescription[] =
-    "Refills forms that dynamically change after an initial fill";
-
 const char kAutofillNoLocalSaveOnUploadSuccessName[] =
     "Disable saving local copy of uploaded card when credit card upload "
     "succeeds";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index bf528754..35a1836e 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -107,10 +107,6 @@
 extern const char kAppLauncherRefreshName[];
 extern const char kAppLauncherRefreshDescription[];
 
-// Title and description for the flag to control the dynamic autofill.
-extern const char kAutofillDynamicFormsName[];
-extern const char kAutofillDynamicFormsDescription[];
-
 // Title and description for the flag to control saving FULL_SERVER_CARDS upon
 // success of credit card upload.
 extern const char kAutofillNoLocalSaveOnUploadSuccessName[];
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index b873f576..930df5f 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -88,7 +88,7 @@
   FindTabHelper::CreateForWebState(web_state);
   U2FTabHelper::CreateForWebState(web_state);
   StoreKitTabHelper::CreateForWebState(web_state);
-  JavaScriptConsoleTabHelper::CreateForWebState(tab.webState);
+  JavaScriptConsoleTabHelper::CreateForWebState(web_state);
   ITunesUrlsHandlerTabHelper::CreateForWebState(web_state);
   HistoryTabHelper::CreateForWebState(web_state);
   LoadTimingTabHelper::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
index e3be7c5..f16813e 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -82,7 +82,6 @@
       payments_client_(std::make_unique<payments::PaymentsClient>(
           base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
               web_state_->GetBrowserState()->GetURLLoaderFactory()),
-          pref_service_,
           identity_manager_,
           personal_data_manager_,
           web_state_->GetBrowserState()->IsOffTheRecord())),
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h
index 655f7ac..2aa4917e 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h
@@ -33,6 +33,13 @@
 // The button text displayed by this InfobarBanner.
 @property(nonatomic, copy) NSString* buttonText;
 
+// - If no interaction is occuring, the InfobarBanner will be dismissed.
+// - If there's some interaction occuring the InfobarBanner will be dismissed
+// once this interaction ends.
+// - If the InfobarBanner was dismissed or is now presenting an InfobarModal
+// because of the last interaction. This method will NO-OP.
+- (void)dismissWhenInteractionIsFinished;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_INFOBARS_BANNERS_INFOBAR_BANNER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
index d38080d..e27d365 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -14,9 +14,9 @@
 namespace {
 // Banner View constants.
 const CGFloat kBannerViewCornerRadius = 13.0;
-const CGFloat kBannerViewYShadowOffset = 4.0;
-const CGFloat kBannerViewShadowRadius = 6.0;
-const CGFloat kBannerViewShadowOpactiy = 0.2;
+const CGFloat kBannerViewYShadowOffset = 3.0;
+const CGFloat kBannerViewShadowRadius = 9.0;
+const CGFloat kBannerViewShadowOpactiy = 0.23;
 
 // Bottom Grip constants.
 const CGFloat kBottomGripCornerRadius = 0.2;
@@ -51,6 +51,10 @@
 @property(nonatomic, assign) CGPoint originalCenter;
 // Delegate to handle this InfobarVC actions.
 @property(nonatomic, weak) id<InfobarBannerDelegate> delegate;
+// YES if the user is interacting with the view via a touch gesture.
+@property(nonatomic, assign) BOOL touchInProgress;
+// YES if the view should be dismissed after any touch gesture has ended.
+@property(nonatomic, assign) BOOL shouldDismissAfterTouchesEnded;
 
 @end
 
@@ -181,6 +185,15 @@
   [self.view addGestureRecognizer:panGestureRecognizer];
 }
 
+#pragma mark - Public Methods
+
+- (void)dismissWhenInteractionIsFinished {
+  if (!self.touchInProgress) {
+    [self.delegate dismissInfobarBanner:self];
+  }
+  self.shouldDismissAfterTouchesEnded = YES;
+}
+
 #pragma mark - Private Methods
 
 - (void)buttonTapped:(id)sender {
@@ -193,6 +206,7 @@
 
   if (gesture.state == UIGestureRecognizerStateBegan) {
     self.originalCenter = self.view.center;
+    self.touchInProgress = YES;
   } else if (gesture.state == UIGestureRecognizerStateChanged) {
     self.view.center =
         CGPointMake(self.view.center.x, self.view.center.y + translation.y);
@@ -201,6 +215,8 @@
     if (self.view.center.y - self.originalCenter.y >
         kChangeInPositionForTransition) {
       [self.delegate presentInfobarModalFromBanner];
+      // Since the modal has now been presented prevent any external dismissal.
+      self.shouldDismissAfterTouchesEnded = NO;
       return;
     }
   }
@@ -208,8 +224,10 @@
   if (gesture.state == UIGestureRecognizerStateEnded ||
       gesture.state == UIGestureRecognizerStateCancelled) {
     // If there's more than a 1px translation in the negative Y axis when the
-    // gesture ended dismiss the banner.
-    if (self.view.center.y - self.originalCenter.y < 0) {
+    // gesture ended or |self.shouldDismissAfterInteraction| is YES, dismiss the
+    // banner.
+    if ((self.view.center.y - self.originalCenter.y < 0) ||
+        self.shouldDismissAfterTouchesEnded) {
       [self.delegate dismissInfobarBanner:self];
       return;
     }
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
index 92e39a60..de0df403 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
@@ -107,6 +107,12 @@
                                  completion:nil];
 }
 
+- (void)dismissInfobarBannerIfPresented {
+  if (!self.modalTransitionDriver) {
+    [self.bannerViewController dismissWhenInteractionIsFinished];
+  }
+}
+
 #pragma mark - InfobarBannerDelegate
 
 - (void)bannerInfobarButtonWasPressed:(id)sender {
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h
index aa1d457..ebb6360 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h
@@ -41,6 +41,10 @@
 // baseViewController will be set on init.
 - (void)presentInfobarModalFrom:(UIViewController*)baseViewController;
 
+// Dismisses the InfobarBanner. NO-OP if the banner has
+// already been dismissed or the InfobarModal is being displayed.
+- (void)dismissInfobarBannerIfPresented;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_INFOBARS_COORDINATORS_INFOBAR_COORDINATING_H_
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
index ccd91a4..9e52747e 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -116,6 +116,12 @@
                                  completion:nil];
 }
 
+- (void)dismissInfobarBannerIfPresented {
+  if (!self.modalTransitionDriver) {
+    [self.bannerViewController dismissWhenInteractionIsFinished];
+  }
+}
+
 #pragma mark - InfobarBannerDelegate
 
 - (void)bannerInfobarButtonWasPressed:(UIButton*)sender {
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
index 30255232..3a8e050 100644
--- a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
@@ -24,6 +24,12 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// The duration in seconds that the InfobarCoordinator banner will be presented
+// for.
+const double kBannerPresentationDurationInSeconds = 6.0;
+}  // namespace
+
 @interface InfobarContainerCoordinator () <
     InfobarContainerConsumer,
     SigninPresenter>
@@ -151,6 +157,14 @@
   [infobarCoordinator presentInfobarBannerFrom:self.baseViewController];
   self.infobarViewController = [infobarCoordinator bannerViewController];
   [self.childCoordinators addObject:infobarCoordinator];
+
+  // Dismissed the presented InfobarCoordinator banner after
+  // kBannerPresentationDuration seconds.
+  dispatch_time_t popTime = dispatch_time(
+      DISPATCH_TIME_NOW, kBannerPresentationDurationInSeconds * NSEC_PER_SEC);
+  dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
+    [infobarCoordinator dismissInfobarBannerIfPresented];
+  });
 }
 
 - (void)setUserInteractionEnabled:(BOOL)enabled {
diff --git a/ios/web/navigation/legacy_navigation_manager_impl.h b/ios/web/navigation/legacy_navigation_manager_impl.h
index 76ddf79..35faeb64 100644
--- a/ios/web/navigation/legacy_navigation_manager_impl.h
+++ b/ios/web/navigation/legacy_navigation_manager_impl.h
@@ -48,6 +48,8 @@
       UserAgentOverrideOption user_agent_override_option) override;
   void CommitPendingItem() override;
   void CommitPendingItem(std::unique_ptr<NavigationItemImpl> item) override;
+  std::unique_ptr<web::NavigationItemImpl> ReleasePendingItem() override;
+  void SetPendingItem(std::unique_ptr<web::NavigationItemImpl> item) override;
   int GetIndexForOffset(int offset) const override;
   int GetPreviousItemIndex() const override;
   void SetPreviousItemIndex(int previous_item_index) override;
diff --git a/ios/web/navigation/legacy_navigation_manager_impl.mm b/ios/web/navigation/legacy_navigation_manager_impl.mm
index cdde8a6..4b59f896 100644
--- a/ios/web/navigation/legacy_navigation_manager_impl.mm
+++ b/ios/web/navigation/legacy_navigation_manager_impl.mm
@@ -120,6 +120,16 @@
   }
 }
 
+std::unique_ptr<web::NavigationItemImpl>
+LegacyNavigationManagerImpl::ReleasePendingItem() {
+  return [session_controller_ releasePendingItem];
+}
+
+void LegacyNavigationManagerImpl::SetPendingItem(
+    std::unique_ptr<web::NavigationItemImpl> item) {
+  [session_controller_ setPendingItem:std::move(item)];
+}
+
 BrowserState* LegacyNavigationManagerImpl::GetBrowserState() const {
   return browser_state_;
 }
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h
index 8a278ef7..670c5f11 100644
--- a/ios/web/navigation/navigation_manager_impl.h
+++ b/ios/web/navigation/navigation_manager_impl.h
@@ -130,6 +130,18 @@
   // items owned by navigation manager and/or outside of navigation manager.
   virtual void CommitPendingItem(std::unique_ptr<NavigationItemImpl> item) = 0;
 
+  // Removes pending item, so it can be stored in NavigationContext.
+  // Pending item is stored in this object when NavigationContext object does
+  // not yet exist (e.g. when navigation was just requested, or when navigation
+  // has aborted).
+  virtual std::unique_ptr<NavigationItemImpl> ReleasePendingItem() = 0;
+
+  // Allows transferring pending item from NavigationContext to this object.
+  // Pending item can be moved from NavigationContext to this object when
+  // navigation is aborted, but pending item should be retained.
+  virtual void SetPendingItem(
+      std::unique_ptr<web::NavigationItemImpl> item) = 0;
+
   // Returns the navigation index that differs from the current item (or pending
   // item if it exists) by the specified |offset|, skipping redirect navigation
   // items. The index returned is not guaranteed to be valid.
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm
index d7ab19a..1ac40c6b 100644
--- a/ios/web/navigation/navigation_manager_impl_unittest.mm
+++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -2759,6 +2759,19 @@
             last_committed_item->GetReferrer().url);
 }
 
+// Tests SetPendingItem() and ReleasePendingItem() methods.
+TEST_P(NavigationManagerTest, TransferPendingItem) {
+  auto item = std::make_unique<web::NavigationItemImpl>();
+  web::NavigationItemImpl* item_ptr = item.get();
+
+  navigation_manager()->SetPendingItem(std::move(item));
+  EXPECT_EQ(item_ptr, navigation_manager()->GetPendingItem());
+
+  auto extracted_item = navigation_manager()->ReleasePendingItem();
+  EXPECT_FALSE(navigation_manager()->GetPendingItem());
+  EXPECT_EQ(item_ptr, extracted_item.get());
+}
+
 INSTANTIATE_TEST_SUITE_P(
     ProgrammaticNavigationManagerTest,
     NavigationManagerTest,
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.h b/ios/web/navigation/wk_based_navigation_manager_impl.h
index 0166f5c..0991390f 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.h
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.h
@@ -106,6 +106,8 @@
       UserAgentOverrideOption user_agent_override_option) override;
   void CommitPendingItem() override;
   void CommitPendingItem(std::unique_ptr<NavigationItemImpl> item) override;
+  std::unique_ptr<web::NavigationItemImpl> ReleasePendingItem() override;
+  void SetPendingItem(std::unique_ptr<web::NavigationItemImpl> item) override;
   int GetIndexForOffset(int offset) const override;
   // Returns the previous navigation item in the main frame.
   int GetPreviousItemIndex() const override;
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm
index 25c0b542..cf48d7b 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.mm
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -330,6 +330,16 @@
   return current_item_index + offset;
 }
 
+std::unique_ptr<web::NavigationItemImpl>
+WKBasedNavigationManagerImpl::ReleasePendingItem() {
+  return std::move(pending_item_);
+}
+
+void WKBasedNavigationManagerImpl::SetPendingItem(
+    std::unique_ptr<web::NavigationItemImpl> item) {
+  pending_item_ = std::move(item);
+}
+
 int WKBasedNavigationManagerImpl::GetPreviousItemIndex() const {
   return previous_item_index_;
 }
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 750db75..18e1757 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1382,7 +1382,7 @@
       // Transfer pending item ownership to NavigationContext.
       // NavigationManager owns pending item after navigation is requested and
       // until navigation context is created.
-      context->SetItem([self.sessionController releasePendingItem]);
+      context->SetItem(self.navigationManagerImpl->ReleasePendingItem());
     }
   } else {
     context = [self registerLoadRequestForURL:URL
@@ -1926,7 +1926,7 @@
         !(_webUIManager &&
           web::GetWebClient()->IsAppSpecificURL(context->GetUrl()))) {
       if (self.navigationManagerImpl->GetPendingItemIndex() == -1) {
-        context->SetItem([self.sessionController releasePendingItem]);
+        context->SetItem(self.navigationManagerImpl->ReleasePendingItem());
       }
     }
   }
@@ -3733,7 +3733,7 @@
       // This NavigationContext will be destroyed, so return pending item
       // ownership to NavigationManager. NavigationContext can only own pending
       // item until the navigation has committed or aborted.
-      [self.sessionController setPendingItem:context->ReleaseItem()];
+      self.navigationManagerImpl->SetPendingItem(context->ReleaseItem());
     }
     web::NavigationItemImpl* item =
         web::GetItemWithUniqueID(self.navigationManagerImpl, context);
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
index 00ee733..b593199 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -44,7 +44,6 @@
       payments_client_(std::make_unique<payments::PaymentsClient>(
           base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
               web_state_->GetBrowserState()->GetURLLoaderFactory()),
-          pref_service_,
           identity_manager_,
           personal_data_manager_,
           web_state_->GetBrowserState()->IsOffTheRecord())),
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index 4ac39af..473713f 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -508,8 +508,24 @@
       profile = VP8PROFILE_ANY;
       break;
     case kCodecVP9:
+      switch (codec_context->profile) {
+        case FF_PROFILE_VP9_0:
+          profile = VP9PROFILE_PROFILE0;
+          break;
+        case FF_PROFILE_VP9_1:
+          profile = VP9PROFILE_PROFILE1;
+          break;
+        case FF_PROFILE_VP9_2:
+          profile = VP9PROFILE_PROFILE2;
+          break;
+        case FF_PROFILE_VP9_3:
+          profile = VP9PROFILE_PROFILE3;
+          break;
+        default:
+          profile = VP9PROFILE_MIN;
+          break;
+      }
       format = PIXEL_FORMAT_I420;
-      profile = VP9PROFILE_PROFILE0;
       break;
     case kCodecAV1:
       format = PIXEL_FORMAT_I420;
diff --git a/media/learning/common/learning_task.h b/media/learning/common/learning_task.h
index a7ca9b9f..3c24aca 100644
--- a/media/learning/common/learning_task.h
+++ b/media/learning/common/learning_task.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/component_export.h"
+#include "base/optional.h"
 #include "media/learning/common/value.h"
 
 namespace media {
@@ -98,9 +99,17 @@
   double min_new_data_fraction = 0.1;
 
   // If set, then we'll record a confusion matrix hackily to UMA using this as
-  // the histogram name.
+  // the histogram name.  If we're using a (single) feature subset, then we'll
+  // slide the x-axis to the right by multiples of 6 (== size of one confusion
+  // matrix, see enums.xml) to match the chosen feature index.
   std::string uma_hacky_confusion_matrix;
 
+  // If provided, then we'll randomly select a |*feature_subset_size|-sized set
+  // of feature to train the model with, to allow for feature importance
+  // measurement.  Note that |uma_hacky_confusion_matrix| reporting only
+  // supports subsets of size one, or the whole set.
+  base::Optional<int> feature_subset_size;
+
   // RandomForest parameters
 
   // Number of trees in the random forest.
diff --git a/media/learning/impl/distribution_reporter.cc b/media/learning/impl/distribution_reporter.cc
index e657ed3..7643bbd 100644
--- a/media/learning/impl/distribution_reporter.cc
+++ b/media/learning/impl/distribution_reporter.cc
@@ -61,8 +61,22 @@
     // Convert to a bucket from which we can get the confusion matrix.
     ConfusionMatrix uma_bucket = static_cast<ConfusionMatrix>(
         (observed_smooth ? 1 : 0) | predicted_bits);
-    base::UmaHistogramEnumeration(task().uma_hacky_confusion_matrix,
-                                  uma_bucket);
+
+    if (!feature_indices() ||
+        feature_indices()->size() == task().feature_descriptions.size()) {
+      base::UmaHistogramEnumeration(task().uma_hacky_confusion_matrix,
+                                    uma_bucket);
+    } else if (feature_indices()->size() == 1) {
+      // Slide the matrix over by whatever feature we're measuring.
+      constexpr int matrix_size =
+          static_cast<int>(ConfusionMatrix::kMaxValue) + 1;
+      int value_max = matrix_size * task().feature_descriptions.size() - 1;
+      int feature_index = *feature_indices()->begin();
+      base::UmaHistogramExactLinear(
+          task().uma_hacky_confusion_matrix,
+          static_cast<int>(uma_bucket) + feature_index * matrix_size,
+          value_max);
+    }  // else do nothing -- we only support one feature for UMA reporting.
   }
 };
 
@@ -88,5 +102,10 @@
                         weak_factory_.GetWeakPtr(), observed);
 }
 
+void DistributionReporter::SetFeatureSubset(
+    const std::set<int>& feature_indices) {
+  feature_indices_ = feature_indices;
+}
+
 }  // namespace learning
 }  // namespace media
diff --git a/media/learning/impl/distribution_reporter.h b/media/learning/impl/distribution_reporter.h
index 78b22e65..b47ce61 100644
--- a/media/learning/impl/distribution_reporter.h
+++ b/media/learning/impl/distribution_reporter.h
@@ -5,10 +5,13 @@
 #ifndef MEDIA_LEARNING_IMPL_DISTRIBUTION_REPORTER_H_
 #define MEDIA_LEARNING_IMPL_DISTRIBUTION_REPORTER_H_
 
+#include <set>
+
 #include "base/callback.h"
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "media/learning/common/learning_task.h"
 #include "media/learning/impl/model.h"
 #include "media/learning/impl/target_distribution.h"
@@ -31,6 +34,15 @@
   virtual Model::PredictionCB GetPredictionCallback(
       TargetDistribution observed);
 
+  // Set the subset of features that is being used to train the model.  This is
+  // used for feature importance measuremnts.
+  //
+  // For example, sending in the set [0, 3, 7] would indicate that the model was
+  // trained with task().feature_descriptions[0, 3, 7] only.
+  //
+  // Note that UMA reporting only supports single feature subsets.
+  void SetFeatureSubset(const std::set<int>& feature_indices);
+
  protected:
   DistributionReporter(const LearningTask& task);
 
@@ -40,9 +52,17 @@
   virtual void OnPrediction(TargetDistribution observed,
                             TargetDistribution predicted) = 0;
 
+  const base::Optional<std::set<int>>& feature_indices() const {
+    return feature_indices_;
+  }
+
  private:
   LearningTask task_;
 
+  // If provided, then these are the features that are used to train the model.
+  // Otherwise, we assume that all features are used.
+  base::Optional<std::set<int>> feature_indices_;
+
   base::WeakPtrFactory<DistributionReporter> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DistributionReporter);
diff --git a/media/learning/impl/learning_task_controller_impl.cc b/media/learning/impl/learning_task_controller_impl.cc
index a824b6f2..fb1540e 100644
--- a/media/learning/impl/learning_task_controller_impl.cc
+++ b/media/learning/impl/learning_task_controller_impl.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "media/learning/impl/extra_trees_trainer.h"
@@ -20,12 +21,18 @@
     SequenceBoundFeatureProvider feature_provider)
     : task_(task),
       training_data_(std::make_unique<TrainingData>()),
-      reporter_(std::move(reporter)),
-      helper_(std::make_unique<LearningTaskControllerHelper>(
-          task,
-          base::BindRepeating(&LearningTaskControllerImpl::AddFinishedExample,
-                              AsWeakPtr()),
-          std::move(feature_provider))) {
+      reporter_(std::move(reporter)) {
+  // TODO(liberato): Make this compositional.  FeatureSubsetTaskController?
+  if (task_.feature_subset_size)
+    DoFeatureSubsetSelection();
+
+  // Now that we have the updated task, create a helper for it.
+  helper_ = std::make_unique<LearningTaskControllerHelper>(
+      task,
+      base::BindRepeating(&LearningTaskControllerImpl::AddFinishedExample,
+                          AsWeakPtr()),
+      std::move(feature_provider));
+
   switch (task_.model) {
     case LearningTask::Model::kExtraTrees:
       trainer_ = std::make_unique<ExtraTreesTrainer>();
@@ -41,7 +48,17 @@
 void LearningTaskControllerImpl::BeginObservation(
     base::UnguessableToken id,
     const FeatureVector& features) {
-  helper_->BeginObservation(id, features);
+  // Copy just the subset we care about.
+  FeatureVector new_features;
+  if (task_.feature_subset_size) {
+    for (auto& iter : feature_indices_)
+      new_features.push_back(features[iter]);
+  } else {
+    // Use them all.
+    new_features = features;
+  }
+
+  helper_->BeginObservation(id, new_features);
 }
 
 void LearningTaskControllerImpl::CompleteObservation(
@@ -110,5 +127,38 @@
   trainer_ = std::move(trainer);
 }
 
+void LearningTaskControllerImpl::DoFeatureSubsetSelection() {
+  // Choose a random feature, and trim the descriptions to match.
+  std::vector<size_t> features;
+  for (size_t i = 0; i < task_.feature_descriptions.size(); i++)
+    features.push_back(i);
+
+  for (int i = 0; i < *task_.feature_subset_size; i++) {
+    // Pick an element from |i| to the end of the list, inclusive.
+    // TODO(liberato): For tests, this will happen before any rng is provided
+    // by the test; we'll use an actual rng.
+    int r = rng()->Generate(features.size() - i) + i;
+    // Swap them.
+    std::swap(features[i], features[r]);
+  }
+
+  // Construct the feature subset from the first few elements.  Also adjust the
+  // task's descriptions to match.  We do this in two steps so that the
+  // descriptions are added via iterating over |feature_indices_|, so that the
+  // enumeration order is the same as when we adjust the feature values of
+  // incoming examples.  In both cases, we iterate over |feature_indicies_|,
+  // which might (will) re-order them with respect to |features|.
+  for (int i = 0; i < *task_.feature_subset_size; i++)
+    feature_indices_.insert(features[i]);
+
+  std::vector<LearningTask::ValueDescription> adjusted_descriptions;
+  for (auto& iter : feature_indices_)
+    adjusted_descriptions.push_back(task_.feature_descriptions[iter]);
+
+  task_.feature_descriptions = adjusted_descriptions;
+
+  reporter_->SetFeatureSubset(feature_indices_);
+}
+
 }  // namespace learning
 }  // namespace media
diff --git a/media/learning/impl/learning_task_controller_impl.h b/media/learning/impl/learning_task_controller_impl.h
index 8de3bc6..86f007baf 100644
--- a/media/learning/impl/learning_task_controller_impl.h
+++ b/media/learning/impl/learning_task_controller_impl.h
@@ -6,6 +6,7 @@
 #define MEDIA_LEARNING_IMPL_LEARNING_TASK_CONTROLLER_IMPL_H_
 
 #include <memory>
+#include <set>
 
 #include "base/callback.h"
 #include "base/component_export.h"
@@ -59,6 +60,9 @@
 
   void SetTrainerForTesting(std::unique_ptr<TrainingAlgorithm> trainer);
 
+  // Update |task_| to reflect a randomly chosen subset of features.
+  void DoFeatureSubsetSelection();
+
   LearningTask task_;
 
   // Current batch of examples.
@@ -83,6 +87,10 @@
   // Helper that we use to handle deferred examples.
   std::unique_ptr<LearningTaskControllerHelper> helper_;
 
+  // If the task specifies feature importance measurement, then this is the
+  // randomly chosen subset of features.
+  std::set<int> feature_indices_;
+
   friend class LearningTaskControllerImplTest;
 };
 
diff --git a/media/learning/impl/learning_task_controller_impl_unittest.cc b/media/learning/impl/learning_task_controller_impl_unittest.cc
index 4ddb3065..5c05b0a 100644
--- a/media/learning/impl/learning_task_controller_impl_unittest.cc
+++ b/media/learning/impl/learning_task_controller_impl_unittest.cc
@@ -22,6 +22,11 @@
     FakeDistributionReporter(const LearningTask& task)
         : DistributionReporter(task) {}
 
+    // protected => public
+    const base::Optional<std::set<int>>& feature_indices() const {
+      return DistributionReporter::feature_indices();
+    }
+
    protected:
     void OnPrediction(TargetDistribution observed,
                       TargetDistribution predicted) override {
@@ -64,14 +69,18 @@
     void Train(const LearningTask& task,
                const TrainingData& training_data,
                TrainedModelCB model_cb) override {
+      task_ = task;
       (*num_models_)++;
       training_data_ = training_data;
       std::move(model_cb).Run(std::make_unique<FakeModel>(target_value_));
     }
 
+    const LearningTask& task() const { return task_; }
+
     const TrainingData& training_data() const { return training_data_; }
 
    private:
+    LearningTask task_;
     int* num_models_ = nullptr;
     TargetValue target_value_;
 
@@ -195,5 +204,50 @@
   EXPECT_EQ(trainer_raw_->training_data()[0].weight, example.weight);
 }
 
+TEST_F(LearningTaskControllerImplTest, FeatureSubsetsWork) {
+  const char* feature_names[] = {
+      "feature0", "feature1", "feature2", "feature3", "feature4",  "feature5",
+      "feature6", "feature7", "feature8", "feature9", "feature10", "feature11",
+  };
+  const int num_features = sizeof(feature_names) / sizeof(feature_names[0]);
+  for (int i = 0; i < num_features; i++)
+    task_.feature_descriptions.push_back({feature_names[i]});
+  const size_t subset_size = 4;
+  task_.feature_subset_size = subset_size;
+  CreateController();
+
+  // Verify that the reporter is given a subset of the features.
+  auto subset = *reporter_raw_->feature_indices();
+  EXPECT_EQ(subset.size(), subset_size);
+
+  // Train a model.  Each feature will have a unique value.
+  LabelledExample example;
+  for (int i = 0; i < num_features; i++)
+    example.features.push_back(FeatureValue(i));
+  AddExample(example);
+
+  // Verify that all feature names in |subset| are present in the task.
+  FeatureVector expected_features;
+  expected_features.resize(subset_size);
+  EXPECT_EQ(trainer_raw_->task().feature_descriptions.size(), subset_size);
+  for (auto& iter : subset) {
+    bool found = false;
+    for (size_t i = 0; i < subset_size; i++) {
+      if (trainer_raw_->task().feature_descriptions[i].name ==
+          feature_names[iter]) {
+        // Also build a vector with the features in the expected order.
+        expected_features[i] = example.features[iter];
+        found = true;
+        break;
+      }
+    }
+    EXPECT_TRUE(found);
+  }
+
+  // Verify that the training data has the adjusted features.
+  EXPECT_EQ(trainer_raw_->training_data().size(), 1u);
+  EXPECT_EQ(trainer_raw_->training_data()[0].features, expected_features);
+}
+
 }  // namespace learning
 }  // namespace media
diff --git a/media/learning/mojo/BUILD.gn b/media/learning/mojo/BUILD.gn
index 624908cc..d8c92955 100644
--- a/media/learning/mojo/BUILD.gn
+++ b/media/learning/mojo/BUILD.gn
@@ -8,7 +8,8 @@
 component("impl") {
   output_name = "media_learning_mojo_impl"
   sources = [
-    "dummy.cc",
+    "mojo_learning_task_controller_service.cc",
+    "mojo_learning_task_controller_service.h",
   ]
 
   defines = [ "IS_MEDIA_LEARNING_MOJO_IMPL" ]
@@ -33,7 +34,9 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = []
+  sources = [
+    "mojo_learning_task_controller_service_unittest.cc",
+  ]
 
   deps = [
     ":impl",
diff --git a/media/learning/mojo/dummy.cc b/media/learning/mojo/dummy.cc
deleted file mode 100644
index 0a1d331..0000000
--- a/media/learning/mojo/dummy.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2019 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.
-
-// Because mac requires a non-empty .a, and removing the component requires
-// quite a bit more fiddling with other gn files.  Since there will be new
-// things in this directory very shortly, it's much easier just to add this.
-void media_learning_mojo_do_nothing() {}
diff --git a/media/learning/mojo/mojo_learning_task_controller_service.cc b/media/learning/mojo/mojo_learning_task_controller_service.cc
new file mode 100644
index 0000000..acd3f31
--- /dev/null
+++ b/media/learning/mojo/mojo_learning_task_controller_service.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 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 "media/learning/mojo/mojo_learning_task_controller_service.h"
+
+#include <utility>
+
+#include "media/learning/common/learning_task_controller.h"
+
+namespace media {
+namespace learning {
+
+// Somewhat arbitrary upper limit on the number of in-flight observations that
+// we'll allow a client to have.
+static const size_t kMaxInFlightObservations = 16;
+
+MojoLearningTaskControllerService::MojoLearningTaskControllerService(
+    const LearningTask& task,
+    std::unique_ptr<::media::learning::LearningTaskController> impl)
+    : task_(task), impl_(std::move(impl)) {}
+
+MojoLearningTaskControllerService::~MojoLearningTaskControllerService() =
+    default;
+
+void MojoLearningTaskControllerService::BeginObservation(
+    const base::UnguessableToken& id,
+    const FeatureVector& features) {
+  // Drop the observation if it doesn't match the feature description size.
+  if (features.size() != task_.feature_descriptions.size())
+    return;
+
+  // Don't allow the client to send too many in-flight observations.
+  if (in_flight_observations_.size() >= kMaxInFlightObservations)
+    return;
+  in_flight_observations_.insert(id);
+
+  // Since we own |impl_|, we don't need to keep track of in-flight
+  // observations.  We'll release |impl_| on destruction, which cancels them.
+  impl_->BeginObservation(id, features);
+}
+
+void MojoLearningTaskControllerService::CompleteObservation(
+    const base::UnguessableToken& id,
+    const ObservationCompletion& completion) {
+  auto iter = in_flight_observations_.find(id);
+  if (iter == in_flight_observations_.end())
+    return;
+  in_flight_observations_.erase(iter);
+
+  impl_->CompleteObservation(id, completion);
+}
+
+void MojoLearningTaskControllerService::CancelObservation(
+    const base::UnguessableToken& id) {
+  auto iter = in_flight_observations_.find(id);
+  if (iter == in_flight_observations_.end())
+    return;
+  in_flight_observations_.erase(iter);
+
+  impl_->CancelObservation(id);
+}
+
+}  // namespace learning
+}  // namespace media
diff --git a/media/learning/mojo/mojo_learning_task_controller_service.h b/media/learning/mojo/mojo_learning_task_controller_service.h
new file mode 100644
index 0000000..cdf8721
--- /dev/null
+++ b/media/learning/mojo/mojo_learning_task_controller_service.h
@@ -0,0 +1,51 @@
+// Copyright 2018 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 MEDIA_LEARNING_MOJO_MOJO_LEARNING_TASK_CONTROLLER_SERVICE_H_
+#define MEDIA_LEARNING_MOJO_MOJO_LEARNING_TASK_CONTROLLER_SERVICE_H_
+
+#include <memory>
+#include <set>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "media/learning/mojo/public/mojom/learning_task_controller.mojom.h"
+
+namespace media {
+namespace learning {
+
+class LearningTaskController;
+
+// Mojo service that talks to a local LearningTaskController.
+class COMPONENT_EXPORT(MEDIA_LEARNING_MOJO) MojoLearningTaskControllerService
+    : public mojom::LearningTaskController {
+ public:
+  // |impl| is the underlying controller that we'll send requests to.
+  explicit MojoLearningTaskControllerService(
+      const LearningTask& task,
+      std::unique_ptr<::media::learning::LearningTaskController> impl);
+  ~MojoLearningTaskControllerService() override;
+
+  // mojom::LearningTaskController
+  void BeginObservation(const base::UnguessableToken& id,
+                        const FeatureVector& features) override;
+  void CompleteObservation(const base::UnguessableToken& id,
+                           const ObservationCompletion& completion) override;
+  void CancelObservation(const base::UnguessableToken& id) override;
+
+ protected:
+  const LearningTask task_;
+
+  // Underlying controller to which we proxy calls.
+  std::unique_ptr<::media::learning::LearningTaskController> impl_;
+
+  std::set<base::UnguessableToken> in_flight_observations_;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoLearningTaskControllerService);
+};
+
+}  // namespace learning
+}  // namespace media
+
+#endif  // MEDIA_LEARNING_MOJO_MOJO_LEARNING_TASK_CONTROLLER_SERVICE_H_
diff --git a/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc b/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc
new file mode 100644
index 0000000..99e8a391
--- /dev/null
+++ b/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc
@@ -0,0 +1,143 @@
+// Copyright 2019 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 <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread.h"
+#include "media/learning/mojo/mojo_learning_task_controller_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace learning {
+
+class MojoLearningTaskControllerServiceTest : public ::testing::Test {
+ public:
+  class FakeLearningTaskController : public LearningTaskController {
+   public:
+    void BeginObservation(base::UnguessableToken id,
+                          const FeatureVector& features) override {
+      begin_args_.id_ = id;
+      begin_args_.features_ = features;
+    }
+
+    void CompleteObservation(base::UnguessableToken id,
+                             const ObservationCompletion& completion) override {
+      complete_args_.id_ = id;
+      complete_args_.completion_ = completion;
+    }
+
+    void CancelObservation(base::UnguessableToken id) override {
+      cancel_args_.id_ = id;
+    }
+
+    struct {
+      base::UnguessableToken id_;
+      FeatureVector features_;
+    } begin_args_;
+
+    struct {
+      base::UnguessableToken id_;
+      ObservationCompletion completion_;
+    } complete_args_;
+
+    struct {
+      base::UnguessableToken id_;
+    } cancel_args_;
+  };
+
+ public:
+  MojoLearningTaskControllerServiceTest() = default;
+  ~MojoLearningTaskControllerServiceTest() override = default;
+
+  void SetUp() override {
+    std::unique_ptr<FakeLearningTaskController> controller =
+        std::make_unique<FakeLearningTaskController>();
+    controller_raw_ = controller.get();
+
+    // Add two features.
+    task_.feature_descriptions.push_back({});
+    task_.feature_descriptions.push_back({});
+
+    // Tell |learning_controller_| to forward to the fake learner impl.
+    service_ = std::make_unique<MojoLearningTaskControllerService>(
+        task_, std::move(controller));
+  }
+
+  LearningTask task_;
+
+  // Mojo stuff.
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  FakeLearningTaskController* controller_raw_ = nullptr;
+
+  // The learner under test.
+  std::unique_ptr<MojoLearningTaskControllerService> service_;
+};
+
+TEST_F(MojoLearningTaskControllerServiceTest, BeginComplete) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  FeatureVector features = {FeatureValue(123), FeatureValue(456)};
+  service_->BeginObservation(id, features);
+  EXPECT_EQ(id, controller_raw_->begin_args_.id_);
+  EXPECT_EQ(features, controller_raw_->begin_args_.features_);
+
+  ObservationCompletion completion(TargetValue(1234));
+  service_->CompleteObservation(id, completion);
+
+  EXPECT_EQ(id, controller_raw_->complete_args_.id_);
+  EXPECT_EQ(completion.target_value,
+            controller_raw_->complete_args_.completion_.target_value);
+}
+
+TEST_F(MojoLearningTaskControllerServiceTest, BeginCancel) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  FeatureVector features = {FeatureValue(123), FeatureValue(456)};
+  service_->BeginObservation(id, features);
+  EXPECT_EQ(id, controller_raw_->begin_args_.id_);
+  EXPECT_EQ(features, controller_raw_->begin_args_.features_);
+
+  service_->CancelObservation(id);
+
+  EXPECT_EQ(id, controller_raw_->cancel_args_.id_);
+}
+
+TEST_F(MojoLearningTaskControllerServiceTest, TooFewFeaturesIsIgnored) {
+  // A FeatureVector with too few elements should be ignored.
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  FeatureVector short_features = {FeatureValue(123)};
+  service_->BeginObservation(id, short_features);
+  EXPECT_NE(id, controller_raw_->begin_args_.id_);
+  EXPECT_EQ(controller_raw_->begin_args_.features_.size(), 0u);
+}
+
+TEST_F(MojoLearningTaskControllerServiceTest, TooManyFeaturesIsIgnored) {
+  // A FeatureVector with too many elements should be ignored.
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  FeatureVector long_features = {FeatureValue(123), FeatureValue(456),
+                                 FeatureValue(789)};
+  service_->BeginObservation(id, long_features);
+  EXPECT_NE(id, controller_raw_->begin_args_.id_);
+  EXPECT_EQ(controller_raw_->begin_args_.features_.size(), 0u);
+}
+
+TEST_F(MojoLearningTaskControllerServiceTest, CompleteWithoutBeginFails) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  ObservationCompletion completion(TargetValue(1234));
+  service_->CompleteObservation(id, completion);
+  EXPECT_NE(id, controller_raw_->complete_args_.id_);
+}
+
+TEST_F(MojoLearningTaskControllerServiceTest, CancelWithoutBeginFails) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  service_->CancelObservation(id);
+  EXPECT_NE(id, controller_raw_->cancel_args_.id_);
+}
+
+}  // namespace learning
+}  // namespace media
diff --git a/media/learning/mojo/public/cpp/BUILD.gn b/media/learning/mojo/public/cpp/BUILD.gn
index 3b0507e43..ce6b135 100644
--- a/media/learning/mojo/public/cpp/BUILD.gn
+++ b/media/learning/mojo/public/cpp/BUILD.gn
@@ -8,6 +8,11 @@
     "//media/learning/mojo/public/cpp:unit_tests",
   ]
 
+  sources = [
+    "mojo_learning_task_controller.cc",
+    "mojo_learning_task_controller.h",
+  ]
+
   defines = [ "IS_MEDIA_LEARNING_MOJO_IMPL" ]
 
   deps = [
@@ -20,6 +25,10 @@
 source_set("unit_tests") {
   testonly = true
 
+  sources = [
+    "mojo_learning_task_controller_unittest.cc",
+  ]
+
   deps = [
     "//base",
     "//base/test:test_support",
diff --git a/media/learning/mojo/public/cpp/learning_mojom_traits.cc b/media/learning/mojo/public/cpp/learning_mojom_traits.cc
index aa308d9d..12841f9 100644
--- a/media/learning/mojo/public/cpp/learning_mojom_traits.cc
+++ b/media/learning/mojo/public/cpp/learning_mojom_traits.cc
@@ -39,4 +39,14 @@
   return true;
 }
 
+// static
+bool StructTraits<media::learning::mojom::ObservationCompletionDataView,
+                  media::learning::ObservationCompletion>::
+    Read(media::learning::mojom::ObservationCompletionDataView data,
+         media::learning::ObservationCompletion* out_observation_completion) {
+  if (!data.ReadTargetValue(&out_observation_completion->target_value))
+    return false;
+  out_observation_completion->weight = data.weight();
+  return true;
+}
 }  // namespace mojo
diff --git a/media/learning/mojo/public/cpp/learning_mojom_traits.h b/media/learning/mojo/public/cpp/learning_mojom_traits.h
index 932a5cb7d..52f8ed5a 100644
--- a/media/learning/mojo/public/cpp/learning_mojom_traits.h
+++ b/media/learning/mojo/public/cpp/learning_mojom_traits.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include "media/learning/common/learning_task_controller.h"
 #include "media/learning/common/value.h"
 #include "media/learning/mojo/public/mojom/learning_types.mojom.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
@@ -52,6 +53,23 @@
                    media::learning::TargetValue* out_target_value);
 };
 
+template <>
+class StructTraits<media::learning::mojom::ObservationCompletionDataView,
+                   media::learning::ObservationCompletion> {
+ public:
+  static media::learning::TargetValue target_value(
+      const media::learning::ObservationCompletion& e) {
+    return e.target_value;
+  }
+  static media::learning::WeightType weight(
+      const media::learning::ObservationCompletion& e) {
+    return e.weight;
+  }
+  static bool Read(
+      media::learning::mojom::ObservationCompletionDataView data,
+      media::learning::ObservationCompletion* out_observation_completion);
+};
+
 }  // namespace mojo
 
 #endif  // MEDIA_LEARNING_MOJO_PUBLIC_CPP_LEARNING_MOJOM_TRAITS_H_
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc b/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc
new file mode 100644
index 0000000..f4648b3
--- /dev/null
+++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc
@@ -0,0 +1,39 @@
+// Copyright 2019 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 "media/learning/mojo/public/cpp/mojo_learning_task_controller.h"
+
+#include <utility>
+
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace media {
+namespace learning {
+
+MojoLearningTaskController::MojoLearningTaskController(
+    mojom::LearningTaskControllerPtr controller_ptr)
+    : controller_ptr_(std::move(controller_ptr)) {}
+
+MojoLearningTaskController::~MojoLearningTaskController() = default;
+
+void MojoLearningTaskController::BeginObservation(
+    base::UnguessableToken id,
+    const FeatureVector& features) {
+  // We don't need to keep track of in-flight observations, since the service
+  // side handles it for us.
+  controller_ptr_->BeginObservation(id, features);
+}
+
+void MojoLearningTaskController::CompleteObservation(
+    base::UnguessableToken id,
+    const ObservationCompletion& completion) {
+  controller_ptr_->CompleteObservation(id, completion);
+}
+
+void MojoLearningTaskController::CancelObservation(base::UnguessableToken id) {
+  controller_ptr_->CancelObservation(id);
+}
+
+}  // namespace learning
+}  // namespace media
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller.h b/media/learning/mojo/public/cpp/mojo_learning_task_controller.h
new file mode 100644
index 0000000..893d1f0
--- /dev/null
+++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller.h
@@ -0,0 +1,42 @@
+// Copyright 2019 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 MEDIA_LEARNING_MOJO_PUBLIC_CPP_MOJO_LEARNING_TASK_CONTROLLER_H_
+#define MEDIA_LEARNING_MOJO_PUBLIC_CPP_MOJO_LEARNING_TASK_CONTROLLER_H_
+
+#include <utility>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "media/learning/common/learning_task_controller.h"
+#include "media/learning/mojo/public/mojom/learning_task_controller.mojom.h"
+
+namespace media {
+namespace learning {
+
+// LearningTaskController implementation to forward to a remote impl via mojo.
+class COMPONENT_EXPORT(MEDIA_LEARNING_MOJO) MojoLearningTaskController
+    : public LearningTaskController {
+ public:
+  explicit MojoLearningTaskController(
+      mojom::LearningTaskControllerPtr controller_ptr);
+  ~MojoLearningTaskController() override;
+
+  // LearningTaskController
+  void BeginObservation(base::UnguessableToken id,
+                        const FeatureVector& features) override;
+  void CompleteObservation(base::UnguessableToken id,
+                           const ObservationCompletion& completion) override;
+  void CancelObservation(base::UnguessableToken id) override;
+
+ private:
+  mojom::LearningTaskControllerPtr controller_ptr_;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoLearningTaskController);
+};
+
+}  // namespace learning
+}  // namespace media
+
+#endif  // MEDIA_LEARNING_MOJO_PUBLIC_CPP_MOJO_LEARNING_TASK_CONTROLLER_H_
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc b/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc
new file mode 100644
index 0000000..546aae1
--- /dev/null
+++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright 2019 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 <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread.h"
+#include "media/learning/mojo/public/cpp/mojo_learning_task_controller.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace learning {
+
+class MojoLearningTaskControllerTest : public ::testing::Test {
+ public:
+  // Impl of a mojom::LearningTaskController that remembers call arguments.
+  class FakeMojoLearningTaskController : public mojom::LearningTaskController {
+   public:
+    void BeginObservation(const base::UnguessableToken& id,
+                          const FeatureVector& features) override {
+      begin_args_.id_ = id;
+      begin_args_.features_ = features;
+    }
+
+    void CompleteObservation(const base::UnguessableToken& id,
+                             const ObservationCompletion& completion) override {
+      complete_args_.id_ = id;
+      complete_args_.completion_ = completion;
+    }
+
+    void CancelObservation(const base::UnguessableToken& id) override {
+      cancel_args_.id_ = id;
+    }
+
+    struct {
+      base::UnguessableToken id_;
+      FeatureVector features_;
+    } begin_args_;
+
+    struct {
+      base::UnguessableToken id_;
+      ObservationCompletion completion_;
+    } complete_args_;
+
+    struct {
+      base::UnguessableToken id_;
+    } cancel_args_;
+  };
+
+ public:
+  MojoLearningTaskControllerTest()
+      : learning_controller_binding_(&fake_learning_controller_) {}
+  ~MojoLearningTaskControllerTest() override = default;
+
+  void SetUp() override {
+    // Create a fake learner provider mojo impl.
+    mojom::LearningTaskControllerPtr learning_controller_ptr;
+    learning_controller_binding_.Bind(
+        mojo::MakeRequest(&learning_controller_ptr));
+
+    // Tell |learning_controller_| to forward to the fake learner impl.
+    learning_controller_ = std::make_unique<MojoLearningTaskController>(
+        std::move(learning_controller_ptr));
+  }
+
+  // Mojo stuff.
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  FakeMojoLearningTaskController fake_learning_controller_;
+  mojo::Binding<mojom::LearningTaskController> learning_controller_binding_;
+
+  // The learner under test.
+  std::unique_ptr<MojoLearningTaskController> learning_controller_;
+};
+
+TEST_F(MojoLearningTaskControllerTest, Begin) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  FeatureVector features = {FeatureValue(123), FeatureValue(456)};
+  learning_controller_->BeginObservation(id, features);
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_EQ(id, fake_learning_controller_.begin_args_.id_);
+  EXPECT_EQ(features, fake_learning_controller_.begin_args_.features_);
+}
+
+TEST_F(MojoLearningTaskControllerTest, Complete) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  ObservationCompletion completion(TargetValue(1234));
+  learning_controller_->CompleteObservation(id, completion);
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_EQ(id, fake_learning_controller_.complete_args_.id_);
+  EXPECT_EQ(completion.target_value,
+            fake_learning_controller_.complete_args_.completion_.target_value);
+}
+
+TEST_F(MojoLearningTaskControllerTest, Cancel) {
+  base::UnguessableToken id = base::UnguessableToken::Create();
+  learning_controller_->CancelObservation(id);
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_EQ(id, fake_learning_controller_.cancel_args_.id_);
+}
+
+}  // namespace learning
+}  // namespace media
diff --git a/media/learning/mojo/public/mojom/BUILD.gn b/media/learning/mojo/public/mojom/BUILD.gn
index e029235..3d0a1f5 100644
--- a/media/learning/mojo/public/mojom/BUILD.gn
+++ b/media/learning/mojo/public/mojom/BUILD.gn
@@ -7,7 +7,7 @@
 
 mojom("mojom") {
   sources = [
-    "learning_session.mojom",
+    "learning_task_controller.mojom",
     "learning_types.mojom",
   ]
 
diff --git a/media/learning/mojo/public/mojom/learning_session.mojom b/media/learning/mojo/public/mojom/learning_session.mojom
deleted file mode 100644
index f7a2b1d7..0000000
--- a/media/learning/mojo/public/mojom/learning_session.mojom
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 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.
-
-module media.learning.mojom;
-
-import "media/learning/mojo/public/mojom/learning_types.mojom";
-
-// Learning tasks, to prevent sending the task name string in AcquireLearner.
-enum LearningTaskType {
-  // There are no tasks yet.
-  kPlaceHolderTask,
-};
-
-// media/learning/public/learning_session.h
-interface LearningSession {
-  // Add |example| to |task_type|.
-  AddExample(LearningTaskType task_type, LabelledExample example);
-};
diff --git a/media/learning/mojo/public/mojom/learning_task_controller.mojom b/media/learning/mojo/public/mojom/learning_task_controller.mojom
new file mode 100644
index 0000000..8fb3135
--- /dev/null
+++ b/media/learning/mojo/public/mojom/learning_task_controller.mojom
@@ -0,0 +1,36 @@
+// Copyright 2019 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.
+
+module media.learning.mojom;
+
+import "mojo/public/mojom/base/unguessable_token.mojom";
+import "media/learning/mojo/public/mojom/learning_types.mojom";
+
+// Client for a single learning task.  Intended to be the primary API for client
+// code that generates FeatureVectors / requests predictions for a single task.
+// The API supports sending in an observed FeatureVector without a target value,
+// so that framework-provided features (FeatureProvider) can be snapshotted at
+// the right time.  One doesn't generally want to wait until the TargetValue is
+// observed to do that.
+//
+// Typically, this interface will allow non-browser processes to communicate
+// with the learning framework in the browser.
+interface LearningTaskController {
+  // Start a new observation.  Call this at the time one would try to predict
+  // the TargetValue.  This lets the framework snapshot any framework-provided
+  // feature values at prediction time.  Later, if you want to turn these
+  // features into an example for training a model, then call
+  // CompleteObservation with the same id and an ObservationCompletion.
+  // Otherwise, call CancelObservation with |id|.  It's also okay to destroy the
+  // controller with outstanding observations; these will be cancelled.
+  BeginObservation(mojo_base.mojom.UnguessableToken id,
+          array<FeatureValue> features);
+
+  // Complete observation |id| by providing |completion|.
+  CompleteObservation(mojo_base.mojom.UnguessableToken id,
+          ObservationCompletion completion);
+
+  // Cancel observation |id|.  Deleting |this| will do the same.
+  CancelObservation(mojo_base.mojom.UnguessableToken id);
+};
diff --git a/media/learning/mojo/public/mojom/learning_types.mojom b/media/learning/mojo/public/mojom/learning_types.mojom
index 9a51bd970..cc4691852 100644
--- a/media/learning/mojo/public/mojom/learning_types.mojom
+++ b/media/learning/mojo/public/mojom/learning_types.mojom
@@ -19,3 +19,9 @@
   array<FeatureValue> features;
   TargetValue target_value;
 };
+
+// learning::ObservationCompletion (common/learning_task_controller.h)
+struct ObservationCompletion {
+  TargetValue target_value;
+  uint64 weight = 1;
+};
diff --git a/media/learning/mojo/public/mojom/learning_types.typemap b/media/learning/mojo/public/mojom/learning_types.typemap
index 4e6a27b..beaf1467 100644
--- a/media/learning/mojo/public/mojom/learning_types.typemap
+++ b/media/learning/mojo/public/mojom/learning_types.typemap
@@ -1,6 +1,7 @@
 mojom = "//media/learning/mojo/public/mojom/learning_types.mojom"
 public_headers = [
   "//media/learning/common/labelled_example.h",
+  "//media/learning/common/learning_task_controller.h",
   "//media/learning/common/value.h",
 ]
 traits_headers = [ "//media/learning/mojo/public/cpp/learning_mojom_traits.h" ]
@@ -15,4 +16,5 @@
   "media.learning.mojom.LabelledExample=media::learning::LabelledExample",
   "media.learning.mojom.FeatureValue=media::learning::FeatureValue",
   "media.learning.mojom.TargetValue=media::learning::TargetValue",
+  "media.learning.mojom.ObservationCompletion=media::learning::ObservationCompletion",
 ]
diff --git a/media/mojo/clients/BUILD.gn b/media/mojo/clients/BUILD.gn
index ab24a49f..d64d3d9 100644
--- a/media/mojo/clients/BUILD.gn
+++ b/media/mojo/clients/BUILD.gn
@@ -48,6 +48,8 @@
     "mojo_renderer.h",
     "mojo_renderer_factory.cc",
     "mojo_renderer_factory.h",
+    "mojo_renderer_wrapper.cc",
+    "mojo_renderer_wrapper.h",
     "mojo_video_decoder.cc",
     "mojo_video_decoder.h",
     "mojo_video_encode_accelerator.cc",
diff --git a/media/mojo/clients/mojo_renderer_wrapper.cc b/media/mojo/clients/mojo_renderer_wrapper.cc
new file mode 100644
index 0000000..2fa912ff
--- /dev/null
+++ b/media/mojo/clients/mojo_renderer_wrapper.cc
@@ -0,0 +1,48 @@
+// Copyright 2019 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 "media/mojo/clients/mojo_renderer_wrapper.h"
+
+#include <utility>
+
+namespace media {
+
+MojoRendererWrapper::MojoRendererWrapper(
+    std::unique_ptr<MojoRenderer> mojo_renderer)
+    : mojo_renderer_(std::move(mojo_renderer)) {}
+
+MojoRendererWrapper::~MojoRendererWrapper() = default;
+
+void MojoRendererWrapper::Initialize(media::MediaResource* media_resource,
+                                     media::RendererClient* client,
+                                     const media::PipelineStatusCB& init_cb) {
+  mojo_renderer_->Initialize(media_resource, client, init_cb);
+}
+
+void MojoRendererWrapper::Flush(const base::Closure& flush_cb) {
+  mojo_renderer_->Flush(flush_cb);
+}
+
+void MojoRendererWrapper::StartPlayingFrom(base::TimeDelta time) {
+  mojo_renderer_->StartPlayingFrom(time);
+}
+
+void MojoRendererWrapper::SetPlaybackRate(double playback_rate) {
+  mojo_renderer_->SetPlaybackRate(playback_rate);
+}
+
+void MojoRendererWrapper::SetVolume(float volume) {
+  mojo_renderer_->SetVolume(volume);
+}
+
+void MojoRendererWrapper::SetCdm(media::CdmContext* cdm_context,
+                                 const media::CdmAttachedCB& cdm_attached_cb) {
+  mojo_renderer_->SetCdm(cdm_context, cdm_attached_cb);
+}
+
+base::TimeDelta MojoRendererWrapper::GetMediaTime() {
+  return mojo_renderer_->GetMediaTime();
+}
+
+}  // namespace media
diff --git a/media/mojo/clients/mojo_renderer_wrapper.h b/media/mojo/clients/mojo_renderer_wrapper.h
new file mode 100644
index 0000000..087cd5e
--- /dev/null
+++ b/media/mojo/clients/mojo_renderer_wrapper.h
@@ -0,0 +1,45 @@
+// Copyright 2019 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 MEDIA_MOJO_CLIENTS_MOJO_RENDERER_WRAPPER_H_
+#define MEDIA_MOJO_CLIENTS_MOJO_RENDERER_WRAPPER_H_
+
+#include <memory>
+
+#include "media/base/renderer.h"
+#include "media/mojo/clients/mojo_renderer.h"
+
+namespace media {
+
+// Simple wrapper around a MojoRenderer.
+// Provides a default behavior for forwarding all media::Renderer calls to a
+// media::Renderer instance in a different process, through |mojo_renderer_|.
+// Used as a base class to reduce boiler plate code for derived types, which can
+// override only the methods they need to specialize.
+class MojoRendererWrapper : public Renderer {
+ public:
+  explicit MojoRendererWrapper(std::unique_ptr<MojoRenderer> mojo_renderer);
+  ~MojoRendererWrapper() override;
+
+  // Renderer implementation.
+  void Initialize(MediaResource* media_resource,
+                  media::RendererClient* client,
+                  const PipelineStatusCB& init_cb) override;
+  void SetCdm(CdmContext* cdm_context,
+              const CdmAttachedCB& cdm_attached_cb) override;
+  void Flush(const base::Closure& flush_cb) override;
+  void StartPlayingFrom(base::TimeDelta time) override;
+  void SetPlaybackRate(double playback_rate) override;
+  void SetVolume(float volume) override;
+  base::TimeDelta GetMediaTime() override;
+
+ private:
+  std::unique_ptr<MojoRenderer> mojo_renderer_;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoRendererWrapper);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_MOJO_CLIENTS_MOJO_RENDERER_WRAPPER_H_
diff --git a/net/cookies/cookie_monster_store_test.h b/net/cookies/cookie_monster_store_test.h
index c85c0eb..33f963b 100644
--- a/net/cookies/cookie_monster_store_test.h
+++ b/net/cookies/cookie_monster_store_test.h
@@ -89,6 +89,7 @@
                           std::vector<std::unique_ptr<CanonicalCookie>> result);
 
   const CommandList& commands() const { return commands_; }
+  CommandList TakeCommands() { return std::move(commands_); }
 
   void Load(const LoadedCallback& loaded_callback,
             const NetLogWithSource& net_log) override;
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 0d5c43e..0e3e8a5a 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -25,6 +25,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/threading/thread.h"
@@ -57,32 +58,6 @@
 
 namespace {
 
-// TODO(erikwright): Replace the pre-existing MockPersistentCookieStore (and
-// brethren) with this one, and remove the 'New' prefix.
-class NewMockPersistentCookieStore
-    : public CookieMonster::PersistentCookieStore {
- public:
-  MOCK_METHOD2(Load,
-               void(const LoadedCallback& loaded_callback,
-                    const NetLogWithSource& net_log));
-  MOCK_METHOD2(LoadCookiesForKey,
-               void(const std::string& key,
-                    const LoadedCallback& loaded_callback));
-  MOCK_METHOD1(AddCookie, void(const CanonicalCookie& cc));
-  MOCK_METHOD1(UpdateCookieAccessTime, void(const CanonicalCookie& cc));
-  MOCK_METHOD1(DeleteCookie, void(const CanonicalCookie& cc));
-  MOCK_METHOD1(SetBeforeCommitCallback, void(base::RepeatingClosure));
-  void Flush(base::OnceClosure callback) override {
-    if (!callback.is_null())
-      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                    std::move(callback));
-  }
-  MOCK_METHOD0(SetForceKeepSessionState, void());
-
- private:
-  ~NewMockPersistentCookieStore() override = default;
-};
-
 // False means 'less than or equal', so we test both ways for full equal.
 MATCHER_P(CookieEquals, expected, "") {
   return !(arg.FullCompare(expected) || expected.FullCompare(arg));
@@ -874,15 +849,6 @@
 
 using CookieMonsterTest = CookieMonsterTestBase<CookieMonsterTestTraits>;
 
-// TODO(erikwright): Replace the other callbacks and synchronous helper methods
-// in this test suite with these Mocks.
-using MockClosure = base::MockCallback<base::Closure>;
-using MockSetCookiesCallback =
-    base::MockCallback<CookieStore::SetCookiesCallback>;
-using MockGetCookieListCallback =
-    base::MockCallback<CookieMonster::GetCookieListCallback>;
-using MockDeleteCallback = base::MockCallback<CookieMonster::DeleteCallback>;
-
 struct CookiesInputInfo {
   const GURL url;
   const std::string name;
@@ -896,63 +862,6 @@
   CookiePriority priority;
 };
 
-ACTION_P(QuitRunLoop, run_loop) {
-  run_loop->Quit();
-}
-
-// TODO(erikwright): When the synchronous helpers 'GetCookies' etc. are removed,
-// rename these, removing the 'Action' suffix.
-ACTION_P4(SetCookieAction, cookie_monster, url, cookie_line, callback) {
-  cookie_monster->SetCookieWithOptionsAsync(url, cookie_line, CookieOptions(),
-                                            callback->Get());
-}
-ACTION_P3(SetAllCookiesAction, cookie_monster, list, callback) {
-  cookie_monster->SetAllCookiesAsync(list, callback->Get());
-}
-ACTION_P3(DeleteAllCreatedInTimeRangeAction,
-          cookie_monster,
-          creation_range,
-          callback) {
-  cookie_monster->DeleteAllCreatedInTimeRangeAsync(creation_range,
-                                                   callback->Get());
-}
-ACTION_P2(GetAllCookiesAction, cookie_monster, callback) {
-  cookie_monster->GetAllCookiesAsync(callback->Get());
-}
-
-ACTION_P3(DeleteAllCreatedMatchingInfoAction,
-          cookie_monster,
-          delete_info,
-          callback) {
-  cookie_monster->DeleteAllMatchingInfoAsync(std::move(delete_info),
-                                             callback->Get());
-}
-
-ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) {
-  cookie_monster->DeleteCanonicalCookieAsync(cookie, callback->Get());
-}
-
-ACTION_P2(DeleteAllAction, cookie_monster, callback) {
-  cookie_monster->DeleteAllAsync(callback->Get());
-}
-
-ACTION_P3(GetCookieListForUrlWithOptionsAction, cookie_monster, url, callback) {
-  cookie_monster->GetCookieListWithOptionsAsync(url, CookieOptions(),
-                                                callback->Get());
-}
-
-ACTION_P3(GetAllCookiesForUrlAction, cookie_monster, url, callback) {
-  cookie_monster->GetAllCookiesForURLAsync(url, callback->Get());
-}
-
-ACTION_P(PushCallbackAction, callback_vector) {
-  callback_vector->push(arg1);
-}
-
-ACTION_P2(DeleteSessionCookiesAction, cookie_monster, callback) {
-  cookie_monster->DeleteSessionCookiesAsync(callback->Get());
-}
-
 }  // namespace
 
 // This test suite verifies the task deferral behaviour of the CookieMonster.
@@ -964,8 +873,9 @@
 // 3. Invocations after the loading has completed complete immediately.
 class DeferredCookieTaskTest : public CookieMonsterTest {
  protected:
-  DeferredCookieTaskTest() : expect_load_called_(false) {
-    persistent_store_ = new NewMockPersistentCookieStore();
+  DeferredCookieTaskTest() {
+    persistent_store_ = base::MakeRefCounted<MockPersistentCookieStore>();
+    persistent_store_->set_store_load_commands(true);
     cookie_monster_ =
         std::make_unique<CookieMonster>(persistent_store_.get(), &net_log_);
   }
@@ -977,88 +887,47 @@
     AddCookieToList(url, cookie_line, creation_time, &loaded_cookies_);
   }
 
-  // Runs the message loop, waiting until PersistentCookieStore::Load is called.
-  // Call CompleteLoading to cause the load to complete.
-  void WaitForLoadCall() {
-    load_run_loop_.Run();
-
-    // Verify that PeristentStore::Load was called.
-    testing::Mock::VerifyAndClear(persistent_store_.get());
-  }
-
-  // Invokes the PersistentCookieStore::LoadCookiesForKey completion callbacks
-  // and PersistentCookieStore::Load completion callback.
-  void CompleteLoading() {
-    while (!loaded_for_key_callbacks_.empty()) {
-      loaded_for_key_callbacks_.front().Run(std::move(loaded_cookies_));
-      loaded_cookies_.clear();
-      loaded_for_key_callbacks_.pop();
+  void ExecuteLoads(CookieStoreCommand::Type type) {
+    for (const auto& command : persistent_store_->commands()) {
+      // Only the first load command will produce the cookies.
+      if (command.type == type) {
+        std::move(command.loaded_callback).Run(std::move(loaded_cookies_));
+      }
     }
-    loaded_callback_.Run(std::move(loaded_cookies_));
   }
 
-  // Performs the provided action, expecting it to cause a call to
-  // PersistentCookieStore::Load. Call WaitForLoadCall to verify the load call
-  // is received.
-  void BeginWith(testing::Action<void(void)> action) {
-    EXPECT_CALL(*this, Begin()).WillOnce(action);
-    ExpectLoadCall();
-    Begin();
+  std::string CommandSummary(
+      const MockPersistentCookieStore::CommandList& commands) {
+    std::string out;
+    for (const auto& command : commands) {
+      switch (command.type) {
+        case CookieStoreCommand::LOAD:
+          base::StrAppend(&out, {"LOAD; "});
+          break;
+        case CookieStoreCommand::LOAD_COOKIES_FOR_KEY:
+          base::StrAppend(&out, {"LOAD_FOR_KEY:", command.key, "; "});
+          break;
+        case CookieStoreCommand::ADD:
+          base::StrAppend(&out, {"ADD; "});
+          break;
+        case CookieStoreCommand::REMOVE:
+          base::StrAppend(&out, {"REMOVE; "});
+          break;
+      }
+    }
+    return out;
   }
 
-  void BeginWithForDomainKey(std::string key,
-                             testing::Action<void(void)> action) {
-    EXPECT_CALL(*this, Begin()).WillOnce(action);
-    ExpectLoadCall();
-    ExpectLoadForKeyCall(key);
-    Begin();
+  std::string TakeCommandSummary() {
+    return CommandSummary(persistent_store_->TakeCommands());
   }
 
-  // Declares an expectation that PersistentCookieStore::Load will be called,
-  // saving the provided callback and sending a quit to |load_run_loop_|.
-  void ExpectLoadCall() {
-    // Make sure the |load_run_loop_| is not reused.
-    CHECK(!expect_load_called_);
-    expect_load_called_ = true;
-    EXPECT_CALL(*persistent_store_.get(), Load(testing::_, testing::_))
-        .WillOnce(testing::DoAll(testing::SaveArg<0>(&loaded_callback_),
-                                 QuitRunLoop(&load_run_loop_)));
-  }
-
-  // Declares an expectation that PersistentCookieStore::LoadCookiesForKey
-  // will be called, saving the provided callback.
-  void ExpectLoadForKeyCall(const std::string& key) {
-    EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
-        .WillOnce(PushCallbackAction(&loaded_for_key_callbacks_));
-  }
-
-  // Invokes the initial action.
-  MOCK_METHOD0(Begin, void(void));
-
-  // Returns the CookieMonster instance under test.
-  CookieMonster& cookie_monster() { return *cookie_monster_.get(); }
-
- private:
-  // Declares that mock expectations in this test suite are strictly ordered.
-  testing::InSequence in_sequence_;
   // Holds cookies to be returned from PersistentCookieStore::Load or
   // PersistentCookieStore::LoadCookiesForKey.
   std::vector<std::unique_ptr<CanonicalCookie>> loaded_cookies_;
-  // Stores the callback passed from the CookieMonster to the
-  // PersistentCookieStore::Load
-  CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback_;
-  // Stores the callback passed from the CookieMonster to the
-  // PersistentCookieStore::LoadCookiesForKey
-  base::queue<CookieMonster::PersistentCookieStore::LoadedCallback>
-      loaded_for_key_callbacks_;
-  // base::RunLoop used to wait for PersistentCookieStore::Load to be called.
-  base::RunLoop load_run_loop_;
-  // Indicates whether ExpectLoadCall() has been called.
-  bool expect_load_called_;
-  // Stores the CookieMonster under test.
+
   std::unique_ptr<CookieMonster> cookie_monster_;
-  // Stores the mock PersistentCookieStore.
-  scoped_refptr<NewMockPersistentCookieStore> persistent_store_;
+  scoped_refptr<MockPersistentCookieStore> persistent_store_;
 };
 
 TEST_F(DeferredCookieTaskTest, DeferredGetCookieList) {
@@ -1066,53 +935,57 @@
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
-  MockGetCookieListCallback get_cookie_list_callback;
+  GetCookieListCallback call1;
+  cookie_monster_->GetCookieListWithOptionsAsync(
+      http_www_foo_.url(), CookieOptions(), call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWithForDomainKey(
-      http_www_foo_.domain(),
-      GetCookieListForUrlWithOptionsAction(
-          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
+  // Finish the per-key load, not everything-load (which is always initiated).
+  ExecuteLoads(CookieStoreCommand::LOAD_COOKIES_FOR_KEY);
+  call1.WaitUntilDone();
+  EXPECT_THAT(call1.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(get_cookie_list_callback,
-              Run(MatchesCookieLine("X=1"), testing::_))
-      .WillOnce(GetCookieListForUrlWithOptionsAction(
-          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
-
-  base::RunLoop loop;
-  EXPECT_CALL(get_cookie_list_callback,
-              Run(MatchesCookieLine("X=1"), testing::_))
-      .WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  GetCookieListCallback call2;
+  cookie_monster_->GetCookieListWithOptionsAsync(
+      http_www_foo_.url(), CookieOptions(), call2.MakeCallback());
+  // Already ready, no need for second load.
+  EXPECT_THAT(call2.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
-  MockSetCookiesCallback set_cookies_callback;
+  // Generate puts to store w/o needing a proper expiration.
+  cookie_monster_->SetPersistSessionCookies(true);
 
-  BeginWithForDomainKey(http_www_foo_.domain(),
-                        SetCookieAction(&cookie_monster(), http_www_foo_.url(),
-                                        "A=B", &set_cookies_callback));
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call1;
+  cookie_monster_->SetCanonicalCookieAsync(
+      CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
+                              CookieOptions()),
+      http_www_foo_.url().scheme(), CookieOptions(), call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  WaitForLoadCall();
+  ExecuteLoads(CookieStoreCommand::LOAD_COOKIES_FOR_KEY);
+  call1.WaitUntilDone();
+  EXPECT_EQ(call1.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ADD; ", TakeCommandSummary());
 
-  EXPECT_CALL(set_cookies_callback,
-              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
-      .WillOnce(SetCookieAction(&cookie_monster(), http_www_foo_.url(), "X=Y",
-                                &set_cookies_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(set_cookies_callback,
-              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
-      .WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call2;
+  cookie_monster_->SetCanonicalCookieAsync(
+      CanonicalCookie::Create(http_www_foo_.url(), "X=Y", base::Time::Now(),
+                              CookieOptions()),
+      http_www_foo_.url().scheme(), CookieOptions(), call2.MakeCallback());
+  ASSERT_TRUE(call2.was_run());
+  EXPECT_EQ(call2.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_EQ("ADD; ", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
-  MockSetCookiesCallback set_cookies_callback;
+  // Generate puts to store w/o needing a proper expiration.
+  cookie_monster_->SetPersistSessionCookies(true);
+
   CookieList list;
   list.push_back(CanonicalCookie("A", "B", "." + http_www_foo_.domain(), "/",
                                  base::Time::Now(), base::Time(), base::Time(),
@@ -1123,22 +996,22 @@
                                  false, true, CookieSameSite::DEFAULT_MODE,
                                  COOKIE_PRIORITY_DEFAULT));
 
-  BeginWith(
-      SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call1;
+  cookie_monster_->SetAllCookiesAsync(list, call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  WaitForLoadCall();
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_EQ(call1.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_EQ("LOAD; ADD; ADD; ", TakeCommandSummary());
 
-  EXPECT_CALL(set_cookies_callback,
-              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
-      .WillOnce(
-          SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(set_cookies_callback,
-              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE))
-      .WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  // 2nd set doesn't need to read from store. It erases the old cookies, though.
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call2;
+  cookie_monster_->SetAllCookiesAsync(list, call2.MakeCallback());
+  ASSERT_TRUE(call2.was_run());
+  EXPECT_EQ(call2.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_EQ("REMOVE; REMOVE; ADD; ADD; ", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
@@ -1146,21 +1019,21 @@
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
-  MockGetCookieListCallback get_cookie_list_callback;
+  GetCookieListCallback call1;
+  cookie_monster_->GetAllCookiesAsync(call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWith(GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_THAT(call1.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("LOAD; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(get_cookie_list_callback, Run(testing::_, testing::_))
-      .WillOnce(
-          GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(get_cookie_list_callback, Run(testing::_, testing::_))
-      .WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  GetCookieListCallback call2;
+  cookie_monster_->GetAllCookiesAsync(call2.MakeCallback());
+  EXPECT_TRUE(call2.was_run());
+  EXPECT_THAT(call2.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
@@ -1168,24 +1041,23 @@
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
-  MockGetCookieListCallback get_cookie_list_callback;
+  GetCookieListCallback call1;
+  cookie_monster_->GetAllCookiesForURLAsync(http_www_foo_.url(),
+                                            call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWithForDomainKey(
-      http_www_foo_.domain(),
-      GetAllCookiesForUrlAction(&cookie_monster(), http_www_foo_.url(),
-                                &get_cookie_list_callback));
+  ExecuteLoads(CookieStoreCommand::LOAD_COOKIES_FOR_KEY);
+  call1.WaitUntilDone();
+  EXPECT_THAT(call1.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(get_cookie_list_callback, Run(testing::_, testing::_))
-      .WillOnce(GetAllCookiesForUrlAction(
-          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(get_cookie_list_callback, Run(testing::_, testing::_))
-      .WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  GetCookieListCallback call2;
+  cookie_monster_->GetAllCookiesForURLAsync(http_www_foo_.url(),
+                                            call2.MakeCallback());
+  EXPECT_TRUE(call2.was_run());
+  EXPECT_THAT(call2.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) {
@@ -1193,160 +1065,192 @@
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
-  MockGetCookieListCallback get_cookie_list_callback;
+  GetCookieListCallback call1;
+  cookie_monster_->GetCookieListWithOptionsAsync(
+      http_www_foo_.url(), CookieOptions(), call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWithForDomainKey(
-      http_www_foo_.domain(),
-      GetCookieListForUrlWithOptionsAction(
-          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
+  ExecuteLoads(CookieStoreCommand::LOAD_COOKIES_FOR_KEY);
+  call1.WaitUntilDone();
+  EXPECT_THAT(call1.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(get_cookie_list_callback, Run(testing::_, testing::_))
-      .WillOnce(GetCookieListForUrlWithOptionsAction(
-          &cookie_monster(), http_www_foo_.url(), &get_cookie_list_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(get_cookie_list_callback, Run(testing::_, testing::_))
-      .WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  GetCookieListCallback call2;
+  cookie_monster_->GetCookieListWithOptionsAsync(
+      http_www_foo_.url(), CookieOptions(), call2.MakeCallback());
+  EXPECT_TRUE(call2.was_run());
+  EXPECT_THAT(call2.cookies(), MatchesCookieLine("X=1"));
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
-  MockDeleteCallback delete_callback;
+  DeclareLoadedCookie(http_www_foo_.url(),
+                      "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
+                      Time::Now() + TimeDelta::FromDays(3));
 
-  BeginWith(DeleteAllAction(&cookie_monster(), &delete_callback));
+  ResultSavingCookieCallback<uint32_t> call1;
+  cookie_monster_->DeleteAllAsync(call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  WaitForLoadCall();
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_EQ(1u, call1.result());
+  EXPECT_EQ("LOAD; REMOVE; ", TakeCommandSummary());
 
-  EXPECT_CALL(delete_callback, Run(false))
-      .WillOnce(DeleteAllAction(&cookie_monster(), &delete_callback));
-
-  base::RunLoop loop;
-  EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  ResultSavingCookieCallback<uint32_t> call2;
+  cookie_monster_->DeleteAllAsync(call2.MakeCallback());
+  // This needs an event loop spin since DeleteAllAsync always reports
+  // asynchronously.
+  call2.WaitUntilDone();
+  EXPECT_EQ(0u, call2.result());
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedInTimeRangeCookies) {
-  MockDeleteCallback delete_callback;
-
   const TimeRange time_range(base::Time(), base::Time::Now());
-  BeginWith(DeleteAllCreatedInTimeRangeAction(&cookie_monster(), time_range,
-                                              &delete_callback));
 
-  WaitForLoadCall();
+  ResultSavingCookieCallback<uint32_t> call1;
+  cookie_monster_->DeleteAllCreatedInTimeRangeAsync(time_range,
+                                                    call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  EXPECT_CALL(delete_callback, Run(false))
-      .WillOnce(DeleteAllCreatedInTimeRangeAction(&cookie_monster(), time_range,
-                                                  &delete_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_EQ(0u, call1.result());
+  EXPECT_EQ("LOAD; ", TakeCommandSummary());
 
-  CompleteLoading();
-  loop.Run();
+  ResultSavingCookieCallback<uint32_t> call2;
+  cookie_monster_->DeleteAllCreatedInTimeRangeAsync(time_range,
+                                                    call2.MakeCallback());
+  call2.WaitUntilDone();
+  EXPECT_EQ(0u, call2.result());
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest,
        DeferredDeleteAllWithPredicateCreatedInTimeRangeCookies) {
-  MockDeleteCallback delete_callback;
+  ResultSavingCookieCallback<uint32_t> call1;
+  cookie_monster_->DeleteAllMatchingInfoAsync(
+      CookieDeletionInfo(Time(), Time::Now()), call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWith(DeleteAllCreatedMatchingInfoAction(
-      &cookie_monster(), CookieDeletionInfo(Time(), Time::Now()),
-      &delete_callback));
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_EQ(0u, call1.result());
+  EXPECT_EQ("LOAD; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(delete_callback, Run(false))
-      .WillOnce(DeleteAllCreatedMatchingInfoAction(
-          &cookie_monster(), CookieDeletionInfo(Time(), Time::Now()),
-          &delete_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  ResultSavingCookieCallback<uint32_t> call2;
+  cookie_monster_->DeleteAllMatchingInfoAsync(
+      CookieDeletionInfo(Time(), Time::Now()), call2.MakeCallback());
+  call2.WaitUntilDone();
+  EXPECT_EQ(0u, call2.result());
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
-  std::vector<std::unique_ptr<CanonicalCookie>> cookies;
   std::unique_ptr<CanonicalCookie> cookie = BuildCanonicalCookie(
       http_www_foo_.url(), "X=1; path=/", base::Time::Now());
 
-  MockDeleteCallback delete_cookie_callback;
+  ResultSavingCookieCallback<uint32_t> call1;
+  cookie_monster_->DeleteCanonicalCookieAsync(*cookie, call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWith(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
-                                        &delete_cookie_callback));
+  // TODO(morlovich): Fix DeleteCanonicalCookieAsync. This test should pass
+  // when using LOAD_COOKIES_FOR_KEY instead, with that reflected in
+  // TakeCommandSummary() as well.
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_EQ(0u, call1.result());
+  EXPECT_EQ("LOAD; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(delete_cookie_callback, Run(0))
-      .WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
-                                            &delete_cookie_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(delete_cookie_callback, Run(0)).WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  ResultSavingCookieCallback<uint32_t> call2;
+  cookie_monster_->DeleteCanonicalCookieAsync(*cookie, call2.MakeCallback());
+  call2.WaitUntilDone();
+  EXPECT_EQ(0u, call2.result());
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
-  MockDeleteCallback delete_callback;
+  ResultSavingCookieCallback<uint32_t> call1;
+  cookie_monster_->DeleteSessionCookiesAsync(call1.MakeCallback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(call1.was_run());
 
-  BeginWith(DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
+  ExecuteLoads(CookieStoreCommand::LOAD);
+  call1.WaitUntilDone();
+  EXPECT_EQ(0u, call1.result());
+  EXPECT_EQ("LOAD; ", TakeCommandSummary());
 
-  WaitForLoadCall();
-
-  EXPECT_CALL(delete_callback, Run(false))
-      .WillOnce(
-          DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
-  base::RunLoop loop;
-  EXPECT_CALL(delete_callback, Run(false)).WillOnce(QuitRunLoop(&loop));
-
-  CompleteLoading();
-  loop.Run();
+  ResultSavingCookieCallback<uint32_t> call2;
+  cookie_monster_->DeleteSessionCookiesAsync(call2.MakeCallback());
+  call2.WaitUntilDone();
+  EXPECT_EQ(0u, call2.result());
+  EXPECT_EQ("", TakeCommandSummary());
 }
 
 // Verify that a series of queued tasks are executed in order upon loading of
 // the backing store and that new tasks received while the queued tasks are
 // being dispatched go to the end of the queue.
 TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
+  cookie_monster_->SetPersistSessionCookies(true);
   DeclareLoadedCookie(http_www_foo_.url(),
                       "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
                       Time::Now() + TimeDelta::FromDays(3));
 
-  MockGetCookieListCallback get_cookie_list_callback;
-  MockSetCookiesCallback set_cookies_callback;
-  MockGetCookieListCallback get_cookie_list_callback_deferred;
+  bool get_cookie_list_callback_was_run = false;
+  GetCookieListCallback get_cookie_list_callback_deferred;
+  ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
+      set_cookies_callback;
+  base::RunLoop run_loop;
+  cookie_monster_->GetCookieListWithOptionsAsync(
+      http_www_foo_.url(), CookieOptions(),
+      base::BindLambdaForTesting([&](const CookieList& cookies,
+                                     const CookieStatusList& excluded_list) {
+        // This should complete before the set.
+        get_cookie_list_callback_was_run = true;
+        EXPECT_FALSE(set_cookies_callback.was_run());
+        EXPECT_THAT(cookies, MatchesCookieLine("X=1"));
+        // Can't use TakeCommandSummary here since ExecuteLoads is walking
+        // through the data it takes.
+        EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ",
+                  CommandSummary(persistent_store_->commands()));
 
-  EXPECT_CALL(*this, Begin())
-      .WillOnce(testing::DoAll(
-          GetCookieListForUrlWithOptionsAction(&cookie_monster(),
-                                               http_www_foo_.url(),
-                                               &get_cookie_list_callback),
-          SetCookieAction(&cookie_monster(), http_www_foo_.url(), "A=B",
-                          &set_cookies_callback)));
-  ExpectLoadCall();
-  ExpectLoadForKeyCall(http_www_foo_.domain());
-  Begin();
+        // Queue up a second get. It should see the result of the set queued
+        // before it.
+        cookie_monster_->GetCookieListWithOptionsAsync(
+            http_www_foo_.url(), CookieOptions(),
+            get_cookie_list_callback_deferred.MakeCallback());
 
-  WaitForLoadCall();
-  EXPECT_CALL(get_cookie_list_callback,
-              Run(MatchesCookieLine("X=1"), testing::_))
-      .WillOnce(GetCookieListForUrlWithOptionsAction(
-          &cookie_monster(), http_www_foo_.url(),
-          &get_cookie_list_callback_deferred));
-  EXPECT_CALL(set_cookies_callback,
-              Run(CanonicalCookie::CookieInclusionStatus::INCLUDE));
-  base::RunLoop loop;
-  EXPECT_CALL(get_cookie_list_callback_deferred,
-              Run(MatchesCookieLine("A=B; X=1"), testing::_))
-      .WillOnce(QuitRunLoop(&loop));
+        run_loop.Quit();
+      }));
 
-  CompleteLoading();
-  loop.Run();
+  cookie_monster_->SetCanonicalCookieAsync(
+      CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
+                              CookieOptions()),
+      http_www_foo_.url().scheme(), CookieOptions(),
+      set_cookies_callback.MakeCallback());
+
+  // Nothing happened yet, before loads are done.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(get_cookie_list_callback_was_run);
+  EXPECT_FALSE(set_cookies_callback.was_run());
+
+  ExecuteLoads(CookieStoreCommand::LOAD_COOKIES_FOR_KEY);
+  run_loop.Run();
+  EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ADD; ", TakeCommandSummary());
+  EXPECT_TRUE(get_cookie_list_callback_was_run);
+  ASSERT_TRUE(set_cookies_callback.was_run());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
+            set_cookies_callback.result());
+
+  ASSERT_TRUE(get_cookie_list_callback_deferred.was_run());
+  EXPECT_THAT(get_cookie_list_callback_deferred.cookies(),
+              MatchesCookieLine("A=B; X=1"));
 }
 
 TEST_F(CookieMonsterTest, TestCookieDeleteAll) {
diff --git a/net/cookies/cookie_store_test_callbacks.cc b/net/cookies/cookie_store_test_callbacks.cc
index 0cc18870..3f1136f 100644
--- a/net/cookies/cookie_store_test_callbacks.cc
+++ b/net/cookies/cookie_store_test_callbacks.cc
@@ -14,15 +14,16 @@
 namespace net {
 
 CookieCallback::CookieCallback(base::Thread* run_in_thread)
-    : run_in_thread_(run_in_thread) {}
+    : run_in_thread_(run_in_thread), was_run_(false) {}
 
 CookieCallback::CookieCallback()
     : run_in_thread_(nullptr),
-      run_in_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+      run_in_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      was_run_(false) {}
 
 CookieCallback::~CookieCallback() = default;
 
-void CookieCallback::CallbackEpilogue() {
+void CookieCallback::ValidateThread() const {
   scoped_refptr<base::SingleThreadTaskRunner> expected_task_runner;
   if (run_in_thread_) {
     DCHECK(!run_in_task_runner_);
@@ -31,8 +32,12 @@
     expected_task_runner = run_in_task_runner_;
   }
   ASSERT_TRUE(expected_task_runner);
-
   EXPECT_TRUE(expected_task_runner->BelongsToCurrentThread());
+}
+
+void CookieCallback::CallbackEpilogue() {
+  ValidateThread();
+  was_run_ = true;
   loop_to_quit_.Quit();
 }
 
@@ -40,6 +45,11 @@
   loop_to_quit_.Run();
 }
 
+bool CookieCallback::was_run() const {
+  ValidateThread();
+  return was_run_;
+}
+
 NoResultCookieCallback::NoResultCookieCallback() = default;
 NoResultCookieCallback::NoResultCookieCallback(base::Thread* run_in_thread)
     : CookieCallback(run_in_thread) {}
diff --git a/net/cookies/cookie_store_test_callbacks.h b/net/cookies/cookie_store_test_callbacks.h
index 4a5ea9e..ff9e2d2f6 100644
--- a/net/cookies/cookie_store_test_callbacks.h
+++ b/net/cookies/cookie_store_test_callbacks.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -28,6 +29,10 @@
   // Waits until the callback is invoked.
   void WaitUntilDone();
 
+  // Returns whether the callback was invoked. Should only be used on the thread
+  // the callback runs on.
+  bool was_run() const;
+
  protected:
   // Constructs a callback that expects to be called in the given thread.
   explicit CookieCallback(base::Thread* run_in_thread);
@@ -43,9 +48,12 @@
   void CallbackEpilogue();
 
  private:
+  void ValidateThread() const;
+
   base::Thread* run_in_thread_;
   scoped_refptr<base::SingleThreadTaskRunner> run_in_task_runner_;
   base::RunLoop loop_to_quit_;
+  bool was_run_;
 };
 
 // Callback implementations for the asynchronous CookieStore methods.
@@ -64,6 +72,13 @@
     CallbackEpilogue();
   }
 
+  // Makes a callback that will invoke Run. Assumes that |this| will be kept
+  // alive till the time the callback is used.
+  base::OnceCallback<void(T)> MakeCallback() {
+    return base::BindOnce(&ResultSavingCookieCallback<T>::Run,
+                          base::Unretained(this));
+  }
+
   const T& result() { return result_; }
 
  private:
@@ -89,6 +104,13 @@
 
   void Run(const CookieList& cookies, const CookieStatusList& excluded_cookies);
 
+  // Makes a callback that will invoke Run. Assumes that |this| will be kept
+  // alive till the time the callback is used.
+  base::OnceCallback<void(const CookieList&, const CookieStatusList&)>
+  MakeCallback() {
+    return base::BindOnce(&GetCookieListCallback::Run, base::Unretained(this));
+  }
+
   const CookieList& cookies() { return cookies_; }
   const CookieStatusList& excluded_cookies() { return excluded_cookies_; }
 
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 1feb128..b242b6af 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -276,6 +276,12 @@
       "expect_ct": true,
       "expect_ct_report_uri": "https://clients3.google.com/ct_upload"
     },
+    {
+      "name": "remotedesktop.corp.google.com", "policy": "google",
+      "mode": "force-https", "include_subdomains": true, "pins": "google",
+      "expect_ct": true,
+      "expect_ct_report_uri": "https://clients3.google.com/ct_upload"
+    },
 
     // Now we force HTTPS for subtrees of google.com.
     { "name": "accounts.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" },
diff --git a/ppapi/proxy/websocket_resource.cc b/ppapi/proxy/websocket_resource.cc
index 02b918e3..8c0c958b 100644
--- a/ppapi/proxy/websocket_resource.cc
+++ b/ppapi/proxy/websocket_resource.cc
@@ -375,9 +375,9 @@
 
 void WebSocketResource::OnPluginMsgCloseReply(
     const ResourceMessageReplyParams& params,
-    unsigned long buffered_amount,
+    uint64_t buffered_amount,
     bool was_clean,
-    unsigned short code,
+    uint16_t code,
     const std::string& reason) {
   // Set close related properties.
   state_ = PP_WEBSOCKETREADYSTATE_CLOSED;
@@ -457,7 +457,7 @@
 
 void WebSocketResource::OnPluginMsgBufferedAmountReply(
     const ResourceMessageReplyParams& params,
-    unsigned long buffered_amount) {
+    uint64_t buffered_amount) {
   buffered_amount_ = buffered_amount;
 }
 
@@ -469,9 +469,9 @@
 
 void WebSocketResource::OnPluginMsgClosedReply(
     const ResourceMessageReplyParams& params,
-    unsigned long buffered_amount,
+    uint64_t buffered_amount,
     bool was_clean,
-    unsigned short code,
+    uint16_t code,
     const std::string& reason) {
   OnPluginMsgCloseReply(params, buffered_amount, was_clean, code, reason);
 }
diff --git a/ppapi/proxy/websocket_resource.h b/ppapi/proxy/websocket_resource.h
index b5580c8..b50b385 100644
--- a/ppapi/proxy/websocket_resource.h
+++ b/ppapi/proxy/websocket_resource.h
@@ -63,9 +63,9 @@
                                const std::string& url,
                                const std::string& protocol);
   void OnPluginMsgCloseReply(const ResourceMessageReplyParams& params,
-                             unsigned long buffered_amount,
+                             uint64_t buffered_amount,
                              bool was_clean,
-                             unsigned short code,
+                             uint16_t code,
                              const std::string& reason);
   void OnPluginMsgReceiveTextReply(const ResourceMessageReplyParams& params,
                                    const std::string& message);
@@ -73,13 +73,13 @@
                                      const std::vector<uint8_t>& message);
   void OnPluginMsgErrorReply(const ResourceMessageReplyParams& params);
   void OnPluginMsgBufferedAmountReply(const ResourceMessageReplyParams& params,
-                                      unsigned long buffered_amount);
+                                      uint64_t buffered_amount);
   void OnPluginMsgStateReply(const ResourceMessageReplyParams& params,
                              int32_t state);
   void OnPluginMsgClosedReply(const ResourceMessageReplyParams& params,
-                              unsigned long buffered_amount,
+                              uint64_t buffered_amount,
                               bool was_clean,
-                              unsigned short code,
+                              uint16_t code,
                               const std::string& reason);
 
   // Picks up a received message and moves it to user receiving buffer. This
diff --git a/services/ws/event_injector.cc b/services/ws/event_injector.cc
index 19e63bb7..b0502ba 100644
--- a/services/ws/event_injector.cc
+++ b/services/ws/event_injector.cc
@@ -81,6 +81,10 @@
       return event_and_host;
     }
 
+    located_event->UpdateForRootTransform(
+        event_and_host.host->GetRootTransform(),
+        event_and_host.host->GetRootTransformForLocalEventCoordinates());
+
     // NOTE: this does not correctly account for coordinates with capture
     // across displays. If needed, the implementation should match something
     // like:
diff --git a/services/ws/event_injector_unittest.cc b/services/ws/event_injector_unittest.cc
index e804ad2..1030a56 100644
--- a/services/ws/event_injector_unittest.cc
+++ b/services/ws/event_injector_unittest.cc
@@ -2,11 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/ws/injected_event_handler.h"
+#include "services/ws/event_injector.h"
 
 #include <memory>
+#include <utility>
 
+#include "base/bind_helpers.h"
 #include "services/ws/event_injector.h"
+#include "services/ws/injected_event_handler.h"
 #include "services/ws/window_delegate_impl.h"
 #include "services/ws/window_service.h"
 #include "services/ws/window_service_test_helper.h"
@@ -23,10 +26,40 @@
 namespace ws {
 namespace {
 
-std::unique_ptr<ui::Event> CreateTestEvent() {
-  return std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_PRESSED, gfx::Point(),
-                                          gfx::Point(), base::TimeTicks::Now(),
-                                          ui::EF_NONE, ui::EF_NONE);
+std::unique_ptr<ui::Event> CreateMouseTestEvent() {
+  return std::make_unique<ui::MouseEvent>(
+      ui::ET_MOUSE_PRESSED, gfx::Point(100, 100), gfx::Point(100, 100),
+      base::TimeTicks::Now(), ui::EF_NONE, ui::EF_NONE);
+}
+
+std::unique_ptr<ui::Event> CreateTouchTestEvent() {
+  return std::make_unique<ui::TouchEvent>(
+      ui::ET_TOUCH_PRESSED, gfx::Point(100, 100), base::TimeTicks::Now(),
+      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
+}
+
+gfx::Transform GetPrimaryDisplayRotationTransform(
+    const display::Display::Rotation& rotation) {
+  gfx::Transform rotate_transform;
+  display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
+  switch (rotation) {
+    case display::Display::ROTATE_0:
+      break;
+    case display::Display::ROTATE_90:
+      rotate_transform.Translate(display.bounds().height(), 0);
+      rotate_transform.Rotate(90);
+      break;
+    case display::Display::ROTATE_180:
+      rotate_transform.Translate(display.bounds().width(),
+                                 display.bounds().height());
+      rotate_transform.Rotate(180);
+      break;
+    case display::Display::ROTATE_270:
+      rotate_transform.Translate(0, display.bounds().width());
+      rotate_transform.Rotate(270);
+      break;
+  }
+  return rotate_transform;
 }
 
 }  // namespace
@@ -43,17 +76,131 @@
   mojom::EventInjector* mojom_event_injector =
       static_cast<mojom::EventInjector*>(event_injector);
   auto display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
-  mojom_event_injector->InjectEventNoAck(display_id, CreateTestEvent());
+  mojom_event_injector->InjectEventNoAck(display_id, CreateMouseTestEvent());
   EXPECT_EQ(1, test_event_rewriter.events_seen());
   EXPECT_FALSE(event_injector->HasQueuedEvents());
   test_event_rewriter.clear_events_seen();
 
   // Repeat, using the API that circumvents rewriters.
   mojom_event_injector->InjectEventNoAckNoRewriters(display_id,
-                                                    CreateTestEvent());
+                                                    CreateMouseTestEvent());
   EXPECT_EQ(0, test_event_rewriter.events_seen());
   EXPECT_FALSE(event_injector->HasQueuedEvents());
   event_source->RemoveEventRewriter(&test_event_rewriter);
 }
 
+// Test that the event's coordinates are set correctly when the screen is
+// rotated at a degree of 90. 180 and 270.
+TEST(EventInjectorTest, EventLocationRootTransformRotation) {
+  WindowServiceTestSetup test_setup;
+  test_setup.service()->OnStart();
+  auto* event_source = test_setup.root()->GetHost()->GetEventSource();
+  ui::test::TestEventRewriter test_event_rewriter;
+  event_source->AddEventRewriter(&test_event_rewriter);
+
+  EventInjector* event_injector =
+      WindowServiceTestHelper(test_setup.service()).event_injector();
+  mojom::EventInjector* mojom_event_injector =
+      static_cast<mojom::EventInjector*>(event_injector);
+
+  auto display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
+
+  // Inject a touch press event without rotating the screen.
+  mojom_event_injector->InjectEventNoAck(display_id, CreateTouchTestEvent());
+  EXPECT_EQ(1, test_event_rewriter.events_seen());
+  const ui::Event* last_event = test_event_rewriter.last_event();
+  ASSERT_TRUE(last_event);
+  gfx::Point location(100, 100);
+  EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
+  test_event_rewriter.ResetLastEvent();
+
+  // Set the screen rotation degreen to 90 and inject a touch press event.
+  test_setup.root()->GetHost()->SetRootTransform(
+      GetPrimaryDisplayRotationTransform(display::Display::ROTATE_90));
+  mojom_event_injector->InjectEventNoAck(display_id, CreateTouchTestEvent());
+  EXPECT_EQ(2, test_event_rewriter.events_seen());
+  last_event = test_event_rewriter.last_event();
+  ASSERT_TRUE(last_event);
+  location = gfx::Point(500, 100);
+  EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
+  test_event_rewriter.ResetLastEvent();
+
+  // Set the screen rotation degreen to 180 and inject a touch press event.
+  test_setup.root()->GetHost()->SetRootTransform(
+      GetPrimaryDisplayRotationTransform(display::Display::ROTATE_180));
+  mojom_event_injector->InjectEventNoAck(display_id, CreateTouchTestEvent());
+  EXPECT_EQ(3, test_event_rewriter.events_seen());
+  last_event = test_event_rewriter.last_event();
+  ASSERT_TRUE(last_event);
+  location = gfx::Point(500, 700);
+  EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
+  test_event_rewriter.ResetLastEvent();
+
+  // Set the screen rotation degreen to 270 and inject a mouse press event.
+  test_setup.root()->GetHost()->SetRootTransform(
+      GetPrimaryDisplayRotationTransform(display::Display::ROTATE_270));
+  mojom_event_injector->InjectEventNoAck(display_id, CreateMouseTestEvent());
+  EXPECT_EQ(4, test_event_rewriter.events_seen());
+  last_event = test_event_rewriter.last_event();
+  ASSERT_TRUE(last_event);
+  location = gfx::Point(100, 700);
+  EXPECT_EQ(ui::ET_MOUSE_PRESSED, last_event->type());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
+  test_event_rewriter.ResetLastEvent();
+  event_source->RemoveEventRewriter(&test_event_rewriter);
+}
+
+// Test that the event's coordinates are set correctly when the screen is
+// rotated at a degree of 90 and applied a scale factor of 2.
+TEST(EventInjectorTest, EventLocationRootTransformRotationScale) {
+  WindowServiceTestSetup test_setup;
+  test_setup.service()->OnStart();
+  auto* event_source = test_setup.root()->GetHost()->GetEventSource();
+  ui::test::TestEventRewriter test_event_rewriter;
+  event_source->AddEventRewriter(&test_event_rewriter);
+
+  EventInjector* event_injector =
+      WindowServiceTestHelper(test_setup.service()).event_injector();
+  mojom::EventInjector* mojom_event_injector =
+      static_cast<mojom::EventInjector*>(event_injector);
+
+  display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
+
+  // Inject a touch press event without rotating the screen and scaling.
+  mojom_event_injector->InjectEventNoAck(display.id(), CreateTouchTestEvent());
+  EXPECT_EQ(1, test_event_rewriter.events_seen());
+  const ui::Event* last_event = test_event_rewriter.last_event();
+  ASSERT_TRUE(last_event);
+  gfx::Point location(100, 100);
+  EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
+  test_event_rewriter.ResetLastEvent();
+
+  // Inject a touch press event when the screen rotation degreen is 90 and the
+  // scale factor is 2.
+  gfx::Transform transform;
+  transform.Scale(2, 2);
+  transform.Translate(display.bounds().height(), 0);
+  transform.Rotate(90);
+  test_setup.root()->GetHost()->SetRootTransform(transform);
+  mojom_event_injector->InjectEventNoAck(display.id(), CreateTouchTestEvent());
+  EXPECT_EQ(2, test_event_rewriter.events_seen());
+  last_event = test_event_rewriter.last_event();
+  ASSERT_TRUE(last_event);
+  location = gfx::Point(1000, 200);
+  EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
+  EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
+  test_event_rewriter.ResetLastEvent();
+  event_source->RemoveEventRewriter(&test_event_rewriter);
+}
+
 }  // namespace ws
diff --git a/services/ws/public/mojom/event_injector.mojom b/services/ws/public/mojom/event_injector.mojom
index 17d6b21..4eaeb8c 100644
--- a/services/ws/public/mojom/event_injector.mojom
+++ b/services/ws/public/mojom/event_injector.mojom
@@ -14,7 +14,7 @@
   // Responds with false on bad |display_id| or bad |event|; true once the
   // event has completed processing.
   //
-  // If |event| is a LocatedEvent, then the coordinates must be in pixels, and
+  // If |event| is a LocatedEvent, then the coordinates must be in DIPs, and
   // relative to the origin of the display identified by |display_id|.
   InjectEvent(int64 display_id, ui.mojom.Event event) => (bool result);
 
diff --git a/sql/database.h b/sql/database.h
index c838f50..e1c5577 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -59,10 +59,6 @@
 //
 // Instances of this class are thread-unsafe and DCHECK that they are accessed
 // on the same sequence.
-//
-// TODO(pwnall): This should be renamed to Database. Class instances are
-// typically named "db_" / "db", and the class' equivalents in other systems
-// used by Chrome are named LevelDB::DB and blink::IDBDatabase.
 class COMPONENT_EXPORT(SQL) Database {
  private:
   class StatementRef;  // Forward declaration, see real one below.
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index a70abc8e..9774b8a 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -6028,7 +6028,7 @@
         "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true,
-          "shards": 10
+          "shards": 21
         },
         "test": "browser_tests"
       },
@@ -6056,7 +6056,7 @@
         "name": "non_single_process_mash_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
-          "shards": 10
+          "shards": 20
         },
         "test": "browser_tests"
       },
@@ -6068,7 +6068,7 @@
         "name": "viz_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
-          "shards": 10
+          "shards": 20
         },
         "test": "browser_tests"
       },
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 46e778a..0c92fc3 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -5784,8 +5784,7 @@
           "${got_revision}",
           "--test-machine-name",
           "${buildername}",
-          "--use-skia-gold",
-          "--no-skia-gold-failure"
+          "--use-skia-gold"
         ],
         "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
@@ -6343,8 +6342,7 @@
           "${got_revision}",
           "--test-machine-name",
           "${buildername}",
-          "--use-skia-gold",
-          "--no-skia-gold-failure"
+          "--use-skia-gold"
         ],
         "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7668,8 +7666,7 @@
           "${got_revision}",
           "--test-machine-name",
           "${buildername}",
-          "--use-skia-gold",
-          "--no-skia-gold-failure"
+          "--use-skia-gold"
         ],
         "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
@@ -8434,8 +8431,7 @@
           "${got_revision}",
           "--test-machine-name",
           "${buildername}",
-          "--use-skia-gold",
-          "--no-skia-gold-failure"
+          "--use-skia-gold"
         ],
         "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
@@ -15805,8 +15801,7 @@
           "${got_revision}",
           "--test-machine-name",
           "${buildername}",
-          "--use-skia-gold",
-          "--no-skia-gold-failure"
+          "--use-skia-gold"
         ],
         "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
@@ -16173,8 +16168,7 @@
           "${got_revision}",
           "--test-machine-name",
           "${buildername}",
-          "--use-skia-gold",
-          "--no-skia-gold-failure"
+          "--use-skia-gold"
         ],
         "experiment_percentage": 100,
         "isolate_name": "telemetry_gpu_integration_test",
diff --git a/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter b/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter
index 06e0b63..376edb1 100644
--- a/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter
@@ -20,3 +20,13 @@
 
 # http://crbug.com/941858
 -org.chromium.chrome.browser.payments.PaymentRequestUpdateWithTest.testUpdateWithShippingOptions
+
+# http://crbug.com/943829
+-org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTest.testStartAndAccept
+-org.chromium.chrome.browser.autofill.keyboard_accessory.AccessorySheetViewTest.testRemovingTabDeletesItsView
+
+# http://crbug.com/943835
+-org.chromium.chrome.browser.widget.OverviewListLayoutTest.testCanSwipeClosed
+
+# http://crbug.com/943847
+-org.chromium.chrome.browser.browserservices.TrustedWebActivityTest.launchesTwa
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 4423f72c..6fe0718 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -89,6 +89,12 @@
       'Win10 Tests x64 (dbg)',
     ],
     'modifications': {
+      # chromium.fyi
+      'linux-chromeos-code-coverage': {
+        'swarming': {
+          'shards': 21,
+        },
+      },
       # chromium.chromiumos
       'linux-chromeos-dbg': {
         'swarming': {
@@ -1017,6 +1023,12 @@
   },
   'non_single_process_mash_browser_tests': {
     'modifications': {
+      # chromium.fyi
+      'linux-chromeos-code-coverage': {
+        'swarming': {
+          'shards': 20,
+        },
+      },
       # chromium.chromiumos
       'linux-chromeos-dbg': {
         'swarming': {
@@ -1372,6 +1384,12 @@
   },
   'viz_browser_tests': {
     'modifications': {
+      # chromium.fyi
+      'linux-chromeos-code-coverage': {
+        'swarming': {
+          'shards': 20,
+        },
+      },
       # chromium.chromiumos
       'linux-chromeos-dbg': {
         'swarming': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index c1f2818..206b736 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3523,7 +3523,6 @@
           '--test-machine-name',
           '${buildername}',
           '--use-skia-gold',
-          '--no-skia-gold-failure',
         ],
         'non_precommit_args': [
           '--upload-refimg-to-cloud-storage',
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 5e6e0e9..f68553e 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2249,6 +2249,7 @@
   kImportMap = 2831,
   kRefreshHeader = 2832,
   kSearchEventFired = 2833,
+  kIdleDetectionStart = 2834,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h
index 3aba024..382ae48a 100644
--- a/third_party/blink/public/platform/web_url_request.h
+++ b/third_party/blink/public/platform/web_url_request.h
@@ -183,8 +183,6 @@
 
   BLINK_PLATFORM_EXPORT network::mojom::RequestContextFrameType GetFrameType()
       const;
-  BLINK_PLATFORM_EXPORT void SetFrameType(
-      network::mojom::RequestContextFrameType);
 
   BLINK_PLATFORM_EXPORT network::mojom::ReferrerPolicy GetReferrerPolicy()
       const;
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 9119816..57687f30 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -54,6 +54,11 @@
   // The main resource request.
   WebURLRequest url_request;
 
+  // The frame type. This must not be kNone. See RequestContextFrameType.
+  // TODO(dgozman): enforce this is not kNone.
+  network::mojom::RequestContextFrameType frame_type =
+      network::mojom::RequestContextFrameType::kNone;
+
   // The navigation type. See WebNavigationType.
   WebNavigationType navigation_type = kWebNavigationTypeOther;
 
diff --git a/third_party/blink/public/web/web_pepper_socket_client.h b/third_party/blink/public/web/web_pepper_socket_client.h
index 614da441..ec826f9 100644
--- a/third_party/blink/public/web/web_pepper_socket_client.h
+++ b/third_party/blink/public/web/web_pepper_socket_client.h
@@ -59,8 +59,8 @@
 
   // FIXME: Deperecate these methods.
   virtual void DidConnect() {}
-  virtual void DidUpdateBufferedAmount(unsigned long buffered_amount) {}
-  virtual void DidClose(unsigned long unhandled_buffered_amount,
+  virtual void DidUpdateBufferedAmount(uint64_t buffered_amount) {}
+  virtual void DidClose(uint64_t unhandled_buffered_amount,
                         ClosingHandshakeCompletionStatus,
                         uint16_t code,
                         const WebString& reason) {}
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index ca0768b..260c645 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -48,6 +48,7 @@
 #include "third_party/blink/renderer/core/css/style_change_reason.h"
 #include "third_party/blink/renderer/core/css/style_environment_variables.h"
 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
@@ -1575,30 +1576,16 @@
   for (auto element : whitespace_reattach_set_) {
     if (element->NeedsReattachLayoutTree() || !element->GetLayoutObject())
       continue;
-    if (RuntimeEnabledFeatures::DisplayLockingEnabled() &&
-        GetDocument().LockedDisplayLockCount() > 0) {
       // This element might be located inside a display locked subtree, so we
       // might mark it for ReattachLayoutTree later on instead.
-      // TODO(crbug.com/924550): Once we figure out a more efficient way to
-      // determine whether we're inside a locked subtree or not, change this.
-      bool is_in_locked_subtree = false;
-      for (const Node& ancestor :
-           FlatTreeTraversal::InclusiveAncestorsOf(*element)) {
-        if (!ancestor.IsElementNode())
-          continue;
-        if (auto* context = ToElement(ancestor).GetDisplayLockContext()) {
-          if (!context->IsLocked())
-            continue;
-          is_in_locked_subtree = true;
-          context->AddToWhitespaceReattachSet(*element);
-          break;
-        }
-      }
-      if (is_in_locked_subtree)
-        continue;
+    if (Element* locked_ancestor =
+            DisplayLockUtilities::NearestLockedInclusiveAncestor(*element)) {
+      locked_ancestor->GetDisplayLockContext()->AddToWhitespaceReattachSet(
+          *element);
+      continue;
+    }
       DCHECK(!element->NeedsStyleRecalc());
       DCHECK(!element->ChildNeedsStyleRecalc());
-    }
     if (Node* first_child = LayoutTreeBuilderTraversal::FirstChild(*element))
       first_child->MarkAncestorsWithChildNeedsReattachLayoutTree();
   }
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
index c3efad22..2d65b82 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -80,4 +80,23 @@
   }
 }
 
+Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(
+    const Node& node) {
+  if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+      node.GetDocument().LockedDisplayLockCount() == 0) {
+    return nullptr;
+  }
+  // TODO(crbug.com/924550): Once we figure out a more efficient way to
+  // determine whether we're inside a locked subtree or not, change this.
+  for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
+    if (!ancestor.IsElementNode())
+      continue;
+    if (auto* context = ToElement(ancestor).GetDisplayLockContext()) {
+      if (context->IsLocked())
+        return &ToElement(ancestor);
+    }
+  }
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.h b/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
index ffef726..186f74a9 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
@@ -42,6 +42,9 @@
   // activatable-locked).
   static const HeapVector<Member<Element>> ActivatableLockedInclusiveAncestors(
       Element& element);
+
+  // Returns the nearest inclusive ancestor of |node| that is display locked.
+  static Element* NearestLockedInclusiveAncestor(const Node& node);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 4083996..40e3e44 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -574,6 +574,7 @@
 }
 
 void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions* options) {
+  ActivateDisplayLockIfNeeded();
   GetDocument().EnsurePaintLocationDataValidForNode(this);
   ScrollIntoViewNoVisualUpdate(options);
 }
diff --git a/third_party/blink/renderer/core/editing/finder/find_buffer.cc b/third_party/blink/renderer/core/editing/finder/find_buffer.cc
index e8e5749..4587109 100644
--- a/third_party/blink/renderer/core/editing/finder/find_buffer.cc
+++ b/third_party/blink/renderer/core/editing/finder/find_buffer.cc
@@ -145,7 +145,7 @@
          IsHTMLLegendElement(element) || IsHTMLMeterElement(element) ||
          IsHTMLObjectElement(element) || IsHTMLProgressElement(element) ||
          (IsHTMLSelectElement(element) &&
-          !ToHTMLSelectElement(element).IsMultiple()) ||
+          ToHTMLSelectElement(element).UsesMenuList()) ||
          IsHTMLStyleElement(element) || IsHTMLScriptElement(element) ||
          IsHTMLVideoElement(element) || IsHTMLAudioElement(element) ||
          (element.GetDisplayLockContext() &&
diff --git a/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc b/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc
index 7f68e944d..88638e5 100644
--- a/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc
+++ b/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc
@@ -629,10 +629,20 @@
   SetBodyContent("<select multiple><option>find me</option></select>");
   FindBuffer buffer(WholeDocumentRange());
 #if defined(OS_ANDROID)
-  ASSERT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
 #else
-  ASSERT_EQ(1u, buffer.FindMatches("find", 0)->CountForTesting());
+  EXPECT_EQ(1u, buffer.FindMatches("find", 0)->CountForTesting());
 #endif  // defined(OS_ANDROID)
+  SetBodyContent("<select size=2><option>find me</option></select>");
+  buffer = FindBuffer(WholeDocumentRange());
+#if defined(OS_ANDROID)
+  EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
+#else
+  EXPECT_EQ(1u, buffer.FindMatches("find", 0)->CountForTesting());
+#endif  // defined(OS_ANDROID)
+  SetBodyContent("<select size=1><option>find me</option></select>");
+  buffer = FindBuffer(WholeDocumentRange());
+  EXPECT_EQ(0u, buffer.FindMatches("find", 0)->CountForTesting());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory.cc b/third_party/blink/renderer/core/events/pointer_event_factory.cc
index 2e68da16..3234509b 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory.cc
+++ b/third_party/blink/renderer/core/events/pointer_event_factory.cc
@@ -165,6 +165,10 @@
       new_event_init->setBubbles(false);
       UpdateCommonPointerEventInit(event, last_global_position, view,
                                    new_event_init);
+      UIEventWithKeyState::SetFromWebInputEventModifiers(
+          new_event_init,
+          static_cast<WebInputEvent::Modifiers>(event.GetModifiers()));
+
       last_global_position = event.PositionInScreen();
 
       PointerEvent* pointer_event =
@@ -385,6 +389,12 @@
 
   SetEventSpecificFields(pointer_event_init, type);
 
+  if (UIEventWithKeyState* key_state_event =
+          FindEventWithKeyState(pointer_event)) {
+    UIEventWithKeyState::SetFromWebInputEventModifiers(
+        pointer_event_init, key_state_event->GetModifiers());
+  }
+
   if (related_target)
     pointer_event_init->setRelatedTarget(related_target);
 
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory_test.cc b/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
index 69e4239..c169f72 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
+++ b/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
@@ -82,6 +82,15 @@
     const char* expected_pointer_type =
         PointerTypeNameForWebPointPointerType(pointer_type);
     EXPECT_EQ(expected_pointer_type, pointer_event->pointerType());
+
+    EXPECT_EQ(!!(modifiers & WebInputEvent::kControlKey),
+              pointer_event->ctrlKey());
+    EXPECT_EQ(!!(modifiers & WebInputEvent::kShiftKey),
+              pointer_event->shiftKey());
+    EXPECT_EQ(!!(modifiers & WebInputEvent::kAltKey), pointer_event->altKey());
+    EXPECT_EQ(!!(modifiers & WebInputEvent::kMetaKey),
+              pointer_event->metaKey());
+
     if (type == WebInputEvent::kPointerMove) {
       EXPECT_EQ(coalesced_event_count,
                 pointer_event->getCoalescedEvents().size());
@@ -160,6 +169,11 @@
   EXPECT_EQ(clone_pointer_event->pointerId(), pointer_event->pointerId());
   EXPECT_EQ(clone_pointer_event->isPrimary(), pointer_event->isPrimary());
   EXPECT_EQ(clone_pointer_event->type(), type);
+
+  EXPECT_EQ(clone_pointer_event->ctrlKey(), pointer_event->ctrlKey());
+  EXPECT_EQ(clone_pointer_event->shiftKey(), pointer_event->shiftKey());
+  EXPECT_EQ(clone_pointer_event->altKey(), pointer_event->altKey());
+  EXPECT_EQ(clone_pointer_event->metaKey(), pointer_event->metaKey());
 }
 
 void PointerEventFactoryTest::CheckNonHoveringPointers(
@@ -651,4 +665,27 @@
   EXPECT_EQ(event_type_names::kPointerup, last_pointerup_event->type());
 }
 
+TEST_F(PointerEventFactoryTest, MousePointerKeyStates) {
+  WebInputEvent::Modifiers modifiers = static_cast<WebInputEvent::Modifiers>(
+      WebInputEvent::kControlKey | WebInputEvent::kMetaKey);
+
+  PointerEvent* pointer_event1 = CreateAndCheckWebPointerEvent(
+      WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
+      true /* isprimary */, true /* hovering */, modifiers,
+      WebInputEvent::kPointerMove);
+
+  CreateAndCheckPointerTransitionEvent(pointer_event1,
+                                       event_type_names::kPointerout);
+
+  modifiers = static_cast<WebInputEvent::Modifiers>(WebInputEvent::kAltKey |
+                                                    WebInputEvent::kShiftKey);
+  PointerEvent* pointer_event2 = CreateAndCheckWebPointerEvent(
+      WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
+      true /* isprimary */, true /* hovering */, modifiers,
+      WebInputEvent::kPointerMove);
+
+  CreateAndCheckPointerTransitionEvent(pointer_event2,
+                                       event_type_names::kPointerover);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/events/ui_event_with_key_state.cc b/third_party/blink/renderer/core/events/ui_event_with_key_state.cc
index 0ec52d62..9860d401 100644
--- a/third_party/blink/renderer/core/events/ui_event_with_key_state.cc
+++ b/third_party/blink/renderer/core/events/ui_event_with_key_state.cc
@@ -156,7 +156,7 @@
 
 UIEventWithKeyState* FindEventWithKeyState(Event* event) {
   for (Event* e = event; e; e = e->UnderlyingEvent())
-    if (e->IsKeyboardEvent() || e->IsMouseEvent())
+    if (e->IsKeyboardEvent() || e->IsMouseEvent() || e->IsPointerEvent())
       return static_cast<UIEventWithKeyState*>(e);
   return nullptr;
 }
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index 21aeb700..8fdcedf 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -508,6 +508,7 @@
 
 void LocalFrameClientImpl::BeginNavigation(
     const ResourceRequest& request,
+    network::mojom::RequestContextFrameType frame_type,
     Document* origin_document,
     DocumentLoader* document_loader,
     WebNavigationType type,
@@ -529,6 +530,7 @@
 
   auto navigation_info = std::make_unique<WebNavigationInfo>();
   navigation_info->url_request = WrappedResourceRequest(request);
+  navigation_info->frame_type = frame_type;
   navigation_info->navigation_type = type;
   navigation_info->navigation_policy = static_cast<WebNavigationPolicy>(policy);
   navigation_info->has_transient_user_activation = has_transient_activation;
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index e0a600c..2f924f8 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -114,6 +114,7 @@
   void DispatchDidChangeThemeColor() override;
   void BeginNavigation(
       const ResourceRequest&,
+      network::mojom::RequestContextFrameType,
       Document* origin_document,
       DocumentLoader*,
       WebNavigationType,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 3560144..12fd00b 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1487,14 +1487,16 @@
                last_frame_time);
   DCHECK(!last_frame_time.is_null());
 
-  if (needs_hover_update_at_begin_frame_) {
-    MainFrameImpl()->GetFrame()->GetEventHandler().RecomputeMouseHoverState();
-    needs_hover_update_at_begin_frame_ = false;
-  }
-
   if (!MainFrameImpl())
     return;
 
+  if (RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled()) {
+    MainFrameImpl()
+        ->GetFrame()
+        ->GetEventHandler()
+        .RecomputeMouseHoverStateIfNeeded();
+  }
+
   if (LocalFrameView* view = MainFrameImpl()->GetFrameView()) {
     if (FragmentAnchor* anchor = view->GetFragmentAnchor())
       anchor->PerformPreRafActions();
@@ -3315,9 +3317,10 @@
                                    args.elastic_overscroll_delta.y());
   UpdateBrowserControlsConstraint(args.browser_controls_constraint);
 
-  needs_hover_update_at_begin_frame_ =
-      args.scroll_gesture_did_end &&
-      RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled();
+  if (args.scroll_gesture_did_end &&
+      RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled()) {
+    MainFrameImpl()->GetFrame()->GetEventHandler().MarkHoverStateDirty();
+  }
 }
 
 void WebViewImpl::RecordWheelAndTouchScrollingCount(
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index 9db8a50..d9b8a6c 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -688,8 +688,6 @@
 
   FloatSize elastic_overscroll_;
 
-  bool needs_hover_update_at_begin_frame_ = false;
-
   Persistent<EventListener> popup_mouse_wheel_event_listener_;
 
   // The local root whose document has |popup_mouse_wheel_event_listener_|
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 3f29066..22df61bd 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -161,6 +161,7 @@
 
   virtual void BeginNavigation(
       const ResourceRequest&,
+      network::mojom::RequestContextFrameType,
       Document* origin_document,
       DocumentLoader*,
       WebNavigationType,
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index e437eff..6c01824 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -71,7 +71,7 @@
   FrameLoadRequest frame_request(&origin_document, ResourceRequest(url));
   frame_request.GetResourceRequest().SetHasUserGesture(
       user_gesture_status == UserGestureStatus::kActive);
-  frame_request.GetResourceRequest().SetFrameType(
+  frame_request.SetFrameType(
       IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
                     : network::mojom::RequestContextFrameType::kNested);
   Navigate(frame_request, frame_load_type);
@@ -89,7 +89,8 @@
   // won't have access to the originDocument. Do it now.
   FrameLoader::SetReferrerForFrameRequest(frame_request);
   FrameLoader::UpgradeInsecureRequest(frame_request.GetResourceRequest(),
-                                      frame_request.OriginDocument());
+                                      frame_request.OriginDocument(),
+                                      frame_request.GetFrameType());
 
   Document* document = frame_request.OriginDocument();
   bool is_opener_navigation = document && document->GetFrame() &&
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index bf02e6a..30f83e0a 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -1215,8 +1215,12 @@
   scroll_manager_->AnimateSnapFling(monotonic_time);
 }
 
-void EventHandler::RecomputeMouseHoverState() {
-  mouse_event_manager_->RecomputeMouseHoverState();
+void EventHandler::RecomputeMouseHoverStateIfNeeded() {
+  mouse_event_manager_->RecomputeMouseHoverStateIfNeeded();
+}
+
+void EventHandler::MarkHoverStateDirty() {
+  mouse_event_manager_->MarkHoverStateDirty();
 }
 
 Element* EventHandler::EffectiveMouseEventTargetElement(
diff --git a/third_party/blink/renderer/core/input/event_handler.h b/third_party/blink/renderer/core/input/event_handler.h
index d1a9b3d..130c343 100644
--- a/third_party/blink/renderer/core/input/event_handler.h
+++ b/third_party/blink/renderer/core/input/event_handler.h
@@ -282,7 +282,9 @@
 
   void AnimateSnapFling(base::TimeTicks monotonic_time);
 
-  void RecomputeMouseHoverState();
+  void RecomputeMouseHoverStateIfNeeded();
+
+  void MarkHoverStateDirty();
 
  private:
   enum NoCursorChangeType { kNoCursorChange };
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc
index 15cb605..f190931 100644
--- a/third_party/blink/renderer/core/input/event_handler_test.cc
+++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -1254,8 +1254,9 @@
   EXPECT_FALSE(iframe_doc->GetActiveElement());
 }
 
-// Test that the hover is updated at the next begin frame after the scroll ends.
-TEST_F(EventHandlerSimTest, TestUpdateHoverAfterScrollAtBeginFrame) {
+// Test that the hover is updated at the next begin frame after the compositor
+// scroll ends.
+TEST_F(EventHandlerSimTest, TestUpdateHoverAfterCompositorScrollAtBeginFrame) {
   RuntimeEnabledFeatures::SetUpdateHoverFromScrollAtBeginFrameEnabled(true);
   WebView().MainFrameWidget()->Resize(WebSize(800, 600));
   SimRequest request("https://example.com/test.html", "text/html");
@@ -1320,7 +1321,8 @@
   EXPECT_EQ("hover over me", element2.InnerHTML().Utf8());
   EXPECT_EQ("hover over me", element3.InnerHTML().Utf8());
 
-  // Do a compositor scroll and set |scroll_gesture_did_end| to be true.
+  // Do a compositor scroll and set |hover_needs_update_at_scroll_end| to be
+  // true in WebViewImpl.
   LocalFrameView* frame_view = GetDocument().View();
   frame_view->LayoutViewport()->DidScroll(FloatPoint(0, 500));
   WebView().MainFrameWidget()->ApplyViewportChanges(
@@ -1338,6 +1340,107 @@
   EXPECT_EQ("hover over me", element3.InnerHTML().Utf8());
 }
 
+// Test that the hover is updated at the next begin frame after the main thread
+// scroll ends.
+TEST_F(EventHandlerSimTest, TestUpdateHoverAfterMainThreadScrollAtBeginFrame) {
+  RuntimeEnabledFeatures::SetUpdateHoverFromScrollAtBeginFrameEnabled(true);
+  WebView().MainFrameWidget()->Resize(WebSize(800, 600));
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      body, html {
+        margin: 0;
+      }
+      div {
+        height: 300px;
+        width: 100%;
+      }
+    </style>
+    <body>
+    <div class="hoverme" id="line1">hover over me</div>
+    <div class="hoverme" id="line2">hover over me</div>
+    <div class="hoverme" id="line3">hover over me</div>
+    <div class="hoverme" id="line4">hover over me</div>
+    <div class="hoverme" id="line5">hover over me</div>
+    </body>
+    <script>
+      let array = document.getElementsByClassName('hoverme');
+      for (let element of array) {
+        element.addEventListener('mouseover', function (e) {
+          this.innerHTML = "currently hovered";
+        });
+        element.addEventListener('mouseout', function (e) {
+          this.innerHTML = "was hovered";
+        });
+      }
+    </script>
+  )HTML");
+  Compositor().BeginFrame();
+
+  // Set mouse position and active web view.
+  WebMouseEvent mouse_down_event(WebMouseEvent::kMouseDown, WebFloatPoint(1, 1),
+                                 WebFloatPoint(1, 1),
+                                 WebPointerProperties::Button::kLeft, 1,
+                                 WebInputEvent::Modifiers::kLeftButtonDown,
+                                 WebInputEvent::GetStaticTimeStampForTests());
+  mouse_down_event.SetFrameScale(1);
+  GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
+      mouse_down_event);
+
+  WebMouseEvent mouse_up_event(
+      WebInputEvent::kMouseUp, WebFloatPoint(1, 1), WebFloatPoint(1, 1),
+      WebPointerProperties::Button::kLeft, 1, WebInputEvent::kNoModifiers,
+      WebInputEvent::GetStaticTimeStampForTests());
+  mouse_up_event.SetFrameScale(1);
+  GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
+      mouse_up_event);
+
+  WebView().MainFrameWidget()->SetFocus(true);
+  WebView().SetIsActive(true);
+
+  WebElement element1 = GetDocument().getElementById("line1");
+  WebElement element2 = GetDocument().getElementById("line2");
+  WebElement element3 = GetDocument().getElementById("line3");
+  EXPECT_EQ("currently hovered", element1.InnerHTML().Utf8());
+  EXPECT_EQ("hover over me", element2.InnerHTML().Utf8());
+  EXPECT_EQ("hover over me", element3.InnerHTML().Utf8());
+
+  // Send scroll gesture events which will set
+  // |hover_needs_update_at_scroll_end_| to be true in ScrollManager.
+  WebGestureEvent scroll_begin_event(
+      WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+      WebInputEvent::GetStaticTimeStampForTests(),
+      blink::kWebGestureDeviceTouchpad);
+  WebGestureEvent scroll_update_event(
+      WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
+      WebInputEvent::GetStaticTimeStampForTests(),
+      blink::kWebGestureDeviceTouchpad);
+  scroll_update_event.data.scroll_update.delta_y = -500;
+  WebGestureEvent scroll_end_event(WebInputEvent::kGestureScrollEnd,
+                                   WebInputEvent::kNoModifiers,
+                                   WebInputEvent::GetStaticTimeStampForTests(),
+                                   blink::kWebGestureDeviceTouchpad);
+  WebView().MainFrameWidget()->HandleInputEvent(
+      WebCoalescedInputEvent(scroll_begin_event));
+  WebView().MainFrameWidget()->HandleInputEvent(
+      WebCoalescedInputEvent(scroll_update_event));
+  WebView().MainFrameWidget()->HandleInputEvent(
+      WebCoalescedInputEvent(scroll_end_event));
+  LocalFrameView* frame_view = GetDocument().View();
+  ASSERT_EQ(500, frame_view->LayoutViewport()->GetScrollOffset().Height());
+  EXPECT_EQ("currently hovered", element1.InnerHTML().Utf8());
+  EXPECT_EQ("hover over me", element2.InnerHTML().Utf8());
+  EXPECT_EQ("hover over me", element3.InnerHTML().Utf8());
+
+  // The fake mouse move event is dispatched at the begin frame to update hover.
+  Compositor().BeginFrame();
+  EXPECT_EQ("was hovered", element1.InnerHTML().Utf8());
+  EXPECT_EQ("currently hovered", element2.InnerHTML().Utf8());
+  EXPECT_EQ("hover over me", element3.InnerHTML().Utf8());
+}
+
 TEST_F(EventHandlerSimTest, LargeCustomCursorIntersectsViewport) {
   WebView().MainFrameWidget()->Resize(WebSize(800, 600));
   SimRequest request("https://example.com/test.html", "text/html");
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc
index d4b00a81..7e3448e 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -136,6 +136,7 @@
   mouse_down_ = WebMouseEvent();
   svg_pan_ = false;
   drag_start_pos_ = LayoutPoint();
+  hover_state_dirty_ = false;
   fake_mouse_move_event_timer_.Stop();
   ResetDragSource();
   ClearDragDataTransfer();
@@ -369,6 +370,13 @@
   RecomputeMouseHoverState();
 }
 
+void MouseEventManager::RecomputeMouseHoverStateIfNeeded() {
+  if (HoverStateDirty()) {
+    RecomputeMouseHoverState();
+    hover_state_dirty_ = false;
+  }
+}
+
 void MouseEventManager::RecomputeMouseHoverState() {
   if (is_mouse_position_unknown_)
     return;
@@ -406,6 +414,18 @@
   fake_mouse_move_event_timer_.Stop();
 }
 
+void MouseEventManager::MarkHoverStateDirty() {
+  DCHECK(RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled());
+  DCHECK(frame_->IsLocalRoot());
+  hover_state_dirty_ = true;
+}
+
+bool MouseEventManager::HoverStateDirty() {
+  DCHECK(RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled());
+  DCHECK(frame_->IsLocalRoot());
+  return hover_state_dirty_;
+}
+
 void MouseEventManager::SetElementUnderMouse(
     Element* target,
     const String& canvas_region_id,
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.h b/third_party/blink/renderer/core/input/mouse_event_manager.h
index a608946..225f885 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.h
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.h
@@ -155,8 +155,11 @@
 
   bool FakeMouseMovePending() const;
 
+  void RecomputeMouseHoverStateIfNeeded();
   void RecomputeMouseHoverState();
 
+  void MarkHoverStateDirty();
+
  private:
   class MouseEventBoundaryEventDispatcher : public BoundaryEventDispatcher {
    public:
@@ -203,6 +206,7 @@
   DataTransfer* CreateDraggingDataTransfer() const;
 
   void ResetDragSource();
+  bool HoverStateDirty();
 
   // Implementations of |SynchronousMutationObserver|
   void NodeChildrenWillBeRemoved(ContainerNode&) final;
@@ -248,6 +252,11 @@
   WebMouseEvent mouse_down_;
 
   LayoutPoint drag_start_pos_;
+  // This indicates that whether we should update the hover at each begin
+  // frame. This is set to be true after the compositor or main thread scroll
+  // ends, and at each begin frame, we will dispatch a fake mouse move event to
+  // update hover when this is true.
+  bool hover_state_dirty_ = false;
 
   TaskRunnerTimer<MouseEventManager> fake_mouse_move_event_timer_;
 
diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc
index 0bcf5c5..4c80b9f 100644
--- a/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -665,8 +665,10 @@
   }
 
   ClearGestureScrollState();
+
   if (RuntimeEnabledFeatures::UpdateHoverFromScrollAtBeginFrameEnabled())
-    frame_->GetEventHandler().RecomputeMouseHoverState();
+    frame_->GetEventHandler().MarkHoverStateDirty();
+
   return WebInputEventResult::kNotHandled;
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
index b6fcf9e0..b6cba171 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -146,7 +146,9 @@
   void SetSegmentData(unsigned segment_data);
   static void SetSegmentData(const RunSegmenter::RunSegmenterRange& range,
                              Vector<NGInlineItem>* items);
+
   RunSegmenter::RunSegmenterRange CreateRunSegmenterRange() const;
+
   // Whether the other item has the same RunSegmenter properties or not.
   bool EqualsRunSegment(const NGInlineItem&) const;
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
index 7ba19329..a0a671d 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
 
 namespace blink {
@@ -237,16 +238,13 @@
     unsigned start_offset,
     unsigned end_offset,
     unsigned item_index) const {
-  scoped_refptr<ShapeResult> shape_result;
+  Vector<RunSegmenter::RunSegmenterRange> ranges;
   for (const RunSegmenter::RunSegmenterRange& range :
        Ranges(start_offset, end_offset, item_index)) {
-    scoped_refptr<ShapeResult> segment_shape_result =
-        shaper->Shape(font, direction, range.start, range.end, &range);
-    if (!shape_result)
-      shape_result = std::move(segment_shape_result);
-    else
-      segment_shape_result->CopyRange(0, end_offset, shape_result.get());
+    ranges.push_back(range);
   }
+  scoped_refptr<ShapeResult> shape_result =
+      shaper->Shape(font, direction, start_offset, end_offset, ranges);
   DCHECK(shape_result);
   DCHECK_EQ(shape_result->StartIndex(), start_offset);
   DCHECK_EQ(shape_result->EndIndex(), end_offset);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 41762634..06ebfc91 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -749,7 +749,7 @@
           start_item.CreateRunSegmenterRange();
       range.end = end_offset;
       shape_result = shaper.Shape(&font, direction, start_item.StartOffset(),
-                                  end_offset, &range);
+                                  end_offset, range);
     } else {
       shape_result = data->segments->ShapeText(
           &shaper, &font, direction, start_item.StartOffset(), end_offset,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index f90602b..73d8086 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -757,7 +757,7 @@
     RunSegmenter::RunSegmenterRange segment_range =
         item.CreateRunSegmenterRange();
     shape_result = shaper_.Shape(&item.Style()->GetFont(), item.Direction(),
-                                 start, end, &segment_range);
+                                 start, end, segment_range);
   } else {
     shape_result = items_data_.segments->ShapeText(
         &shaper_, &item.Style()->GetFont(), item.Direction(), start, end,
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc
index e702026..99621207 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -96,6 +96,7 @@
 
 void EmptyLocalFrameClient::BeginNavigation(
     const ResourceRequest&,
+    network::mojom::RequestContextFrameType,
     Document* origin_document,
     DocumentLoader*,
     WebNavigationType,
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index b8e78f2..fb3e622 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -273,6 +273,7 @@
   void DispatchDidChangeThemeColor() override {}
 
   void BeginNavigation(const ResourceRequest&,
+                       network::mojom::RequestContextFrameType,
                        Document* origin_document,
                        DocumentLoader*,
                        WebNavigationType,
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 75742ed7..6f59499 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -682,6 +682,8 @@
 }
 
 void FrameFetchContext::ModifyRequestForCSP(ResourceRequest& resource_request) {
+  DCHECK_EQ(network::mojom::RequestContextFrameType::kNone,
+            resource_request.GetFrameType());
   if (GetResourceFetcherProperties().IsDetached())
     return;
 
@@ -689,7 +691,8 @@
   // request.
   GetFrame()->Loader().RecordLatestRequiredCSP();
   GetFrame()->Loader().ModifyRequestForCSP(
-      resource_request, &frame_or_imported_document_->GetDocument());
+      resource_request, &frame_or_imported_document_->GetDocument(),
+      network::mojom::RequestContextFrameType::kNone);
 }
 
 void FrameFetchContext::AddClientHintsIfNecessary(
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index 81bf36b..28e2b93a 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -316,6 +316,13 @@
             KURL("https://secureorigin.test/image.png"))) {}
 
  protected:
+  void ModifyRequestForCSP(ResourceRequest& resource_request,
+                           network::mojom::RequestContextFrameType frame_type) {
+    document->GetFrame()->Loader().RecordLatestRequiredCSP();
+    document->GetFrame()->Loader().ModifyRequestForCSP(
+        resource_request, document.Get(), frame_type);
+  }
+
   void ExpectUpgrade(const char* input, const char* expected) {
     ExpectUpgrade(input, mojom::RequestContextType::SCRIPT,
                   network::mojom::RequestContextFrameType::kNone, expected);
@@ -330,9 +337,8 @@
 
     ResourceRequest resource_request(input_url);
     resource_request.SetRequestContext(request_context);
-    resource_request.SetFrameType(frame_type);
 
-    GetFetchContext()->ModifyRequestForCSP(resource_request);
+    ModifyRequestForCSP(resource_request, frame_type);
 
     EXPECT_EQ(expected_url.GetString(), resource_request.Url().GetString());
     EXPECT_EQ(expected_url.Protocol(), resource_request.Url().Protocol());
@@ -350,9 +356,8 @@
 
     ResourceRequest resource_request(input_url);
     resource_request.SetRequestContext(mojom::RequestContextType::SCRIPT);
-    resource_request.SetFrameType(frame_type);
 
-    GetFetchContext()->ModifyRequestForCSP(resource_request);
+    ModifyRequestForCSP(resource_request, frame_type);
 
     EXPECT_EQ(
         should_prefer ? String("1") : String(),
@@ -374,11 +379,10 @@
     const KURL main_frame_url(main_frame);
     ResourceRequest resource_request(input_url);
     resource_request.SetRequestContext(mojom::RequestContextType::SCRIPT);
-    resource_request.SetFrameType(
-        network::mojom::RequestContextFrameType::kNone);
 
     document->SetSecurityOrigin(SecurityOrigin::Create(KURL(main_frame_url)));
-    GetFetchContext()->ModifyRequestForCSP(resource_request);
+    ModifyRequestForCSP(resource_request,
+                        network::mojom::RequestContextFrameType::kNone);
 
     EXPECT_EQ(expected_value, resource_request.IsAutomaticUpgrade());
   }
@@ -390,9 +394,8 @@
     const KURL input_url(input);
     ResourceRequest resource_request(input_url);
     resource_request.SetRequestContext(mojom::RequestContextType::SCRIPT);
-    resource_request.SetFrameType(frame_type);
 
-    GetFetchContext()->ModifyRequestForCSP(resource_request);
+    ModifyRequestForCSP(resource_request, frame_type);
 
     EXPECT_EQ(expected_required_csp,
               resource_request.HttpHeaderField(http_names::kSecRequiredCSP));
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.h b/third_party/blink/renderer/core/loader/frame_load_request.h
index ddfcd07..2fee010 100644
--- a/third_party/blink/renderer/core/loader/frame_load_request.h
+++ b/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -26,6 +26,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_LOAD_REQUEST_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_LOAD_REQUEST_H_
 
+#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
 #include "third_party/blink/public/web/web_triggering_event_info.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -54,6 +55,13 @@
 
   Document* OriginDocument() const { return origin_document_.Get(); }
 
+  network::mojom::RequestContextFrameType GetFrameType() const {
+    return frame_type_;
+  }
+  void SetFrameType(network::mojom::RequestContextFrameType frame_type) {
+    frame_type_ = frame_type;
+  }
+
   ResourceRequest& GetResourceRequest() { return resource_request_; }
   const ResourceRequest& GetResourceRequest() const {
     return resource_request_;
@@ -148,6 +156,8 @@
   scoped_refptr<base::RefCountedData<mojom::blink::BlobURLTokenPtr>>
       blob_url_token_;
   base::TimeTicks input_start_time_;
+  network::mojom::RequestContextFrameType frame_type_ =
+      network::mojom::RequestContextFrameType::kNone;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 3733bcc..72f3286 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -861,8 +861,7 @@
                             DownloadCrossOriginRedirects::kFollow);
       return;  // Navigation/download will be handled by the client.
     } else if (should_navigate_target_frame) {
-      resource_request.SetFrameType(
-          network::mojom::RequestContextFrameType::kAuxiliary);
+      request.SetFrameType(network::mojom::RequestContextFrameType::kAuxiliary);
       CreateWindowForRequest(request, *frame_);
       return;  // Navigation will be handled by the new frame/window.
     }
@@ -899,9 +898,9 @@
       request.TriggeringEventInfo() != WebTriggeringEventInfo::kNotFromEvent);
   resource_request.SetRequestContext(
       DetermineRequestContextFromNavigationType(navigation_type));
-  resource_request.SetFrameType(
-      frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
-                            : network::mojom::RequestContextFrameType::kNested);
+  request.SetFrameType(frame_->IsMainFrame()
+                           ? network::mojom::RequestContextFrameType::kTopLevel
+                           : network::mojom::RequestContextFrameType::kNested);
 
   mojom::blink::NavigationInitiatorPtr navigation_initiator;
   WebContentSecurityPolicyList initiator_csp;
@@ -939,7 +938,8 @@
   // (i.e. javascript urls). Please see https://crbug.com/701749.
 
   // Report-only CSP headers are checked in browser.
-  ModifyRequestForCSP(resource_request, origin_document);
+  ModifyRequestForCSP(resource_request, origin_document,
+                      request.GetFrameType());
 
   DCHECK(Client()->HasWebView());
   // Check for non-escaped new lines in the url.
@@ -961,8 +961,9 @@
   }
 
   Client()->BeginNavigation(
-      resource_request, origin_document, nullptr /* document_loader */,
-      navigation_type, policy, has_transient_activation, frame_load_type,
+      resource_request, request.GetFrameType(), origin_document,
+      nullptr /* document_loader */, navigation_type, policy,
+      has_transient_activation, frame_load_type,
       request.ClientRedirect() == ClientRedirectPolicy::kClientRedirect,
       request.TriggeringEventInfo(), request.Form(),
       request.ShouldCheckMainWorldContentSecurityPolicy(),
@@ -1661,8 +1662,10 @@
   return flags;
 }
 
-void FrameLoader::ModifyRequestForCSP(ResourceRequest& resource_request,
-                                      Document* origin_document) const {
+void FrameLoader::ModifyRequestForCSP(
+    ResourceRequest& resource_request,
+    Document* origin_document,
+    network::mojom::RequestContextFrameType frame_type) const {
   if (!RequiredCSP().IsEmpty()) {
     DCHECK(
         ContentSecurityPolicy::IsValidCSPAttr(RequiredCSP().GetString(), ""));
@@ -1673,8 +1676,7 @@
   // Tack an 'Upgrade-Insecure-Requests' header to outgoing navigational
   // requests, as described in
   // https://w3c.github.io/webappsec-upgrade-insecure-requests/#feature-detect
-  if (resource_request.GetFrameType() !=
-      network::mojom::RequestContextFrameType::kNone) {
+  if (frame_type != network::mojom::RequestContextFrameType::kNone) {
     // Early return if the request has already been upgraded.
     if (!resource_request.HttpHeaderField(http_names::kUpgradeInsecureRequests)
              .IsNull()) {
@@ -1685,12 +1687,14 @@
                                         "1");
   }
 
-  UpgradeInsecureRequest(resource_request, origin_document);
+  UpgradeInsecureRequest(resource_request, origin_document, frame_type);
 }
 
 // static
-void FrameLoader::UpgradeInsecureRequest(ResourceRequest& resource_request,
-                                         ExecutionContext* origin_context) {
+void FrameLoader::UpgradeInsecureRequest(
+    ResourceRequest& resource_request,
+    ExecutionContext* origin_context,
+    network::mojom::RequestContextFrameType frame_type) {
   // We always upgrade requests that meet any of the following criteria:
   //  1. Are for subresources.
   //  2. Are for nested frames.
@@ -1730,10 +1734,8 @@
   }
 
   // Nested frames are always upgraded on the browser process.
-  if (resource_request.GetFrameType() ==
-      network::mojom::RequestContextFrameType::kNested) {
+  if (frame_type == network::mojom::RequestContextFrameType::kNested)
     return;
-  }
 
   // We set the UpgradeIfInsecure flag even if the current request wasn't
   // upgraded (due to already being HTTPS), since we still need to upgrade
@@ -1747,8 +1749,7 @@
     return;
   }
 
-  if (resource_request.GetFrameType() ==
-          network::mojom::RequestContextFrameType::kNone ||
+  if (frame_type == network::mojom::RequestContextFrameType::kNone ||
       resource_request.GetRequestContext() == mojom::RequestContextType::FORM ||
       (!url.Host().IsNull() && origin_context->GetSecurityContext()
                                    .InsecureNavigationsToUpgrade()
diff --git a/third_party/blink/renderer/core/loader/frame_loader.h b/third_party/blink/renderer/core/loader/frame_loader.h
index 1b1b2b7..fbcc2aa 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.h
+++ b/third_party/blink/renderer/core/loader/frame_loader.h
@@ -34,6 +34,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_LOADER_H_
 
 #include "base/macros.h"
+#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
 #include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
 #include "third_party/blink/public/web/web_document_loader.h"
@@ -170,7 +171,9 @@
   void ForceSandboxFlags(SandboxFlags flags) { forced_sandbox_flags_ |= flags; }
   SandboxFlags EffectiveSandboxFlags() const;
 
-  void ModifyRequestForCSP(ResourceRequest&, Document*) const;
+  void ModifyRequestForCSP(ResourceRequest&,
+                           Document*,
+                           network::mojom::RequestContextFrameType) const;
 
   Frame* Opener();
   void SetOpener(LocalFrame*);
@@ -222,7 +225,9 @@
   void Trace(blink::Visitor*);
 
   static void SetReferrerForFrameRequest(FrameLoadRequest&);
-  static void UpgradeInsecureRequest(ResourceRequest&, ExecutionContext*);
+  static void UpgradeInsecureRequest(ResourceRequest&,
+                                     ExecutionContext*,
+                                     network::mojom::RequestContextFrameType);
 
   void ClientDroppedNavigation();
   void MarkAsLoading();
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index b52bf70..22996cb 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -299,7 +299,9 @@
     const ClientHintsPreferences& hints_preferences,
     const FetchParameters::ResourceWidth& resource_width,
     ResourceRequest& out_request) {
-  FrameLoader::UpgradeInsecureRequest(out_request, global_scope_);
+  FrameLoader::UpgradeInsecureRequest(
+      out_request, global_scope_,
+      network::mojom::RequestContextFrameType::kNone);
   SetFirstPartyCookie(out_request);
   if (!out_request.TopFrameOrigin())
     out_request.SetTopFrameOrigin(GetTopFrameOrigin());
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc
index 40b84e1..d61bee9 100644
--- a/third_party/blink/renderer/core/page/create_window.cc
+++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -315,7 +315,7 @@
                                  bool& created) {
   DCHECK(request.GetResourceRequest().RequestorOrigin() ||
          opener_frame.GetDocument()->Url().IsEmpty());
-  DCHECK_EQ(request.GetResourceRequest().GetFrameType(),
+  DCHECK_EQ(request.GetFrameType(),
             network::mojom::RequestContextFrameType::kAuxiliary);
   probe::WindowOpen(opener_frame.GetDocument(),
                     request.GetResourceRequest().Url(), request.FrameName(),
@@ -404,7 +404,7 @@
                                  ResourceRequest(completed_url), frame_name);
   frame_request.SetShouldSetOpener(window_features.noopener ? kNeverSetOpener
                                                             : kMaybeSetOpener);
-  frame_request.GetResourceRequest().SetFrameType(
+  frame_request.SetFrameType(
       network::mojom::RequestContextFrameType::kAuxiliary);
 
   // Normally, FrameLoader would take care of setting the referrer for a
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
index c20fef1..d97be5a 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -650,12 +650,6 @@
   if (!frame_view)
     return;
 
-  // Wait until after layout to update.
-  // TODO(pdr): This check is wrong as we need to mark the rects as dirty
-  // regardless of whether the frame view needs layout. Remove this check.
-  if (frame_view->NeedsLayout())
-    return;
-
   // FIXME: scheduleAnimation() is just a method of forcing the compositor to
   // realize that it needs to commit here. We should expose a cleaner API for
   // this.
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
index bf7e7c5..c36f3dd 100644
--- a/third_party/blink/renderer/core/page/validation_message_client_impl.cc
+++ b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -85,7 +85,7 @@
     target_frame = &anchor.GetDocument().GetFrame()->LocalFrameRoot();
 
   allow_initial_empty_anchor_ = !target_frame->IsMainFrame();
-  auto delegate = ValidationMessageOverlayDelegate::Create(
+  auto delegate = std::make_unique<ValidationMessageOverlayDelegate>(
       *page_, anchor, message_, message_dir, sub_message, sub_message_dir);
   overlay_delegate_ = delegate.get();
   overlay_ = std::make_unique<FrameOverlay>(target_frame, std::move(delegate));
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
index cbec2fc..238b0c0b0 100644
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -52,7 +52,7 @@
   Member<LocalFrameView> anchor_view_;
 };
 
-inline ValidationMessageOverlayDelegate::ValidationMessageOverlayDelegate(
+ValidationMessageOverlayDelegate::ValidationMessageOverlayDelegate(
     Page& page,
     const Element& anchor,
     const String& message,
@@ -66,17 +66,6 @@
       message_dir_(message_dir),
       sub_message_dir_(sub_message_dir) {}
 
-std::unique_ptr<ValidationMessageOverlayDelegate>
-ValidationMessageOverlayDelegate::Create(Page& page,
-                                         const Element& anchor,
-                                         const String& message,
-                                         TextDirection message_dir,
-                                         const String& sub_message,
-                                         TextDirection sub_message_dir) {
-  return base::WrapUnique(new ValidationMessageOverlayDelegate(
-      page, anchor, message, message_dir, sub_message, sub_message_dir));
-}
-
 ValidationMessageOverlayDelegate::~ValidationMessageOverlayDelegate() {
   if (page_)
     page_->WillBeDestroyed();
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
index 25ad505..5f96ce5 100644
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
@@ -25,13 +25,12 @@
 // Ownership: A FrameOverlay instance owns a ValidationMessageOverlayDelegate.
 class ValidationMessageOverlayDelegate : public FrameOverlay::Delegate {
  public:
-  static std::unique_ptr<ValidationMessageOverlayDelegate> Create(
-      Page&,
-      const Element& anchor,
-      const String& message,
-      TextDirection message_dir,
-      const String& sub_message,
-      TextDirection sub_message_dir);
+  ValidationMessageOverlayDelegate(Page&,
+                                   const Element& anchor,
+                                   const String& message,
+                                   TextDirection message_dir,
+                                   const String& sub_message,
+                                   TextDirection sub_message_dir);
   ~ValidationMessageOverlayDelegate() override;
 
   void PaintFrameOverlay(const FrameOverlay&,
@@ -41,12 +40,6 @@
   bool IsHiding() const;
 
  private:
-  ValidationMessageOverlayDelegate(Page&,
-                                   const Element& anchor,
-                                   const String& message,
-                                   TextDirection message_dir,
-                                   const String& sub_message,
-                                   TextDirection sub_message_dir);
   LocalFrameView& FrameView() const;
   void UpdateFrameViewState(const FrameOverlay&, const IntSize& view_size);
   void EnsurePage(const FrameOverlay&, const IntSize& view_size);
diff --git a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
index 17f1111..7813d0c 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -732,7 +732,7 @@
   }
 };
 
-Elements.StylesSidebarPane._maxLinkLength = 30;
+Elements.StylesSidebarPane._maxLinkLength = 23;
 
 Elements.SectionBlock = class {
   /**
@@ -761,7 +761,7 @@
   static createKeyframesBlock(keyframesName) {
     const separatorElement = createElement('div');
     separatorElement.className = 'sidebar-separator';
-    separatorElement.textContent = Common.UIString('@keyframes ' + keyframesName);
+    separatorElement.textContent = `@keyframes ${keyframesName}`;
     return new Elements.SectionBlock(separatorElement);
   }
 
@@ -772,7 +772,7 @@
   static async _createInheritedNodeBlock(node) {
     const separatorElement = createElement('div');
     separatorElement.className = 'sidebar-separator';
-    separatorElement.createTextChild(Common.UIString('Inherited from') + ' ');
+    separatorElement.createTextChild(ls`Inherited from${' '}`);
     const link = await Common.Linkifier.linkify(node);
     separatorElement.appendChild(link);
     return new Elements.SectionBlock(separatorElement);
@@ -844,9 +844,8 @@
     this._selectorElement.addEventListener('mousemove', event => event.consume(), false);
     this._selectorElement.addEventListener('mouseleave', this._onMouseOutSelector.bind(this), false);
 
-    const openBrace = createElement('span');
+    const openBrace = selectorContainer.createChild('span', 'sidebar-pane-open-brace');
     openBrace.textContent = ' {';
-    selectorContainer.appendChild(openBrace);
     selectorContainer.addEventListener('mousedown', this._handleEmptySpaceMouseDown.bind(this), false);
     selectorContainer.addEventListener('click', this._handleSelectorContainerClick.bind(this), false);
 
@@ -929,7 +928,7 @@
 
     if (header && header.ownerNode) {
       const link = Elements.DOMLinkifier.linkifyDeferredNodeReference(header.ownerNode);
-      link.textContent = '<style>…</style>';
+      link.textContent = '<style>';
       return link;
     }
 
@@ -1084,7 +1083,7 @@
     if (this._style.type === SDK.CSSStyleDeclaration.Type.Inline)
       return this._matchedStyles.isInherited(this._style) ? Common.UIString('Style Attribute') : 'element.style';
     if (this._style.type === SDK.CSSStyleDeclaration.Type.Attributes)
-      return node.nodeNameInCorrectCase() + '[' + Common.UIString('Attributes Style') + ']';
+      return ls`${node.nodeNameInCorrectCase()}[Attributes Style]`;
     return this._style.parentRule.selectorText();
   }
 
@@ -2138,14 +2137,13 @@
       // If a CSS value is being edited that has a numeric or hex substring, hint that precision modifier shortcuts are available.
       if (treeElement && treeElement.valueElement) {
         const cssValueText = treeElement.valueElement.textContent;
+        const cmdOrCtrl = Host.isMac() ? 'Cmd' : 'Ctrl';
         if (cssValueText.match(/#[\da-f]{3,6}$/i)) {
-          this.setTitle(Common.UIString(
-              'Increment/decrement with mousewheel or up/down keys. %s: R ±1, Shift: G ±1, Alt: B ±1',
-              Host.isMac() ? 'Cmd' : 'Ctrl'));
+          this.setTitle(ls
+              `Increment/decrement with mousewheel or up/down keys. ${cmdOrCtrl}: R ±1, Shift: G ±1, Alt: B ±1`);
         } else if (cssValueText.match(/\d+/)) {
-          this.setTitle(Common.UIString(
-              'Increment/decrement with mousewheel or up/down keys. %s: ±100, Shift: ±10, Alt: ±0.1',
-              Host.isMac() ? 'Cmd' : 'Ctrl'));
+          this.setTitle(ls
+              `Increment/decrement with mousewheel or up/down keys. ${cmdOrCtrl}: ±100, Shift: ±10, Alt: ±0.1`);
         }
       }
     }
diff --git a/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css b/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
index 47442464..d5be8fdc 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
+++ b/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
@@ -54,7 +54,7 @@
 }
 
 .styles-section-title .media-list {
-    color: #888;
+    color: hsl(0, 0%, 46%);
 }
 
 .styles-section-title .media-list.media-matches .media.editable-media {
@@ -68,13 +68,13 @@
 
 .styles-section-title .media .subtitle {
     float: right;
-    color: rgb(85, 85, 85);
+    color: hsl(0, 0%, 34%);
 }
 
 .styles-section-subtitle {
-    color: rgb(85, 85, 85);
+    color: hsl(0, 0%, 44%);
     float: right;
-    margin-left: 5px;
+    padding-left: 15px;
     max-width: 100%;
     text-overflow: ellipsis;
     overflow: hidden;
@@ -83,12 +83,18 @@
     margin-bottom: -1px;
 }
 
+.sidebar-pane-open-brace,
+.sidebar-pane-closing-brace {
+    color: hsl(0, 0%, 46%);
+}
+
 .styles-section .styles-section-subtitle .devtools-link {
-    color: inherit;
+    color: hsl(0, 0%, 44%);
+    text-decoration-color: hsl(0, 0%, 60%);
 }
 
 .styles-section .selector {
-    color: #888;
+    color: hsl(0, 0%, 46%);
 }
 
 .styles-section .simple-selector.selector-matches, .styles-section.keyframe-key {
@@ -192,7 +198,7 @@
     background-color: var(--toolbar-bg-color);
     padding: 0 5px;
     border-bottom: 1px solid var(--divider-color);
-    color: rgb(50, 50, 50);
+    color: hsla(0, 0%, 32%, 1);
     white-space: nowrap;
     text-overflow: ellipsis;
     overflow: hidden;
@@ -200,9 +206,12 @@
 }
 
 .sidebar-separator > span.monospace {
-    background: rgb(255, 255, 255);
-    padding: 1px 3px;
-    border: 1px solid var(--divider-color);
+    max-width: 90px;
+    display: inline-block;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    vertical-align: middle;
+    margin-left: 2px;
 }
 
 .sidebar-pane-section-toolbar {
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
index 0f5acb8..3052412d 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -68,9 +68,10 @@
    * @param {!SDK.RemoteObject} object
    * @param {!Components.Linkifier=} linkifier
    * @param {boolean=} skipProto
+   * @param {boolean=} readOnly
    * @return {!Element}
    */
-  static defaultObjectPresentation(object, linkifier, skipProto) {
+  static defaultObjectPresentation(object, linkifier, skipProto, readOnly) {
     const componentRoot = createElementWithClass('span', 'source-code');
     const shadowRoot = UI.createShadowRootWithCoreStyles(componentRoot, 'object_ui/objectValue.css');
     shadowRoot.appendChild(
@@ -82,6 +83,8 @@
     objectPropertiesSection.editable = false;
     if (skipProto)
       objectPropertiesSection.skipProto();
+    if (readOnly)
+      objectPropertiesSection.setEditable(false);
 
     return objectPropertiesSection.element;
   }
diff --git a/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js b/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
index 2d74f1e..a63b29b9 100644
--- a/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
+++ b/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
@@ -447,7 +447,7 @@
       case 'key':
       case 'primaryKey':
         cell.removeChildren();
-        const objectElement = ObjectUI.ObjectPropertiesSection.defaultObjectPresentation(value, undefined, true);
+        const objectElement = ObjectUI.ObjectPropertiesSection.defaultObjectPresentation(value, undefined, true, true);
         cell.appendChild(objectElement);
         break;
       default:
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard.cc b/third_party/blink/renderer/modules/clipboard/clipboard.cc
index 57a75b78..065bccc 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard.cc
+++ b/third_party/blink/renderer/modules/clipboard/clipboard.cc
@@ -21,8 +21,9 @@
   return ClipboardPromise::CreateForReadText(script_state);
 }
 
-ScriptPromise Clipboard::write(ScriptState* script_state,
-                               HeapVector<Member<Blob>> data) {
+ScriptPromise Clipboard::write(
+    ScriptState* script_state,
+    HeapVector<std::pair<String, Member<Blob>>> data) {
   return ClipboardPromise::CreateForWrite(script_state, std::move(data));
 }
 
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard.h b/third_party/blink/renderer/modules/clipboard/clipboard.h
index 424b9a8..e18decf8 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard.h
+++ b/third_party/blink/renderer/modules/clipboard/clipboard.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_H_
 
+#include <utility>
+
 #include "base/macros.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
@@ -26,7 +28,8 @@
   ScriptPromise read(ScriptState*);
   ScriptPromise readText(ScriptState*);
 
-  ScriptPromise write(ScriptState*, HeapVector<Member<Blob>>);
+  ScriptPromise write(ScriptState*,
+                      HeapVector<std::pair<String, Member<Blob>>>);
   ScriptPromise writeText(ScriptState*, const String&);
 
   // EventTarget
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard.idl b/third_party/blink/renderer/modules/clipboard/clipboard.idl
index bf45d33..4687936 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard.idl
+++ b/third_party/blink/renderer/modules/clipboard/clipboard.idl
@@ -11,7 +11,7 @@
     [MeasureAs=AsyncClipboardAPIRead,
      CallWith=ScriptState,
      RuntimeEnabled=AsyncClipboard
-    ] Promise<sequence<Blob>> read();
+    ] Promise<record<DOMString, Blob>> read();
 
     [MeasureAs=AsyncClipboardAPIReadText,
      CallWith=ScriptState
@@ -21,7 +21,7 @@
     [MeasureAs=AsyncClipboardAPIWrite,
      CallWith=ScriptState,
      RuntimeEnabled=AsyncClipboard
-    ] Promise<void> write(sequence<Blob> data);
+    ] Promise<void> write(record<DOMString, Blob> data);
 
     [MeasureAs=AsyncClipboardAPIWriteText,
      CallWith=ScriptState
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
index 3fc4e3d..8cdab5f 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
+++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -87,16 +87,18 @@
 }
 
 // static
-ScriptPromise ClipboardPromise::CreateForWrite(ScriptState* script_state,
-                                               HeapVector<Member<Blob>> data) {
+ScriptPromise ClipboardPromise::CreateForWrite(
+    ScriptState* script_state,
+    HeapVector<std::pair<String, Member<Blob>>> clipboard_item) {
   ClipboardPromise* clipboard_promise =
       MakeGarbageCollected<ClipboardPromise>(script_state);
-  HeapVector<Member<Blob>>* blob_sequence =
-      MakeGarbageCollected<HeapVector<Member<Blob>>>(data);
+  HeapVector<std::pair<String, Member<Blob>>>* blob_map =
+      MakeGarbageCollected<HeapVector<std::pair<String, Member<Blob>>>>(
+          clipboard_item);
   clipboard_promise->GetTaskRunner()->PostTask(
-      FROM_HERE, WTF::Bind(&ClipboardPromise::HandleWrite,
-                           WrapPersistent(clipboard_promise),
-                           WrapPersistent(blob_sequence)));
+      FROM_HERE,
+      WTF::Bind(&ClipboardPromise::HandleWrite,
+                WrapPersistent(clipboard_promise), WrapPersistent(blob_map)));
   return clipboard_promise->script_promise_resolver_->Promise();
 }
 
@@ -208,25 +210,25 @@
   }
 
   Vector<String> types_to_read = TypesToRead();
-  HeapVector<Member<Blob>> blobs;
-  blobs.ReserveInitialCapacity(types_to_read.size());
-  for (const String& type_to_read : types_to_read) {
+  HeapVector<std::pair<String, Member<Blob>>> clipboard_item;
+  clipboard_item.ReserveInitialCapacity(types_to_read.size());
+  for (String& type_to_read : types_to_read) {
     if (type_to_read == kMimeTypeImagePng) {
-      blobs.push_back(ReadImageAsBlob());
+      clipboard_item.emplace_back(std::move(type_to_read), ReadImageAsBlob());
     } else if (type_to_read == kMimeTypeTextPlain) {
-      blobs.push_back(ReadTextAsBlob());
+      clipboard_item.emplace_back(std::move(type_to_read), ReadTextAsBlob());
     } else {
       NOTREACHED() << "Type " << type_to_read << " was not implemented";
     }
   }
 
-  if (!blobs.size()) {
+  if (!clipboard_item.size()) {
     script_promise_resolver_->Reject(DOMException::Create(
         DOMExceptionCode::kDataError, "No valid data on clipboard."));
     return;
   }
 
-  script_promise_resolver_->Resolve(std::move(blobs));
+  script_promise_resolver_->Resolve(std::move(clipboard_item));
 }
 
 void ClipboardPromise::HandleReadText() {
@@ -247,10 +249,11 @@
   script_promise_resolver_->Resolve(text);
 }
 
-void ClipboardPromise::HandleWrite(HeapVector<Member<Blob>>* data) {
+void ClipboardPromise::HandleWrite(
+    HeapVector<std::pair<String, Member<Blob>>>* clipboard_item) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(async_clipboard_sequence_checker);
-  CHECK(data);
-  blob_sequence_data_ = std::move(*data);
+  CHECK(clipboard_item);
+  clipboard_item_ = std::move(*clipboard_item);
 
   CheckWritePermission(WTF::Bind(&ClipboardPromise::HandleWriteWithPermission,
                                  WrapPersistent(this)));
@@ -264,25 +267,25 @@
     return;
   }
 
-  // Check that all blobs have valid and unique MIME types.
-  HashSet<String> unique_types;
-  unique_types.ReserveCapacityForSize(blob_sequence_data_.size());
-  for (const Member<Blob>& blob : blob_sequence_data_) {
-    String type = blob->type();
+  // Check that incoming dictionary isn't empty. If it is, it's possible that
+  // Javascript bindings implicitly converted an Object (like a Blob) into {},
+  // an empty dictionary.
+  if(!clipboard_item_.size()) {
+    script_promise_resolver_->Reject(
+          DOMException::Create(DOMExceptionCode::kNotAllowedError,
+                               "No items in input."));
+      return;
+  }
+
+  // Check that all blobs have valid MIME types.
+  for (const auto& type_and_blob : clipboard_item_) {
+    String type = type_and_blob.first;
     if (!IsValidClipboardType(type)) {
       script_promise_resolver_->Reject(
           DOMException::Create(DOMExceptionCode::kNotAllowedError,
                                "Write type " + type + " not supported."));
       return;
     }
-    if (unique_types.Contains(type)) {
-      script_promise_resolver_->Reject(
-          DOMException::Create(DOMExceptionCode::kNotAllowedError,
-                               "Attempting to write duplicate type " + type +
-                                   +". All types must be unique"));
-      return;
-    }
-    unique_types.insert(type);
   }
 
   DCHECK(!clipboard_representation_index_);
@@ -292,14 +295,14 @@
 // Called to begin writing a type, or after writing each type.
 void ClipboardPromise::WriteNextRepresentation() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(async_clipboard_sequence_checker);
-  if (clipboard_representation_index_ == blob_sequence_data_.size()) {
+  if (clipboard_representation_index_ == clipboard_item_.size()) {
     SystemClipboard::GetInstance().CommitWrite();
     script_promise_resolver_->Resolve();
     return;
   }
 
   const Member<Blob>& blob =
-      blob_sequence_data_[clipboard_representation_index_];
+      clipboard_item_[clipboard_representation_index_].second;
   clipboard_representation_index_++;
   DCHECK(IsValidClipboardType(blob->type()));
 
@@ -333,8 +336,8 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(async_clipboard_sequence_checker);
   file_reader_.reset();
 
-  String blob_type =
-      blob_sequence_data_[clipboard_representation_index_ - 1]->type();
+  const String& blob_type =
+      clipboard_item_[clipboard_representation_index_ - 1].first;
   DCHECK(IsValidClipboardType(blob_type));
 
   if (blob_type == kMimeTypeImagePng) {
@@ -428,7 +431,7 @@
   script_promise_resolver_->Reject(DOMException::Create(
       DOMExceptionCode::kDataError,
       "Failed to read Blob for clipboard item type " +
-          blob_sequence_data_[clipboard_representation_index_]->type() + "."));
+          clipboard_item_[clipboard_representation_index_].first + "."));
 }
 
 // TODO(huangdarwin): This is beginning to share responsibility
@@ -484,7 +487,7 @@
 void ClipboardPromise::Trace(blink::Visitor* visitor) {
   visitor->Trace(script_state_);
   visitor->Trace(script_promise_resolver_);
-  visitor->Trace(blob_sequence_data_);
+  visitor->Trace(clipboard_item_);
   ContextLifecycleObserver::Trace(visitor);
 }
 
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
index 89e0c08..f4e59ac4 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
+++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_PROMISE_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_CLIPBOARD_CLIPBOARD_PROMISE_H_
 
+#include <utility>
+
 #include "base/macros.h"
 #include "base/sequence_checker.h"
 #include "third_party/blink/public/mojom/clipboard/clipboard.mojom-blink.h"
@@ -34,7 +36,9 @@
   // Creates promise to execute Clipboard API functions off the main thread.
   static ScriptPromise CreateForRead(ScriptState*);
   static ScriptPromise CreateForReadText(ScriptState*);
-  static ScriptPromise CreateForWrite(ScriptState*, HeapVector<Member<Blob>>);
+  static ScriptPromise CreateForWrite(
+      ScriptState*,
+      HeapVector<std::pair<String, Member<Blob>>>);
   static ScriptPromise CreateForWriteText(ScriptState*, const String&);
 
   // Entry points back into ClipboardPromise, from ClipboardFileReader.
@@ -58,7 +62,7 @@
   // Checks Read/Write permission (interacting with PermissionService).
   void HandleRead();
   void HandleReadText();
-  void HandleWrite(HeapVector<Member<Blob>>*);
+  void HandleWrite(HeapVector<std::pair<String, Member<Blob>>>*);
   void HandleWriteText(const String&);
 
   // Reads/Writes after permission check.
@@ -100,7 +104,7 @@
   mojom::ClipboardBuffer buffer_;
 
   String write_data_;
-  HeapVector<Member<Blob>> blob_sequence_data_;
+  HeapVector<std::pair<String, Member<Blob>>> clipboard_item_;
   // Index of clipboard representation currently being processed.
   wtf_size_t clipboard_representation_index_;
 
diff --git a/third_party/blink/renderer/modules/idle/idle_manager.idl b/third_party/blink/renderer/modules/idle/idle_manager.idl
index a0d3089..e11d3b22 100644
--- a/third_party/blink/renderer/modules/idle/idle_manager.idl
+++ b/third_party/blink/renderer/modules/idle/idle_manager.idl
@@ -9,6 +9,6 @@
   Exposed=(Window,DedicatedWorker),
   RuntimeEnabled=IdleDetection
 ] interface IdleManager {
-  [CallWith=ScriptState, RaisesException]
+  [CallWith=ScriptState, RaisesException, MeasureAs=IdleDetectionStart]
   Promise<IdleStatus> query(optional IdleOptions options);
 };
diff --git a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc
index c1e4b664..4431a6c 100644
--- a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc
+++ b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc
@@ -100,7 +100,7 @@
 
 bool WebPepperSocketImpl::SendArrayBuffer(
     const WebArrayBuffer& web_array_buffer) {
-  size_t size = web_array_buffer.ByteLength();
+  unsigned size = web_array_buffer.ByteLength();
   buffered_amount_ += size;
   if (is_closing_or_closed_)
     buffered_amount_after_close_ += size;
diff --git a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h
index 3c29c8d..bb13b54 100644
--- a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h
+++ b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.h
@@ -80,8 +80,8 @@
   WebString subprotocol_;
   bool is_closing_or_closed_;
   // |buffered_amount_| includes |buffered_amount_after_close_|.
-  unsigned long buffered_amount_;
-  unsigned long buffered_amount_after_close_;
+  uint64_t buffered_amount_;
+  uint64_t buffered_amount_after_close_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
index c9b7f86..600074a76 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -178,7 +178,7 @@
   // |handshake_throttle_| is owned by |channel_| once SetUp() has been called.
   MockWebSocketHandshakeThrottle* handshake_throttle_;
   Persistent<WebSocketChannelImpl> channel_;
-  unsigned long sum_of_consumed_buffered_amount_;
+  uint64_t sum_of_consumed_buffered_amount_;
 };
 
 MATCHER_P2(MemEq,
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index 40bfd45..cc37b3b 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -239,11 +239,6 @@
   resource_request_->SetRequestContext(request_context);
 }
 
-void WebURLRequest::SetFrameType(
-    network::mojom::RequestContextFrameType frame_type) {
-  resource_request_->SetFrameType(frame_type);
-}
-
 int WebURLRequest::RequestorID() const {
   return resource_request_->RequestorID();
 }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
index 435856d..d824cf4 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -740,6 +740,17 @@
   }
 }
 
+inline RangeData CreateRangeData(const Font* font,
+                                 TextDirection direction,
+                                 hb_buffer_t* buffer) {
+  RangeData range_data;
+  range_data.buffer = buffer;
+  range_data.font = font;
+  range_data.text_direction = direction;
+  SetFontFeatures(font, &range_data.font_features);
+  return range_data;
+}
+
 class CapsFeatureSettingsScopedOverlay final {
   STACK_ALLOCATED();
 
@@ -811,7 +822,6 @@
     ShapeResult* result) const {
   DCHECK(result);
   DCHECK(range_data->buffer);
-
   const Font* font = range_data->font;
   const FontDescription& font_description = font->GetFontDescription();
   const hb_language_t language =
@@ -930,34 +940,23 @@
   }
 }
 
-scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
-    const Font* font,
-    TextDirection direction,
-    unsigned start,
-    unsigned end,
-    const RunSegmenter::RunSegmenterRange* pre_segmented) const {
+scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(const Font* font,
+                                                 TextDirection direction,
+                                                 unsigned start,
+                                                 unsigned end) const {
   DCHECK_GE(end, start);
   DCHECK_LE(end, text_.length());
-  DCHECK(!pre_segmented ||
-         (start >= pre_segmented->start && end <= pre_segmented->end));
 
   unsigned length = end - start;
   scoped_refptr<ShapeResult> result =
       ShapeResult::Create(font, length, direction);
-  HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
 
-  RangeData range_data;
-  range_data.buffer = buffer.Get();
-  range_data.font = font;
-  range_data.text_direction = direction;
+  HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
+  RangeData range_data = CreateRangeData(font, direction, buffer.Get());
   range_data.start = start;
   range_data.end = end;
-  SetFontFeatures(font, &range_data.font_features);
 
-  if (pre_segmented) {
-    ShapeSegment(&range_data, *pre_segmented, result.get());
-
-  } else if (text_.Is8Bit()) {
+  if (text_.Is8Bit()) {
     // 8-bit text is guaranteed to horizontal latin-1.
     RunSegmenter::RunSegmenterRange segment_range = {
         start, end, USCRIPT_LATIN, OrientationIterator::kOrientationKeep,
@@ -999,6 +998,81 @@
 
 scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
     const Font* font,
+    TextDirection direction,
+    unsigned start,
+    unsigned end,
+    const Vector<RunSegmenter::RunSegmenterRange>& ranges) const {
+  DCHECK_GE(end, start);
+  DCHECK_LE(end, text_.length());
+  DCHECK_GT(ranges.size(), 0u);
+  DCHECK_EQ(start, ranges[0].start);
+  DCHECK_EQ(end, ranges[ranges.size() - 1].end);
+
+  unsigned length = end - start;
+  scoped_refptr<ShapeResult> result =
+      ShapeResult::Create(font, length, direction);
+
+  HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
+  RangeData range_data = CreateRangeData(font, direction, buffer.Get());
+
+  for (const RunSegmenter::RunSegmenterRange& segmented_range : ranges) {
+    DCHECK_GE(segmented_range.end, segmented_range.start);
+    DCHECK_GE(segmented_range.start, start);
+    DCHECK_LE(segmented_range.end, end);
+
+    range_data.start = segmented_range.start;
+    range_data.end = segmented_range.end;
+    ShapeSegment(&range_data, segmented_range, result.get());
+  }
+
+  // Ensure |start_index_| is updated even when no runs were inserted.
+  if (UNLIKELY(result->runs_.IsEmpty()))
+    result->start_index_ = start;
+
+#if DCHECK_IS_ON()
+  if (result)
+    CheckShapeResultRange(result.get(), start, end, text_, font);
+#endif
+
+  return result;
+}
+
+scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
+    const Font* font,
+    TextDirection direction,
+    unsigned start,
+    unsigned end,
+    const RunSegmenter::RunSegmenterRange pre_segmented) const {
+  DCHECK_GE(end, start);
+  DCHECK_LE(end, text_.length());
+  DCHECK_GE(start, pre_segmented.start);
+  DCHECK_LE(end, pre_segmented.end);
+
+  unsigned length = end - start;
+  scoped_refptr<ShapeResult> result =
+      ShapeResult::Create(font, length, direction);
+
+  HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
+  RangeData range_data = CreateRangeData(font, direction, buffer.Get());
+  range_data.start = start;
+  range_data.end = end;
+
+  ShapeSegment(&range_data, pre_segmented, result.get());
+
+  // Ensure |start_index_| is updated even when no runs were inserted.
+  if (UNLIKELY(result->runs_.IsEmpty()))
+    result->start_index_ = start;
+
+#if DCHECK_IS_ON()
+  if (result)
+    CheckShapeResultRange(result.get(), start, end, text_, font);
+#endif
+
+  return result;
+}
+
+scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
+    const Font* font,
     TextDirection direction) const {
   return Shape(font, direction, 0, text_.length());
 }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
index 52cda93b..ba982bc 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
@@ -58,15 +58,27 @@
   // occur, such as at the beginning or end of lines or at element boundaries.
   // If given arbitrary positions the results are not guaranteed to be correct.
   // May be called multiple times; font and direction may vary between calls.
-  //
-  // If |pre_segmented| is given, it is assumed that the string is already
-  // segmented. Otherwise the string is segmented into runs before shaping.
+  scoped_refptr<ShapeResult> Shape(const Font*,
+                                   TextDirection,
+                                   unsigned start,
+                                   unsigned end) const;
+
+  // Shape a range that has already been pre-segmented. Start and end positions
+  // must match the positions defined by the ranges and must be at valid break
+  // positions.
   scoped_refptr<ShapeResult> Shape(
       const Font*,
       TextDirection,
       unsigned start,
       unsigned end,
-      const RunSegmenter::RunSegmenterRange* pre_segmented = nullptr) const;
+      const Vector<RunSegmenter::RunSegmenterRange>&) const;
+
+  // Shape a single range. Start and end positions defined by the range.
+  scoped_refptr<ShapeResult> Shape(const Font*,
+                                   TextDirection,
+                                   unsigned start,
+                                   unsigned end,
+                                   const RunSegmenter::RunSegmenterRange) const;
 
   // Shape the entire string with a single font and direction.
   // Equivalent to calling the range version with a start offset of zero and an
diff --git a/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h b/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
index 93227df..2a6f7c9 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
@@ -26,8 +26,7 @@
 
  public:
   // Indices into the UTF-16 buffer that is passed in
-  struct RunSegmenterRange {
-    DISALLOW_NEW();
+  struct PLATFORM_EXPORT RunSegmenterRange {
     unsigned start;
     unsigned end;
     UScriptCode script;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 3f7e470e..89f4a980 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -715,8 +715,8 @@
         anti_aliasing_mode_ = gpu::kAntialiasingModeMSAAImplicitResolve;
       } else if (extensions_util_->SupportsExtension(
                      "GL_CHROMIUM_screen_space_antialiasing") &&
-                 !ContextProvider()->GetGpuFeatureInfo().IsWorkaroundEnabled(
-                     gpu::DISABLE_FRAMEBUFFER_CMAA)) {
+                 ContextProvider()->GetGpuFeatureInfo().IsWorkaroundEnabled(
+                     gpu::USE_FRAMEBUFFER_CMAA)) {
         anti_aliasing_mode_ = gpu::kAntialiasingModeScreenSpaceAntialiasing;
       }
     } else {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
index aa3244f..453cd99 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
@@ -173,7 +173,6 @@
   ResourceRequest request;
   request.SetURL(test_url_);
   request.SetRequestContext(mojom::RequestContextType::FETCH);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kNone);
   FetchParameters fetch_parameters(request);
 
   Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
@@ -198,7 +197,6 @@
   ResourceRequest request;
   request.SetURL(test_url_);
   request.SetRequestContext(mojom::RequestContextType::FETCH);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kNone);
   FetchParameters fetch_parameters(request);
 
   Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
@@ -213,7 +211,6 @@
   ResourceRequest request;
   request.SetURL(test_url_);
   request.SetRequestContext(mojom::RequestContextType::FETCH);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kNone);
   FetchParameters fetch_parameters(request);
 
   Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
@@ -232,7 +229,6 @@
   ResourceRequest request;
   request.SetURL(test_url_);
   request.SetRequestContext(mojom::RequestContextType::FETCH);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kNone);
   FetchParameters fetch_parameters(request);
 
   Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
@@ -255,7 +251,6 @@
   ResourceRequest request;
   request.SetURL(test_url_);
   request.SetRequestContext(mojom::RequestContextType::FETCH);
-  request.SetFrameType(network::mojom::RequestContextFrameType::kNone);
 
   FetchParameters fetch_parameters(request);
   Resource* resource = RawResource::Fetch(fetch_parameters, fetcher, nullptr);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index e282391e..f4e2b81 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -114,7 +114,6 @@
   request->SetDownloadToBlob(DownloadToBlob());
   request->SetUseStreamOnResponse(UseStreamOnResponse());
   request->SetRequestContext(GetRequestContext());
-  request->SetFrameType(GetFrameType());
   request->SetShouldResetAppCache(ShouldResetAppCache());
   request->SetFetchRequestMode(GetFetchRequestMode());
   request->SetFetchCredentialsMode(GetFetchCredentialsMode());
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index 2742ec09..9a7a5ca 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -289,11 +289,10 @@
   }
 
   network::mojom::RequestContextFrameType GetFrameType() const {
+    // TODO(dgozman): remove this getter.
+    DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, frame_type_);
     return frame_type_;
   }
-  void SetFrameType(network::mojom::RequestContextFrameType frame_type) {
-    frame_type_ = frame_type;
-  }
 
   network::mojom::FetchRequestMode GetFetchRequestMode() const {
     return fetch_request_mode_;
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index dc1a2a6..67ac126 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -1730,7 +1730,6 @@
 external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html [ WontFix ]
 external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html [ WontFix ]
 external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html [ WontFix ]
-external/wpt/clipboard-apis/async-write-duplicate-mime-type-manual.https.html [ WontFix ]
 external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html [ WontFix ]
 external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html [ WontFix ]
 external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index dcd71be..1f52c67 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -65,20 +65,8 @@
 # available in child/sibling frames.  This assumption doesn't hold with User
 # Activation v2 (UAv2).
 crbug.com/906791 external/wpt/fullscreen/api/element-ready-check-allowed-cross-origin-manual.sub.html [ Timeout ]
-crbug.com/860713 bluetooth/characteristic/notifications/notification-after-disconnection.html [ Failure ]
 crbug.com/860713 external/wpt/bluetooth/requestDevice/cross-origin-iframe.sub.https.html [ Failure Timeout ]
-crbug.com/860713 external/wpt/bluetooth/requestDevice/request-from-iframe.https.html [ Failure Timeout ]
 crbug.com/860713 external/wpt/bluetooth/requestDevice/request-from-sandboxed-iframe.https.html [ Failure Timeout ]
-crbug.com/860713 external/wpt/bluetooth/server/disconnect/detach-gc.https.html [ Failure Timeout ]
-crbug.com/860713 external/wpt/bluetooth/server/disconnect/gc-detach.https.html [ Failure Timeout ]
-crbug.com/860713 external/wpt/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/service/getCharacteristic/gen-reconnect-during.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/service/getCharacteristics/gen-reconnect-during-with-uuid.https.html [ Failure ]
-crbug.com/860713 external/wpt/bluetooth/service/getCharacteristics/gen-reconnect-during.https.html [ Failure ]
 
 # The following tests passes only with User Activation v2 (UAv2) disabled.
 crbug.com/908841 external/wpt/fullscreen/api/element-ready-check-containing-iframe-manual.html [ Timeout ]
@@ -176,12 +164,10 @@
 crbug.com/678482 virtual/binary-for-devtools/http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ]
 crbug.com/678491 http/tests/misc/webtiming-no-origin.html [ Crash Pass ]
 crbug.com/765779 http/tests/loading/bad-server-subframe.html [ Failure ]
-crbug.com/793127 external/wpt/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html [ Crash ]
 crbug.com/793127 http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ]
 crbug.com/793127 virtual/outofblink-cors/http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ]
 crbug.com/793127 virtual/feature-policy-for-sandbox/http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ]
 crbug.com/801992 http/tests/misc/iframe-script-modify-attr.html [ Pass Crash ]
-crbug.com/807675 http/tests/images/image-decode-in-frame.html [ Crash Failure ]
 crbug.com/819800 external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Failure ]
 crbug.com/822372 http/tests/printing/cross-site-frame-scrolled.html [ Crash ]
 crbug.com/822372 http/tests/printing/cross-site-frame.html [ Crash ]
@@ -269,6 +255,7 @@
 crbug.com/504613 crbug.com/524248 [ Mac ] paint/images/image-backgrounds-not-antialiased.html [ Failure ]
 
 crbug.com/619103 paint/invalidation/background/background-resize-width.html [ Failure Pass ]
+crbug.com/619103 virtual/disable-blink-gen-property-trees/paint/invalidation/background/background-resize-width.html [ Failure Pass ]
 
 crbug.com/784956 fast/history/frameset-repeated-name.html [ Pass Failure ]
 
@@ -2902,9 +2889,6 @@
 
 crbug.com/723741 virtual/threaded/http/tests/devtools/tracing/idle-callback.js [ Failure Crash Pass Timeout ]
 
-# Sheriff 2019-03-07
-crbug.com/939406 external/wpt/html/browsers/windows/embedded-opener-remove-frame.html [ Failure ]
-
 # Sheriff 2019-03-08
 crbug.com/940050 virtual/threaded/external/wpt/animation-worklet/playback-rate.https.html [ Failure Timeout ]
 
@@ -3382,10 +3366,6 @@
 crbug.com/906959 external/wpt/referrer-policy/unset-referrer-policy/http-rp/same-origin/http-http/shared-worker/no-redirect/insecure-protocol.http.html [ Failure ]
 crbug.com/906959 external/wpt/referrer-policy/unset-referrer-policy/meta-referrer/same-origin/http-http/shared-worker/keep-origin-redirect/insecure-protocol.http.html [ Failure ]
 crbug.com/906959 external/wpt/referrer-policy/unset-referrer-policy/meta-referrer/same-origin/http-http/shared-worker/no-redirect/insecure-protocol.http.html [ Failure ]
-crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer/http-rp/same-origin/http-http/shared-worker/keep-origin-redirect/generic.http.html [ Failure ]
-crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer/http-rp/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Failure ]
-crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer/meta-referrer/same-origin/http-http/shared-worker/keep-origin-redirect/generic.http.html [ Failure ]
-crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer/meta-referrer/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Failure ]
 crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer-when-downgrade/http-rp/same-origin/http-http/shared-worker/keep-origin-redirect/insecure-protocol.http.html [ Failure ]
 crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer-when-downgrade/http-rp/same-origin/http-http/shared-worker/no-redirect/insecure-protocol.http.html [ Failure ]
 crbug.com/906959 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer-when-downgrade/meta-referrer/same-origin/http-http/shared-worker/keep-origin-redirect/insecure-protocol.http.html [ Failure ]
@@ -3930,7 +3910,6 @@
 crbug.com/626703 external/wpt/html/browsers/windows/noreferrer-window-name.html [ Timeout ]
 crbug.com/626703 crbug.com/930297 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Timeout Crash ]
 crbug.com/626703 crbug.com/930297 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html [ Timeout Crash ]
-crbug.com/626703 external/wpt/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html [ Failure ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html [ Failure ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/relevant-mutations.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-video-element/video_initially_paused.html [ Failure ]
@@ -4281,7 +4260,6 @@
 # Off-the-main-thread service worker script fetch.
 # This fails because CORS check?: Error message is like:
 # Access to XMLHttpRequest at 'foobar://abcd' (redirected from 'http://web-platform.test:8001/xhr/resources/redirect.py?location=foobar://abcd&code=301') from origin 'http://web-platform.test:8001' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-crbug.com/924043 virtual/omt-worker-fetch/external/wpt/xhr/send-redirect-bogus-sync.htm [ Timeout ]
 # Following tests are crashing because module script fetcher for service worker
 # doesn't set CSP correctly.
 crbug.com/937757 external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Crash ]
@@ -4380,12 +4358,6 @@
 crbug.com/660384 external/wpt/webmessaging/without-ports/001.html [ Failure ]
 crbug.com/660384 external/wpt/webmessaging/with-options/broken-origin.html [ Failure ]
 
-# These tests used to pass because javascript urls would commit synchronously.
-# Now they need PostMessageTimer to not be cancelled when a javascript: url
-# replaces the existing document.
-crbug.com/914587 external/wpt/webmessaging/with-ports/018.html [ Timeout ]
-crbug.com/914587 external/wpt/webmessaging/without-ports/018.html [ Timeout ]
-
 # Added 2016-12-12
 crbug.com/610835 http/tests/security/XFrameOptions/x-frame-options-deny-multiple-clients.html [ Failure Pass ]
 crbug.com/610835 virtual/outofblink-cors/http/tests/security/XFrameOptions/x-frame-options-deny-multiple-clients.html [ Failure Pass ]
@@ -5040,14 +5012,8 @@
 crbug.com/807110 external/wpt/media-source/mediasource-is-type-supported.html [ Failure Pass ]
 crbug.com/807110 external/wpt/media-source/mediasource-sequencemode-append-buffer.html [ Failure Pass ]
 crbug.com/807110 external/wpt/media-source/mediasource-sourcebuffer-mode-timestamps.html [ Failure Pass ]
-crbug.com/825444 [ Mac ] media/video-rotation.html [ Crash Failure Pass ]
-crbug.com/825444 [ Mac ] virtual/video-surface-layer/media/video-rotation.html [ Crash Failure Pass ]
-crbug.com/794338 [ Linux ] media/video-rotation.html [ Failure Pass ]
-crbug.com/794338 [ Win ] media/video-rotation.html [ Failure Pass ]
-crbug.com/794338 [ Android ] media/video-rotation.html [ Failure Pass ]
-crbug.com/794338 [ Linux ] virtual/video-surface-layer/media/video-rotation.html [ Failure Pass ]
-crbug.com/794338 [ Win ] virtual/video-surface-layer/media/video-rotation.html [ Failure Pass ]
-crbug.com/794338 [ Android ] virtual/video-surface-layer/media/video-rotation.html [ Failure Pass ]
+crbug.com/794338 media/video-rotation.html [ Failure Pass ]
+crbug.com/794338 virtual/video-surface-layer/media/video-rotation.html [ Failure Pass ]
 crbug.com/811605 media/video-poster-after-loadedmetadata.html [ Failure Pass ]
 crbug.com/811605 virtual/video-surface-layer/media/video-poster-after-loadedmetadata.html [ Failure Pass ]
 crbug.com/860368 virtual/video-surface-layer/media/autoplay/webaudio-audio-context-resume.html  [ Pass Failure ]
@@ -5187,7 +5153,6 @@
 crbug.com/833658 [ Linux ] media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 crbug.com/833658 [ Win ] media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 crbug.com/833658 [ Mac ] media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
-crbug.com/833100 [ Mac ] external/wpt/battery-status/battery-full-manual.https.html [ Failure ]
 
 # Sheriff 2018-04-23
 crbug.com/833331 [ Win10 ] inspector-protocol/page/pageNavigateToFragment.js [ Pass Failure ]
@@ -5968,10 +5933,6 @@
 # WebXR feature policy feature name in Chrome doesn't match spec.
 crbug.com/924670 external/wpt/webvr/webvr-supported-by-feature-policy.html [ Failure ]
 
-# This test requires FeaturePolicyForSandbox flag.
-crbug.com/791017 external/wpt/feature-policy/feature-policy-for-sandbox/feature-propagation-to-auxiliary-context.html [ Failure ]
-crbug.com/791017 virtual/unified-autoplay/external/wpt/feature-policy/feature-policy-for-sandbox/feature-propagation-to-auxiliary-context.html [ Failure ]
-
 # Sheriff 2019-01-25
 crbug.com/925325 [ Mac ] storage/indexeddb/index-population.html [ Pass Failure ]
 
@@ -6050,7 +6011,6 @@
 crbug.com/935689 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-fixed-invalid.html [ Failure Pass ]
 crbug.com/935689 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-numeric-invalid.html [ Failure Pass ]
 crbug.com/935689 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-symbolic-invalid.html [ Failure Pass ]
-crbug.com/935690 virtual/video-surface-layer/media/video-played-ranges-1.html [ Failure ]
 
 # Sheriff 2019-02-26
 crbug.com/936083 external/wpt/import-maps/builtin-import-scheme.tentative.html [ Failure Pass ]
@@ -6109,7 +6069,7 @@
 crbug.com/937811 [ Win Release ] virtual/binary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ]
 crbug.com/937811 [ Win Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ]
 crbug.com/937811 [ Win Release ] virtual/binary-for-devtools/http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ]
-crbug.com/935689 [ Linux Debug ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function.html [ Failure Pass ]
+crbug.com/935689 [ Mac Linux Debug ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function.html [ Failure Pass ]
 crbug.com/937858 [ Debug ] external/wpt/ambient-light/AmbientLightSensor.https.html [ Pass Failure ]
 crbug.com/937902 [ Linux Debug ] virtual/disable-blink-gen-property-trees/compositing/overflow/overflow-scroll-with-local-background.html [ Pass Failure ]
 crbug.com/937991 [ Win7 Release ] http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ]
@@ -6164,3 +6124,7 @@
 # Trooper 2019-03-19
 crbug.com/836242 [ Mac ] external/wpt/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html [ Pass Failure ]
 
+# Sheriff 2019-03-20
+crbug.com/943907 [ Mac10.10 Mac10.11 ] fast/forms/validation-bubble-appearance-escape.html [ Pass Failure ]
+crbug.com/943907 [ Mac10.10 Mac10.11 ] fast/forms/validation-bubble-device-emulation-change.html [ Pass Failure ]
+crbug.com/943907 [ Mac10.10 Mac10.11 ] fast/forms/validation-bubble-device-emulation.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html
index 618bdf76..1d2aacb 100644
--- a/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html
+++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-navigator-clipboard-basics.https.html
@@ -21,26 +21,33 @@
 promise_test(async () => {
   await getPermissions();
   const blob = new Blob(["hello"], {type: 'text/plain'});
-  await navigator.clipboard.write([blob]);
-}, "navigator.clipboard.write([text/plain Blob]) succeeds");
+  await navigator.clipboard.write({'text/plain': blob});
+}, "navigator.clipboard.write({string : text/plain Blob}) succeeds");
 
 promise_test(async t => {
   await getPermissions();
   await promise_rejects(t, new TypeError(),
                          navigator.clipboard.write());
-}, "navigator.clipboard.write() fails (expect [Blob])");
+}, "navigator.clipboard.write() fails (expect {string : Blob})");
 
 promise_test(async t => {
   await getPermissions();
   await promise_rejects(t, new TypeError(),
                          navigator.clipboard.write(null));
-}, "navigator.clipboard.write(null) fails (expect [Blob])");
+}, "navigator.clipboard.write(null) fails (expect {string : Blob})");
 
 promise_test(async t => {
   await getPermissions();
   await promise_rejects(t, new TypeError(),
                          navigator.clipboard.write("Bad string"));
-}, "navigator.clipboard.write(DOMString) fails (expect [Blob])");
+}, "navigator.clipboard.write(DOMString) fails (expect {string : Blob})");
+
+promise_test(async t => {
+  await getPermissions();
+  const blob = new Blob(["hello"], {type: 'text/plain'});
+  await promise_rejects(t, 'NotAllowedError',
+                         navigator.clipboard.write(blob));
+}, "navigator.clipboard.write(Blob) fails (expect {string : Blob})");
 
 promise_test(async () => {
   await getPermissions();
@@ -56,9 +63,7 @@
 promise_test(async () => {
   await getPermissions();
   const result = await navigator.clipboard.read();
-  assert_true(result instanceof Array);
-  assert_true(result[0] instanceof Blob);
-  assert_equals(typeof result, "object");
+  assert_true(result instanceof Object);
 }, "navigator.clipboard.read() succeeds");
 
 promise_test(async () => {
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html
index 7be86d9..b10933b 100644
--- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html
+++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-blobtext.https.html
@@ -14,10 +14,10 @@
 
     const blobInput = new Blob([textInput], {type: 'text/plain'});
 
-    await navigator.clipboard.write([blobInput]);
+    await navigator.clipboard.write({'text/plain': blobInput});
     const blobsOutput = await navigator.clipboard.read();
-    assert_equals(blobsOutput.length, 1);
-    const blobOutput = blobsOutput[0];
+    assert_equals(Object.keys(blobsOutput).length, 1);
+    const blobOutput = blobsOutput["text/plain"];
     assert_equals(blobOutput.type, "text/plain");
 
     const textOutput = await (new Response(blobOutput)).text();
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html
index 62e73a0..cb0c7ba9 100644
--- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html
+++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-blobtext-read-text.https.html
@@ -12,7 +12,7 @@
 
     const blobInput = new Blob([textInput], {type: 'text/plain'});
 
-    await navigator.clipboard.write([blobInput]);
+    await navigator.clipboard.write({'text/plain': blobInput});
     const textOutput = await navigator.clipboard.readText();
 
     assert_equals(textOutput, textInput);
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-duplicate-mime-type.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-duplicate-mime-type.https.html
deleted file mode 100644
index 1d54dd4..0000000
--- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-duplicate-mime-type.https.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>
-  Async Clipboard write duplicate mime type test
-</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../http/tests/resources/permissions-helper.js"></script>
-
-<script>
-promise_test(async t => {
-  await PermissionsHelper.setPermission('clipboard-write', 'granted');
-
-  const blobText = new Blob(["test text"], {type: 'text/plain'});
-  const blobText2 = new Blob(["test text"], {type: 'text/plain'});
-
-  assert_equals(blobText.type, "text/plain");
-  assert_equals(blobText2.type, "text/plain");
-
-  await promise_rejects(t, 'NotAllowedError',
-      navigator.clipboard.write([blobText, blobText2]));
-}, "Verify write and read clipboard (multiple blobs)");
-</script>
diff --git a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html
index 2dfeb5d9..e1c1f22 100644
--- a/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html
+++ b/third_party/blink/web_tests/clipboard/async-clipboard/async-write-text-read-blobtext.https.html
@@ -12,8 +12,8 @@
 
     await navigator.clipboard.writeText(textInput);
     const blobsOutput = await navigator.clipboard.read();
-    assert_equals(blobsOutput.length, 1);
-    const blobOutput = blobsOutput[0];
+    assert_equals(Object.keys(blobsOutput).length, 1);
+    const blobOutput = blobsOutput["text/plain"];
     assert_equals(blobOutput.type, "text/plain");
 
     const textOutput = await (new Response(blobOutput)).text();
diff --git a/third_party/blink/web_tests/display-lock/activation/scroll-into-view-beforeactivate.html b/third_party/blink/web_tests/display-lock/activation/scroll-into-view-beforeactivate.html
new file mode 100644
index 0000000..c410eeaa
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/activation/scroll-into-view-beforeactivate.html
@@ -0,0 +1,75 @@
+<!doctype HTML>
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<style>
+  div {
+    contain: style layout;
+  }
+</style>
+<div id="outermost">
+  Outermost
+  <div id="outer">
+    Outer
+    <div id="inner">
+      Inner
+      <div id="innermost">
+        Innermost
+      </div>
+    </div>
+  </div>
+</div>
+<script>
+'use strict';
+function prepareTest() {
+  return Promise.all([
+    outer.displayLock.acquire({ timeout: Infinity, activatable: true }),
+    inner.displayLock.acquire({ timeout: Infinity, activatable: true })
+  ]);
+}
+
+promise_test(() => {
+  return new Promise((resolve, reject) => {
+    prepareTest().then(() => {
+      assert_false(outermost.displayLock.locked);
+      assert_true(outer.displayLock.locked);
+      assert_true(inner.displayLock.locked);
+      assert_false(innermost.displayLock.locked);
+
+      let innerPromise = new Promise((resolve, reject) => {
+        inner.onbeforeactivate = (e) => {
+          assert_equals(e.activatedElement, innermost);
+          resolve();
+        }
+      });
+
+      let outerPromise = new Promise((resolve, reject) => {
+        outer.onbeforeactivate = (e) => {
+          assert_equals(e.activatedElement, innermost);
+          // Resolve if this is directly targeted to #outer,
+          // instead of bubbling here.
+          if (e.target == outer)
+            resolve();
+        }
+      });
+
+      let outermostPromise = new Promise((resolve, reject) => {
+        outermost.onbeforeactivate = (e) => {
+          assert_equals(e.activatedElement, innermost);
+          assert_not_equals(e.target, outermost);
+          // Resolve if this is targeted to #outer, which is
+          // dispatched after the event targeted to #inner.
+          if (e.target == outer)
+            resolve();
+        }
+      });
+
+      innermost.onbeforeactivate = reject;
+      // Navigating to element in locked subtree should fire beforeactivate
+      // on locked ancestors, but not itself.
+      innermost.scrollIntoView();
+      Promise.all([innerPromise, outerPromise, outermostPromise]).then(resolve);
+    });
+  });
+}, "Activation through scrollIntoView fires beforeactivate on locked ancestor");
+</script>
diff --git a/third_party/blink/web_tests/display-lock/activation/scroll-into-view-expected.html b/third_party/blink/web_tests/display-lock/activation/scroll-into-view-expected.html
new file mode 100644
index 0000000..c07dd441
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/activation/scroll-into-view-expected.html
@@ -0,0 +1,42 @@
+<!doctype HTML>
+
+<style>
+.spacer {
+  width: 150px;
+  height: 3000px;
+  background: lightblue;
+}
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightgreen;
+}
+#target {
+  width: 100px;
+  height: 100px;
+  background: green;
+}
+</style>
+
+<div class="spacer"></div>
+<div id="container"><div id="target"></div></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function notifyDone() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  document.getElementById("target").scrollIntoView();
+  requestAnimationFrame(notifyDone);
+}
+
+window.onload = () => { requestAnimationFrame(runTest); };
+</script>
diff --git a/third_party/blink/web_tests/display-lock/activation/scroll-into-view.html b/third_party/blink/web_tests/display-lock/activation/scroll-into-view.html
new file mode 100644
index 0000000..3a9baea
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/activation/scroll-into-view.html
@@ -0,0 +1,43 @@
+<!doctype HTML>
+
+<style>
+.spacer {
+  width: 150px;
+  height: 3000px;
+  background: lightblue;
+}
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightgreen;
+}
+#target {
+  width: 100px;
+  height: 100px;
+  background: green;
+}
+</style>
+
+<div class="spacer"></div>
+<div id="container"><div id="target"></div></div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, activatable: true }).then(() => {
+    document.getElementById("target").scrollIntoView();
+    requestAnimationFrame(finishTest);
+  });
+}
+
+window.onload = () => { requestAnimationFrame(runTest); };
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
index 2d2ebf6..7d2cba8b 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
@@ -13,23 +13,29 @@
 
 promise_test(async () => {
   const blob = new Blob(["hello"], {type: 'text/plain'});
-  await navigator.clipboard.write([blob]);
-}, "navigator.clipboard.write([text/plain Blob]) succeeds");
+  await navigator.clipboard.write({'text/plain': blob});
+}, "navigator.clipboard.write({string : text/plain Blob}) succeeds");
 
 promise_test(async t => {
   await promise_rejects(t, new TypeError(),
                          navigator.clipboard.write());
-}, "navigator.clipboard.write() fails (expect [Blob])");
+}, "navigator.clipboard.write() fails (expect {string : Blob})");
 
 promise_test(async t => {
   await promise_rejects(t, new TypeError(),
                          navigator.clipboard.write(null));
-}, "navigator.clipboard.write(null) fails (expect [Blob])");
+}, "navigator.clipboard.write(null) fails (expect {string : Blob})");
 
 promise_test(async t => {
   await promise_rejects(t, new TypeError(),
                          navigator.clipboard.write("Bad string"));
-}, "navigator.clipboard.write(DOMString) fails (expect [Blob])");
+}, "navigator.clipboard.write(DOMString) fails (expect {string : Blob})");
+
+promise_test(async t => {
+  const blob = new Blob(["hello"], {type: 'text/plain'});
+  await promise_rejects(t, 'NotAllowedError',
+                         navigator.clipboard.write(blob));
+}, "navigator.clipboard.write(Blob) fails (expect {string : Blob})");
 
 promise_test(async () => {
   await navigator.clipboard.writeText("New clipboard text");
@@ -45,14 +51,12 @@
         'http://localhost:8001/clipboard-apis/resources/greenbox.png');
   const image = await fetched.blob();
 
-  await navigator.clipboard.write([image]);
-}, "navigator.clipboard.write([image/png Blob]) succeeds");
+  await navigator.clipboard.write({'image/png' : image});
+}, "navigator.clipboard.write({string : image/png Blob}) succeeds");
 
 promise_test(async () => {
   const result = await navigator.clipboard.read();
-  assert_true(result instanceof Array);
-  assert_true(result[0] instanceof Blob);
-  assert_equals(typeof result, "object");
+  assert_true(result instanceof Object);
 }, "navigator.clipboard.read() succeeds");
 
 promise_test(async () => {
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html
index e616b5e..3666c93 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobs-read-blobs-manual.https.html
@@ -19,12 +19,13 @@
   assert_equals(blobText.type, "text/plain");
   assert_equals(blobImage.type, "image/png");
 
-  await navigator.clipboard.write([blobText, blobImage]);
+  await navigator.clipboard.write(
+        {"text/plain" : blobText, "image/png" : blobImage});
   const output = await navigator.clipboard.read();
 
-  assert_equals(output.length, 2);
-  assert_equals(output[0].type, "text/plain");
-  assert_equals(output[1].type, "image/png");
+  assert_equals(Object.keys(output).length, 2);
+  assert_equals(output["text/plain"].type, "text/plain");
+  assert_equals(output["image/png"].type, "image/png");
 }, "Verify write and read clipboard (multiple blobs)");
 </script>
 <p>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html
index bc8511e..44c5742 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-blobtext-manual.https.html
@@ -10,10 +10,10 @@
   promise_test(async t => {
     const blobInput = new Blob([textInput], {type: 'text/plain'});
 
-    await navigator.clipboard.write([blobInput]);
+    await navigator.clipboard.write({'text/plain': blobInput});
     const blobsOutput = await navigator.clipboard.read();
-    assert_equals(blobsOutput.length, 1);
-    const blobOutput = blobsOutput[0];
+    assert_equals(Object.keys(blobsOutput).length, 1);
+    const blobOutput = blobsOutput["text/plain"];
     assert_equals(blobOutput.type, "text/plain");
 
     const textOutput = await (new Response(blobOutput)).text();
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html
index b1b85de6..c991f1f 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-blobtext-read-text-manual.https.html
@@ -8,7 +8,7 @@
   promise_test(async t => {
     const blobInput = new Blob([textInput], {type: 'text/plain'});
 
-    await navigator.clipboard.write([blobInput]);
+    await navigator.clipboard.write({'text/plain': blobInput});
     const textOutput = await navigator.clipboard.readText();
 
     assert_equals(textOutput, textInput);
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-duplicate-mime-type-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-duplicate-mime-type-manual.https.html
deleted file mode 100644
index 8e249fc..0000000
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-duplicate-mime-type-manual.https.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>
-  Async Clipboard write duplicate mime type test
-</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<script>
-promise_test(async t => {
-  const blobText = new Blob(["test text"], {type: 'text/plain'});
-  const blobText2 = new Blob(["test text"], {type: 'text/plain'});
-
-  assert_equals(blobText.type, "text/plain");
-  assert_equals(blobText2.type, "text/plain");
-
-
-  await promise_rejects(t, 'NotAllowedError',
-      navigator.clipboard.write([blobText, blobText2]));
-}, "Verify write and read clipboard (multiple blobs)");
-</script>
-<p>
-  Note: This is a manual test because it writes/reads to the shared system
-  clipboard and thus cannot be run async with other tests that might interact
-  with the clipboard.
-</p>
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html
index 76d3d872..2a32348 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-image-read-image-manual.https.html
@@ -40,10 +40,10 @@
   const blobInput = await loadBlob('resources/greenbox.png');
 
   assert_equals(blobInput.type, "image/png");
-  await navigator.clipboard.write([blobInput]);
+  await navigator.clipboard.write({"image/png" : blobInput});
   const blobsOutput = await navigator.clipboard.read();
-  assert_equals(blobsOutput.length, 1);
-  const blobOutput = blobsOutput[0];
+  assert_equals(Object.keys(blobsOutput).length, 1);
+  const blobOutput = blobsOutput["image/png"];
   assert_equals(blobOutput.type, "image/png");
 
   document.getElementById('image-on-clipboard').src =
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html
index b54fa60..24e6b6e 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-blobtext-manual.https.html
@@ -8,8 +8,8 @@
   promise_test(async t => {
     await navigator.clipboard.writeText(textInput);
     const blobsOutput = await navigator.clipboard.read();
-    assert_equals(blobsOutput.length, 1);
-    const blobOutput = blobsOutput[0];
+    assert_equals(Object.keys(blobsOutput).length, 1);
+    const blobOutput = blobsOutput["text/plain"];
     assert_equals(blobOutput.type, "text/plain");
 
     const textOutput = await (new Response(blobOutput)).text();
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt
+++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt
+++ /dev/null
diff --git a/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash-expected.txt b/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash-expected.txt
deleted file mode 100644
index 0a7ab54..0000000
--- a/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash-expected.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-CONSOLE WARNING: line 19: We don't execute document.execCommand() this time, because it is called recursively.
-x
-x This test passes if it doesn't crash.
diff --git a/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash.html b/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash.html
index dcf3e5cf..b3278b3 100644
--- a/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash.html
+++ b/third_party/blink/web_tests/fast/parser/nested-fragment-parser-crash.html
@@ -1,15 +1,16 @@
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 x<h4><strike>x
 This test passes if it doesn't crash.
 <script>
-  if (window.testRunner)
-    testRunner.dumpAsText();
-
   var counter = 0;
   window.onload=function(){
-    document.execCommand("SelectAll");
-    document.designMode="on";
-    document.execCommand("Indent");
-    document.execCommand("InsertOrderedList", false);
+    test(function(){
+      document.execCommand("SelectAll");
+      document.designMode="on";
+      document.execCommand("Indent");
+      document.execCommand("InsertOrderedList", false);
+    });
   };
   function handler() {
     // This constant is somewhat magic. It's the smallest constant such that
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/dark-mode/image-filter-all/text-on-backgrounds-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt
rename to third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/dark-mode/image-filter-all/text-on-backgrounds-expected.txt
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/dark-mode/paint/dark-mode/image-filter-all/text-on-backgrounds-expected.txt
similarity index 100%
copy from third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt
copy to third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/dark-mode/paint/dark-mode/image-filter-all/text-on-backgrounds-expected.txt
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/high-contrast-mode/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/high-contrast-mode/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt
deleted file mode 100644
index 3b2860a..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/high-contrast-mode/paint/high-contrast-mode/image-filter-all/text-on-backgrounds-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Red on white Green on white Blue on white
-Red on black Green on black Blue on black
-Black on red Black on green Black on blue
-White on red White on green White on blue
diff --git a/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html b/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html
index 6c64664..9018086 100644
--- a/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html
+++ b/third_party/blink/web_tests/http/tests/clipboard/async-write-blobs-read-blobs.html
@@ -23,11 +23,12 @@
   assert_equals(blobText.type, "text/plain");
   assert_equals(blobImage.type, "image/png");
 
-  await navigator.clipboard.write([blobText, blobImage]);
+  await navigator.clipboard.write(
+      {"text/plain" : blobText, "image/png" : blobImage});
   const output = await navigator.clipboard.read();
 
-  assert_equals(output.length, 2);
-  assert_equals(output[0].type, "text/plain");
-  assert_equals(output[1].type, "image/png");
+  assert_equals(Object.keys(output).length, 2);
+  assert_equals(output["text/plain"].type, "text/plain");
+  assert_equals(output["image/png"].type, "image/png");
 }, "Verify write and read clipboard (multiple blobs)");
 </script>
diff --git a/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html b/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html
index 1e8c4a80..cc8cbd0d 100644
--- a/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html
+++ b/third_party/blink/web_tests/http/tests/clipboard/async-write-image-read-image.html
@@ -44,10 +44,10 @@
   const blobInput = await loadBlob('resources/greenbox.png');
 
   assert_equals(blobInput.type, "image/png");
-  await navigator.clipboard.write([blobInput]);
+  await navigator.clipboard.write({"image/png" : blobInput});
   const blobsOutput = await navigator.clipboard.read();
-  assert_equals(blobsOutput.length, 1);
-  const blobOutput = blobsOutput[0];
+  assert_equals(Object.keys(blobsOutput).length, 1);
+  const blobOutput = blobsOutput["image/png"];
   assert_equals(blobOutput.type, "image/png");
 
   document.getElementById('image-on-clipboard').src =
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/elements-panel-styles-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/elements-panel-styles-expected.txt
index f570cb1..470ddee 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/elements-panel-styles-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/elements-panel-styles-expected.txt
@@ -60,24 +60,24 @@
     -webkit-font-smoothing: subpixel-antialiased;
 
 [expanded] 
-#container .foo { (elements-panel-styles.css:17 -> elements-panel-styles.css:17:18)
+#container .foo { (elements-pa…yles.css:17 -> elements-panel-styles.css:17:18)
     font-style: italic !important;
 
 [expanded] 
-body .foo { (elements-panel-styles.css:6 -> elements-panel-styles.css:6:12)
+body .foo { (elements-pa…tyles.css:6 -> elements-panel-styles.css:6:12)
 /-- overloaded --/     text-indent: 10px;
 
 [expanded] 
-.foo { (elements-panel-styles.css:53 -> elements-panel-styles.css:53:7)
+.foo { (elements-pa…yles.css:53 -> elements-panel-styles.css:53:7)
 
 [expanded] 
-.foo, .foo::before { (elements-panel-styles.css:34 -> elements-panel-styles.css:34:21)
+.foo, .foo::before { (elements-pa…yles.css:34 -> elements-panel-styles.css:34:21)
     content: "[before Foo]";
     color: blue;
     display: block !important;
 
 [expanded] 
-.foo { (elements-panel-styles.css:21 -> elements-panel-styles.css:21:7)
+.foo { (elements-pa…yles.css:21 -> elements-panel-styles.css:21:7)
 /-- overloaded --/     color: black;
     margin-left: 1px;
     margin: 10px 0 2px;
@@ -111,20 +111,20 @@
 
 ======== Inherited from div#container ========
 [expanded] 
-#container { (elements-panel-styles.css:10 -> elements-panel-styles.css:10:13)
+#container { (elements-pa…yles.css:10 -> elements-panel-styles.css:10:13)
     font-family: serif;
     font-size: 14px;
 /-- overloaded --/     color: red;
 
 ======== Inherited from body ========
 [expanded] 
-body { (elements-panel-styles.css:1 -> elements-panel-styles.css:1:7)
+body { (elements-pa…tyles.css:1 -> elements-panel-styles.css:1:7)
 /-- overloaded --/     font-size: 12px;
 /-- overloaded --/     text-indent: 20px !important;
 
 ======== Inherited from html ========
 [expanded] 
-html { (elements-panel-styles.css:61 -> elements-panel-styles.css:61:7)
+html { (elements-pa…yles.css:61 -> elements-panel-styles.css:61:7)
 /-- overloaded --/     color: magenta !important;
 
 [expanded] 
@@ -133,26 +133,26 @@
 
 ======== Pseudo ::before element ========
 [expanded] 
-.foo::before { (elements-panel-styles.css:57 -> elements-panel-styles.css:57:15)
+.foo::before { (elements-pa…yles.css:57 -> elements-panel-styles.css:57:15)
 
 [expanded] 
-.foo::before { (elements-panel-styles.css:40 -> elements-panel-styles.css:40:15)
+.foo::before { (elements-pa…yles.css:40 -> elements-panel-styles.css:40:15)
     color: red;
 
 [expanded] 
-.foo, .foo::before { (elements-panel-styles.css:34 -> elements-panel-styles.css:34:21)
+.foo, .foo::before { (elements-pa…yles.css:34 -> elements-panel-styles.css:34:21)
     content: "[before Foo]";
 /-- overloaded --/     color: blue;
     display: block !important;
 
 ======== Pseudo ::after element ========
 [expanded] 
-.foo::after { (elements-panel-styles.css:48 -> elements-panel-styles.css:48:14)
+.foo::after { (elements-pa…yles.css:48 -> elements-panel-styles.css:48:14)
     font-family: courier;
     content: "[after Foo 2]";
 
 [expanded] 
-.foo::after { (elements-panel-styles.css:44 -> elements-panel-styles.css:44:14)
+.foo::after { (elements-pa…yles.css:44 -> elements-panel-styles.css:44:14)
 /-- overloaded --/     content: "[after Foo]";
     color: green;
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt
index 5da8cfb..5c165288 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/navigate-styles-sidebar-with-arrow-keys-expected.txt
@@ -9,19 +9,19 @@
 
 Navigating with arrow keys
 Editing: false
-<style>…</style>div#foo {}
+<style>div#foo {}
 
 Editing: false
-<style>…</style>#foo {}
+<style>#foo {}
 
 Editing: false
-<style>…</style>div {}
+<style>div {}
 
 Editing: false
 user agent stylesheetdiv {}
 
 Editing: false
-<style>…</style>div {}
+<style>div {}
 
 Typing should start editing
 Editing: true
@@ -29,7 +29,7 @@
 
 Pressing escape again should restore focus
 Editing: false
-<style>…</style>div {}
+<style>div {}
 
 Pressing enter should start editing selector
 Editing: true
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/commit-selector-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/commit-selector-expected.txt
index a7c1c88..6b12233b 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/commit-selector-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/commit-selector-expected.txt
@@ -6,7 +6,7 @@
     color: red;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
@@ -24,7 +24,7 @@
     color: red;
 
 [expanded] 
-hr, #inspected { (<style>…</style>)
+hr, #inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
@@ -42,7 +42,7 @@
     color: red;
 
 [expanded] [no-affect] 
-#inspectedChanged { (<style>…</style>)
+#inspectedChanged { (<style>)
     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/cssom-media-insert-crash-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/cssom-media-insert-crash-expected.txt
index 101d08a..e9d94629a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/cssom-media-insert-crash-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/cssom-media-insert-crash-expected.txt
@@ -4,12 +4,12 @@
 element.style { ()
 
 [expanded] 
-#box { (<style>…</style>)
+#box { (<style>)
     color: white;
     background: red;
 
 [expanded] 
-div { (<style>…</style>)
+div { (<style>)
     border: 1px solid black;
 /-- overloaded --/     background-color: white;
     padding: 20px;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/disable-property-workingcopy-update-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/disable-property-workingcopy-update-expected.txt
index bbcc7de..f0ba032 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/disable-property-workingcopy-update-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/disable-property-workingcopy-update-expected.txt
@@ -24,7 +24,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (disable-propert…y-update.css:1 -> disable-property-workingcopy-update.css:1:13)
+#inspected { (disable-pro…pdate.css:1 -> disable-property-workingcopy-update.css:1:13)
 /-- overloaded --/ /-- disabled --/     /* font-weight: bold; */
 
 [expanded] 
@@ -50,7 +50,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (disable-propert…y-update.css:1 -> disable-property-workingcopy-update.css:1:13)
+#inspected { (disable-pro…pdate.css:1 -> disable-property-workingcopy-update.css:1:13)
     font-weight: bold;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/dynamic-style-tag-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/dynamic-style-tag-expected.txt
index e7dc626..8381852 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/dynamic-style-tag-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/dynamic-style-tag-expected.txt
@@ -58,27 +58,27 @@
     color: red;
 
 [expanded] 
-.inline-style-created-by-script-with-source-url { (inlineStyleCrea…ByScript.css:1 -> inlineStyleCreatedByScript.css:1:50)
+.inline-style-created-by-script-with-source-url { (inlineStyle…cript.css:1 -> inlineStyleCreatedByScript.css:1:50)
 /-- overloaded --/     color: grey;
 
 [expanded] 
-.inline-style-created-by-script { (<style>…</style>)
+.inline-style-created-by-script { (<style>)
 /-- overloaded --/     color: orange;
 
 [expanded] 
-.inline-style-added-by-document-write-with-source-url { (inlineStyleAdde…entWrite.css:2 -> inlineStyleAddedByDocumentWrite.css:2:56)
+.inline-style-added-by-document-write-with-source-url { (inlineStyle…Write.css:2 -> inlineStyleAddedByDocumentWrite.css:2:56)
 /-- overloaded --/     color: yellow;
 
 [expanded] 
-.inline-style-added-by-parser-in-document-write { (<style>…</style>)
+.inline-style-added-by-parser-in-document-write { (<style>)
 /-- overloaded --/     color: blue;
 
 [expanded] 
-.inline-style-added-by-parser-with-source-url { (inlineStyleAddedByParser.css:2 -> inlineStyleAddedByParser.css:2:48)
+.inline-style-added-by-parser-with-source-url { (inlineStyle…arser.css:2 -> inlineStyleAddedByParser.css:2:48)
 /-- overloaded --/     color: green;
 
 [expanded] 
-.inline-style-added-by-parser { (dynamic-style-tag.html:3 -> dynamic-style-tag.html:3:45)
+.inline-style-added-by-parser { (dynamic-sty…-tag.html:3 -> dynamic-style-tag.html:3:45)
 /-- overloaded --/     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/edit-media-text-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/edit-media-text-expected.txt
index 9f66f5c..25b8e3b3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/edit-media-text-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/edit-media-text-expected.txt
@@ -7,12 +7,12 @@
 
 [expanded] 
 @media screen and (max-device-width: 100000px)
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: blue;
 
 [expanded] 
 @media screen and (max-device-width: 100000px)
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
@@ -31,12 +31,12 @@
 
 [expanded] 
 @media screen and (max-device-width: 99999px)
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: blue;
 
 [expanded] 
 @media screen and (max-device-width: 99999px)
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
@@ -54,11 +54,11 @@
     color: red;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: blue;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/empty-background-url-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/empty-background-url-expected.txt
index e1db018..ea64886 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/empty-background-url-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-1/empty-background-url-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     background-image: url();
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/add-import-rule-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/add-import-rule-expected.txt
index 67464ce..a20d013 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/add-import-rule-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/add-import-rule-expected.txt
@@ -7,7 +7,7 @@
 element.style { ()
 
 [expanded] 
-span { (<style>…</style>)
+span { (<style>)
     color: red;
 
 ======== Inherited from html ========
@@ -22,7 +22,7 @@
 element.style { ()
 
 [expanded] 
-span { (data:text/css,s…color:green}:1 -> data:text/css,span{color:green}:1:6)
+span { (data:text/c…or:green}:1 -> data:text/css,span{color:green}:1:6)
     color: green;
 
 ======== Inherited from html ========
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/cssom-shorthand-important-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/cssom-shorthand-important-expected.txt
index 323d147..c6b9eb6 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/cssom-shorthand-important-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/cssom-shorthand-important-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     margin-top: 10px;
     padding: 10px 50px !important;
         padding-top: 10px !important;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/force-pseudo-state-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/force-pseudo-state-expected.txt
index 951be4a..9477dd0 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/force-pseudo-state-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/force-pseudo-state-expected.txt
@@ -6,11 +6,11 @@
 element.style { ()
 
 [expanded] 
-div:active, a:active { (<style>…</style>)
+div:active, a:active { (<style>)
     font-weight: bold;
 
 [expanded] 
-div:hover, a:hover { (<style>…</style>)
+div:hover, a:hover { (<style>)
     color: red;
 
 [expanded] 
@@ -39,11 +39,11 @@
 element.style { ()
 
 [expanded] 
-div:active, a:active { (<style>…</style>)
+div:active, a:active { (<style>)
     font-weight: bold;
 
 [expanded] 
-div:focus, a:focus { (<style>…</style>)
+div:focus, a:focus { (<style>)
     border: 1px solid green;
         border-top-color: green;
         border-top-style: solid;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inactive-properties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inactive-properties-expected.txt
index ba85be0..03f57cb4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inactive-properties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inactive-properties-expected.txt
@@ -5,13 +5,13 @@
 display: block;
     block - div user agent stylesheet
 text-align: right;
-    right - #inspected <style>…</style>
+    right - #inspected <style>
     OVERLOADED -webkit-left - element.style
 [expanded] 
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     text-align: left;
 /-- overloaded --/     text-align: bar;
     text-align: right;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inherited-mixed-case-properties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inherited-mixed-case-properties-expected.txt
index b6989cc..139b8fb 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inherited-mixed-case-properties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inherited-mixed-case-properties-expected.txt
@@ -18,7 +18,7 @@
     CoLoR: blAck;
 
 [expanded] 
-#container { (<style>…</style>)
+#container { (<style>)
     -webkit-FONT-smoothing: antialiased;
 
 ======== Inherited from html ========
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inject-stylesheet-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inject-stylesheet-expected.txt
index 89480a46..342d16d9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inject-stylesheet-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/inject-stylesheet-expected.txt
@@ -2,25 +2,25 @@
 
 Main frame style:
 background-attachment: scroll;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-clip: border-box;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-color: rgb(0, 0, 255);
-    blue - #main <style>…</style>
+    blue - #main <style>
 background-image: none;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-origin: padding-box;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-position-x: 0%;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-position-y: 0%;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-repeat-x: ;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-repeat-y: ;
-    initial - #main <style>…</style>
+    initial - #main <style>
 background-size: auto;
-    initial - #main <style>…</style>
+    initial - #main <style>
 border-bottom-style: solid;
     solid - #main injected stylesheet
 border-left-style: solid;
@@ -40,7 +40,7 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     background: blue;
         background-image: initial;
         background-position-x: initial;
@@ -133,7 +133,7 @@
         background-color: red;
 
 [expanded] 
-body { (inject-styleshe…me-data.html:4 -> inject-stylesheet-iframe-data.html:4:9)
+body { (inject-styl…data.html:4 -> inject-stylesheet-iframe-data.html:4:9)
 /-- overloaded --/     background: green;
     /-- overloaded --/     background-image: initial;
     /-- overloaded --/     background-position-x: initial;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/keyframes-rules-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/keyframes-rules-expected.txt
index 78afa72..713a74e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/keyframes-rules-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/keyframes-rules-expected.txt
@@ -9,7 +9,7 @@
     background-color: white;
 
 [expanded] 
-* { (<style>…</style>)
+* { (<style>)
 /-- overloaded --/     background-color: papayawhip;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/lazy-computed-style-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/lazy-computed-style-expected.txt
index 91f8def..d9605b6 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/lazy-computed-style-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/lazy-computed-style-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     background: gray;
         background-image: initial;
         background-position-x: initial;
@@ -19,12 +19,12 @@
         background-color: gray;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     background-color: black;
     font-family: Courier;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     background-color: green;
 /-- overloaded --/     font-family: Times;
 
@@ -39,39 +39,39 @@
 
 ==== All styles (computed should be there) ====
 background-attachment: scroll;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-clip: border-box;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-color: rgb(128, 128, 128);
-    gray - #inspected <style>…</style>
-    OVERLOADED black - #inspected <style>…</style>
-    OVERLOADED green - #inspected <style>…</style>
+    gray - #inspected <style>
+    OVERLOADED black - #inspected <style>
+    OVERLOADED green - #inspected <style>
 background-image: none;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-origin: padding-box;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-position-x: 0%;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-position-y: 0%;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-repeat-x: ;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-repeat-y: ;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 background-size: auto;
-    initial - #inspected <style>…</style>
+    initial - #inspected <style>
 color: rgb(0, 0, 0);
     -internal-root-color - html user agent stylesheet
 display: block;
     block - div user agent stylesheet
 font-family: Courier;
-    Courier - #inspected <style>…</style>
-    OVERLOADED Times - #inspected <style>…</style>
+    Courier - #inspected <style>
+    OVERLOADED Times - #inspected <style>
 [expanded] 
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     background: gray;
         background-image: initial;
         background-position-x: initial;
@@ -85,12 +85,12 @@
         background-color: gray;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     background-color: black;
     font-family: Courier;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     background-color: green;
 /-- overloaded --/     font-family: Times;
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-emulation-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-emulation-expected.txt
index af5b22c..2e4ce87 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-emulation-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-emulation-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     color: red;
 
 [expanded] 
@@ -23,11 +23,11 @@
 
 [expanded] 
 @media print
-#main { (<style>…</style>)
+#main { (<style>)
     color: black;
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/     color: red;
 
 [expanded] 
@@ -44,11 +44,11 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     color: green;
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/     color: red;
 
 [expanded] 
@@ -65,7 +65,7 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-queries-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-queries-expected.txt
index ea3139e..2375d0a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-queries-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-queries-expected.txt
@@ -13,7 +13,7 @@
     border: 1px solid black;
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     background: blue;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-using-same-url-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-using-same-url-expected.txt
index f3f259d..ece61003 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-using-same-url-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/media-using-same-url-expected.txt
@@ -5,11 +5,11 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     color: white;
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
     background: blue;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-comments-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-comments-expected.txt
index 4d3b33f..0250767 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-comments-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-comments-expected.txt
@@ -5,13 +5,13 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/ /-- disabled --/     /* color: red; */
     color/* color: red */:/* color: red */ green/* color: red */;
 /-- overloaded --/ /-- disabled --/     /* color: red; */
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/ /-- disabled --/     /* color: red; */
     background /* color: red */ :/* color: red */blue/* color: red */;
 /-- overloaded --/ /-- disabled --/     /* color: red; */
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-utf8-bom-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-utf8-bom-expected.txt
index d7eec62..39465a95 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-utf8-bom-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/parse-utf8-bom-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-h1 { (parse-utf8-bom-main.css:3 -> parse-utf8-bom-main.css:3:5)
+h1 { (parse-utf8-…-main.css:3 -> parse-utf8-bom-main.css:3:5)
     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/perform-undo-perform-of-mergable-action-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/perform-undo-perform-of-mergable-action-expected.txt
index a734d1c..00688b6 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/perform-undo-perform-of-mergable-action-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/perform-undo-perform-of-mergable-action-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
 
 [expanded] 
@@ -22,7 +22,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: normal;
 
 [expanded] 
@@ -39,7 +39,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
 
 [expanded] 
@@ -56,7 +56,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: normal;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt
index 7598177..75e211d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt
@@ -30,24 +30,24 @@
 
 ======== Pseudo ::before element ========
 [expanded] 
-[$#inspected:before, $].some-other-selector { (<style>…</style>)
+[$#inspected:before, $].some-other-selector { (<style>)
     content: "BEFORE";
 
 ======== Pseudo ::after element ========
 [expanded] 
-[$#inspected:after$] { (<style>…</style>)
+[$#inspected:after$] { (<style>)
     content: "AFTER";
 
 
 Running: dumpBeforeStyles
 [expanded] 
-[$#inspected:before, $].some-other-selector { (<style>…</style>)
+[$#inspected:before, $].some-other-selector { (<style>)
     content: "BEFORE";
 
 
 Running: dumpAfterStyles
 [expanded] 
-[$#inspected:after$] { (<style>…</style>)
+[$#inspected:after$] { (<style>)
     content: "AFTER";
 
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/region-style-crash-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/region-style-crash-expected.txt
index 58a52cb..38afa8d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/region-style-crash-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/region-style-crash-expected.txt
@@ -1,7 +1,7 @@
 Tests that webkit css region styling can be parsed correctly. Test passes if it doesn't crash.
 
 color: rgb(255, 0, 0);
-    #ff0000 - #p1 <style>…</style>
+    #ff0000 - #p1 <style>
     OVERLOADED -internal-root-color - html user agent stylesheet
 display: block;
     block - p user agent stylesheet
@@ -17,7 +17,7 @@
 element.style { ()
 
 [expanded] 
-#p1 { (<style>…</style>)
+#p1 { (<style>)
     color: #ff0000;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/computed-properties-retain-expanded-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/computed-properties-retain-expanded-expected.txt
index f62da1e..77e1487 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/computed-properties-retain-expanded-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/computed-properties-retain-expanded-expected.txt
@@ -4,14 +4,14 @@
 #inspected computed styles: 
 color: rgb(0, 0, 255);
 display: flex;
-    flex - #inspected <style>…</style>
-    OVERLOADED block - div <style>…</style>
+    flex - #inspected <style>
+    OVERLOADED block - div <style>
     OVERLOADED block - div user agent stylesheet
 
 #other computed styles: 
 color: rgb(0, 0, 0);
 display: inline;
-    inline - #other <style>…</style>
-    OVERLOADED block - div <style>…</style>
+    inline - #other <style>
+    OVERLOADED block - div <style>
     OVERLOADED block - div user agent stylesheet
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/selector-list-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/selector-list-expected.txt
index bc4ab296..eecd1644 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/selector-list-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/selector-list-expected.txt
@@ -4,17 +4,17 @@
 element.style { ()
 
 [expanded] 
-FOO bAr, #inspected, MOO>BAR, htML div, Foo~Moo, MOO { (<style>…</style>)
+FOO bAr, #inspected, MOO>BAR, htML div, Foo~Moo, MOO { (<style>)
     color: green;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 
 [expanded] 
-#InSpEcTeD { (<style>…</style>)
+#InSpEcTeD { (<style>)
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 
 [expanded] 
 div { (user agent stylesheet)
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/shadow-dom-rules-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/shadow-dom-rules-expected.txt
index bdc4af8..614c1b5c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/shadow-dom-rules-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/shadow-dom-rules-expected.txt
@@ -8,7 +8,7 @@
 element.style { ()
 
 [expanded] 
-.red { (<style>…</style>)
+.red { (<style>)
     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet-expected.txt
index 079a042..00fa05584 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-.square { (imported-stylesheet.css:2 -> imported-stylesheet.css:2:2)
+.square { (imported-st…sheet.css:2 -> imported-stylesheet.css:2:2)
     background-color: red;
     display: inline-block;
 
@@ -23,7 +23,7 @@
 element.style { ()
 
 [expanded] 
-.square { (imported-stylesheet.css:2 -> imported-stylesheet.css:2:2)
+.square { (imported-st…sheet.css:2 -> imported-stylesheet.css:2:2)
 /-- overloaded --/ /-- disabled --/     /* background-color: red; */
     display: inline-block;
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-add-new-rule-to-stylesheet-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-add-new-rule-to-stylesheet-expected.txt
index e00d40b..5bcb7de 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-add-new-rule-to-stylesheet-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-add-new-rule-to-stylesheet-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#other, div { (different-rule-types.css:48 -> different-rule-types.css:48:14)
+#other, div { (different-r…ypes.css:48 -> different-rule-types.css:48:14)
 
 [expanded] 
 div { (user agent stylesheet)
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-computed-trace-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-computed-trace-expected.txt
index c7c5ed13..c165c4c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-computed-trace-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-computed-trace-expected.txt
@@ -2,62 +2,62 @@
 
 ==== Computed style for ID1 ====
 background-attachment: scroll;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-clip: border-box;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-color: rgb(128, 128, 128);
-    gray - #id1 <style>…</style>
-    OVERLOADED black - #id1 <style>…</style>
-    OVERLOADED green - #id1 <style>…</style>
+    gray - #id1 <style>
+    OVERLOADED black - #id1 <style>
+    OVERLOADED green - #id1 <style>
 background-image: none;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-origin: padding-box;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-position-x: 0%;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-position-y: 0%;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-repeat-x: ;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-repeat-y: ;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 background-size: auto;
-    initial - #id1 <style>…</style>
+    initial - #id1 <style>
 color: rgb(0, 0, 0);
     -internal-root-color - html user agent stylesheet
 display: block;
     block - div user agent stylesheet
 font-family: Courier;
-    Courier - #id1 <style>…</style>
-    OVERLOADED Times - #id1 <style>…</style>
-    OVERLOADED Arial - body <style>…</style>
+    Courier - #id1 <style>
+    OVERLOADED Times - #id1 <style>
+    OVERLOADED Arial - body <style>
 text-decoration-color: rgb(0, 0, 0);
-    initial - div <style>…</style>
+    initial - div <style>
 text-decoration-line: underline;
-    underline - div <style>…</style>
+    underline - div <style>
 text-decoration-style: solid;
-    initial - div <style>…</style>
+    initial - div <style>
 [expanded] 
 element.style { ()
 
 ==== Computed style for ID2 ====
 background-color: rgb(0, 0, 255);
-    blue - #id2 <style>…</style>
+    blue - #id2 <style>
 color: rgb(0, 0, 0);
     -internal-root-color - html user agent stylesheet
 display: block;
     block - div user agent stylesheet
 font-family: Courier;
-    Courier - #id2 <style>…</style>
-    OVERLOADED Courier - #id1 <style>…</style>
-    OVERLOADED Times - #id1 <style>…</style>
-    OVERLOADED Arial - body <style>…</style>
+    Courier - #id2 <style>
+    OVERLOADED Courier - #id1 <style>
+    OVERLOADED Times - #id1 <style>
+    OVERLOADED Arial - body <style>
 text-decoration-color: rgb(0, 0, 0);
-    initial - div <style>…</style>
+    initial - div <style>
 text-decoration-line: underline;
-    underline - div <style>…</style>
+    underline - div <style>
 text-decoration-style: solid;
-    initial - div <style>…</style>
+    initial - div <style>
 [expanded] 
 element.style { ()
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-cssom-important-property-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-cssom-important-property-expected.txt
index 333f5f5..91b3350 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-cssom-important-property-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-cssom-important-property-expected.txt
@@ -3,7 +3,7 @@
 element.style { ()
 
 [expanded] 
-div { (<style>…</style>)
+div { (<style>)
     color: red !important;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-disable-property-after-selector-edit-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-disable-property-after-selector-edit-expected.txt
index c03e05e6..4a178869 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-disable-property-after-selector-edit-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-disable-property-after-selector-edit-expected.txt
@@ -15,7 +15,7 @@
 element.style { ()
 
 [expanded] 
-#inspected, .INSERTED-OTHER-SELECTOR { (<style>…</style>)
+#inspected, .INSERTED-OTHER-SELECTOR { (<style>)
 /-- overloaded --/ /-- disabled --/     /* color: red; */
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-variables-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-variables-expected.txt
index b466f61..735c0ed 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-variables-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-3/styles-variables-expected.txt
@@ -9,7 +9,7 @@
 element.style { ()
 
 [expanded] 
-#id1 { (<style>…</style>)
+#id1 { (<style>)
     --b: 44px;
 
 [expanded] 
@@ -18,7 +18,7 @@
 
 ======== Inherited from body ========
 [expanded] 
-body { (<style>…</style>)
+body { (<style>)
     --a: red;
 
 ======== Inherited from html ========
@@ -36,7 +36,7 @@
 element.style { ()
 
 [expanded] 
-#id2 { (<style>…</style>)
+#id2 { (<style>)
     --a: green;
 
 [expanded] 
@@ -45,12 +45,12 @@
 
 ======== Inherited from div#id1 ========
 [expanded] 
-#id1 { (<style>…</style>)
+#id1 { (<style>)
     --b: 44px;
 
 ======== Inherited from body ========
 [expanded] 
-body { (<style>…</style>)
+body { (<style>)
 /-- overloaded --/     --a: red;
 
 ======== Inherited from html ========
@@ -68,7 +68,7 @@
 element.style { ()
 
 [expanded] 
-#id3 { (<style>…</style>)
+#id3 { (<style>)
     --a: inherit;
 
 [expanded] 
@@ -77,17 +77,17 @@
 
 ======== Inherited from div#id2 ========
 [expanded] 
-#id2 { (<style>…</style>)
+#id2 { (<style>)
 /-- overloaded --/     --a: green;
 
 ======== Inherited from div#id1 ========
 [expanded] 
-#id1 { (<style>…</style>)
+#id1 { (<style>)
     --b: 44px;
 
 ======== Inherited from body ========
 [expanded] 
-body { (<style>…</style>)
+body { (<style>)
 /-- overloaded --/     --a: red;
 
 ======== Inherited from html ========
@@ -105,7 +105,7 @@
 element.style { ()
 
 [expanded] 
-#id4 { (<style>…</style>)
+#id4 { (<style>)
     --a: var(--z);
 
 [expanded] 
@@ -114,7 +114,7 @@
 
 ======== Inherited from body ========
 [expanded] 
-body { (<style>…</style>)
+body { (<style>)
 /-- overloaded --/     --a: red;
 
 ======== Inherited from html ========
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt
index 2c0fad4..1f63cc7 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt
@@ -7,7 +7,7 @@
 
 [expanded] 
 @media (min-width: 6px)
-#container { (styles-do-not-d…n-edits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:9)
+#container { (styles-do-n…dits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:9)
     border: 1px solid blue;
     color: blue;
 
@@ -27,7 +27,7 @@
 
 [expanded] 
 @media (min-width: 6px)
-#container { (styles-do-not-d…n-edits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:9)
+#container { (styles-do-n…dits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:9)
     border: 1px solid blue;
 /-- overloaded --/     NAME: VALUE;
 
@@ -47,7 +47,7 @@
 
 [expanded] 
 @media (min-width: 6px)
-#container, SELECTOR { (styles-do-not-d…n-edits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:17)
+#container, SELECTOR { (styles-do-n…dits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:17)
     border: 1px solid blue;
 /-- overloaded --/     NAME: VALUE;
 
@@ -67,7 +67,7 @@
 
 [expanded] 
 @media (max-width: 9999999px)
-#container, SELECTOR { (styles-do-not-d…n-edits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:17)
+#container, SELECTOR { (styles-do-n…dits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:17)
     border: 1px solid blue;
 /-- overloaded --/     NAME: VALUE;
 
@@ -86,11 +86,11 @@
 element.style { ()
 
 [expanded] [no-affect] 
-NEW-RULE { (styles-do-not-d…n-edits.scss:4 -> styles-do-not-detach-sourcemap-on-edits.scss:4:20)
+NEW-RULE { (styles-do-n…dits.scss:4 -> styles-do-not-detach-sourcemap-on-edits.scss:4:20)
 
 [expanded] 
 @media (max-width: 9999999px)
-#container, SELECTOR { (styles-do-not-d…n-edits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:17)
+#container, SELECTOR { (styles-do-n…dits.scss:3 -> styles-do-not-detach-sourcemap-on-edits.scss:3:17)
     border: 1px solid blue;
 /-- overloaded --/     NAME: VALUE;
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-edit-property-after-invalid-rule-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-edit-property-after-invalid-rule-expected.txt
index 55250d3..808c17b4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-edit-property-after-invalid-rule-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-edit-property-after-invalid-rule-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-#container { (<style>…</style>)
+#container { (<style>)
     padding: 15px;
 
 [expanded] 
@@ -22,7 +22,7 @@
 element.style { ()
 
 [expanded] 
-#container { (<style>…</style>)
+#container { (<style>)
     padding: 20px;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-iframe-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-iframe-expected.txt
index 18d17b77..9c8ad63f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-iframe-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-iframe-expected.txt
@@ -22,7 +22,7 @@
 element.style { ()
 
 [expanded] 
-body { (styles-iframe-data.html:4 -> styles-iframe-data.html:4:9)
+body { (styles-ifra…data.html:4 -> styles-iframe-data.html:4:9)
     background: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-inherited-same-source-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-inherited-same-source-expected.txt
index c5b495a..4180754 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-inherited-same-source-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-inherited-same-source-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-div { (<style>…</style>)
+div { (<style>)
     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt
index 46cf2f1..d6426e3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt
@@ -27,12 +27,12 @@
 
 ======== @keyframes animName ========
 [expanded] 
-0%, 20% { (<style>…</style>)
+0%, 20% { (<style>)
     margin-left: 200px;
     color: red;
 
 [expanded] 
-100% { (<style>…</style>)
+100% { (<style>)
     margin-left: 500px;
 
 ======== @keyframes mediaAnim ========
@@ -84,12 +84,12 @@
 
 ======== @keyframes animName ========
 [expanded] 
-0%, 20% { (<style>…</style>)
+0%, 20% { (<style>)
     margin-left: 200px;
     color: red;
 
 [expanded] 
-1% { (<style>…</style>)
+1% { (<style>)
     margin-left: 500px;
 
 ======== @keyframes mediaAnim ========
@@ -141,12 +141,12 @@
 
 ======== @keyframes animName ========
 [expanded] 
-0%, 20% { (<style>…</style>)
+0%, 20% { (<style>)
     margin-left: 200px;
     color: red;
 
 [expanded] 
-100% { (<style>…</style>)
+100% { (<style>)
     margin-left: 500px;
 
 ======== @keyframes mediaAnim ========
@@ -198,12 +198,12 @@
 
 ======== @keyframes animName ========
 [expanded] 
-0%, 20% { (<style>…</style>)
+0%, 20% { (<style>)
     margin-left: 200px;
     color: red;
 
 [expanded] 
-1% { (<style>…</style>)
+1% { (<style>)
     margin-left: 500px;
 
 ======== @keyframes mediaAnim ========
@@ -255,12 +255,12 @@
 
 ======== @keyframes animName ========
 [expanded] 
-0%, 20% { (<style>…</style>)
+0%, 20% { (<style>)
     margin-left: 200px;
     color: red;
 
 [expanded] 
-1% { (<style>…</style>)
+1% { (<style>)
     margin-left: 500px;
 
 ======== @keyframes mediaAnim ========
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overloaded-shorthand-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overloaded-shorthand-expected.txt
index 9896aac..7e1e2e30 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overloaded-shorthand-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overloaded-shorthand-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-.foo { (<style>…</style>)
+.foo { (<style>)
     font-style: normal;
     font-variant-ligatures: normal;
     font-variant-caps: normal;
@@ -22,7 +22,7 @@
     /-- overloaded --/     margin-left: 10px;
 
 [expanded] 
-div { (<style>…</style>)
+div { (<style>)
     margin-left: 0px !important;
     margin-right: 0px !important;
     margin-top: 0px !important;
@@ -34,7 +34,7 @@
 
 ======== Inherited from body ========
 [expanded] 
-body { (<style>…</style>)
+body { (<style>)
 /-- overloaded --/     font: 1.2em "Arial", sans-serif;
     /-- overloaded --/     font-style: normal;
     /-- overloaded --/     font-variant-ligatures: normal;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overriden-properties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overriden-properties-expected.txt
index 4813ba0..94b737e9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overriden-properties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-overriden-properties-expected.txt
@@ -4,15 +4,15 @@
 element.style { ()
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/     -x: ;
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/     -x: ;
 
 [expanded] 
-#main { (<style>…</style>)
+#main { (<style>)
 /-- overloaded --/     background: #000;
     background: #bada55;
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-properties-overload-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-properties-overload-expected.txt
index 45b5e6f0..c611b016 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-properties-overload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-properties-overload-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#inspect { (<style>…</style>)
+#inspect { (<style>)
     margin-top: 1px;
     margin-left: 1px;
     margin-right: 1px;
@@ -22,7 +22,7 @@
         font-family: Arial;
 
 [expanded] 
-div { (<style>…</style>)
+div { (<style>)
 /-- overloaded --/     margin: 1px;
     /-- overloaded --/     margin-top: 1px;
     /-- overloaded --/     margin-right: 1px;
@@ -53,7 +53,7 @@
 
 ======== Inherited from div.container ========
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
 /-- overloaded --/     font-size: 10px;
 
 ======== Inherited from html ========
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-expected.txt
index 14c54b1a..1ba28148 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-expected.txt
@@ -4,22 +4,22 @@
 element.style { ()
 
 [expanded] 
-#main, .at_line_49 { (styles-source-l…helper.html:50 -> styles-source-lines-helper.html:50:2)
+#main, .at_line_49 { (styles-sour…per.html:50 -> styles-source-lines-helper.html:50:2)
     border: 1px solid
     red;
 
 [expanded] 
-#main, .at_line_41 { (styles-source-l…helper.html:43 -> styles-source-lines-helper.html:43:2)
+#main, .at_line_41 { (styles-sour…per.html:43 -> styles-source-lines-helper.html:43:2)
     font-size: 10px;
 
 [expanded] 
-#main, .at_line_26 { (styles-source-l…helper.html:29 -> styles-source-lines-helper.html:29:2)
+#main, .at_line_26 { (styles-sour…per.html:29 -> styles-source-lines-helper.html:29:2)
     font-family: /*  Comment in 
                       value  */courier;
 /-- overloaded --/     color blue: ;
 
 [expanded] 
-#main, .at_line_11::before { (styles-source-l…helper.html:15 -> styles-source-lines-helper.html:15:2)
+#main, .at_line_11::before { (styles-sour…per.html:15 -> styles-source-lines-helper.html:15:2)
     color: red;
     content: "Before";
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-inline-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-inline-expected.txt
index d3e1c166..3dd7591 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-inline-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-inline-expected.txt
@@ -5,7 +5,7 @@
     display: none;
 
 [expanded] 
-.foo { (styles-source-l…-helper.html:4 -> styles-source-lines-inline-helper.html:4:7)
+.foo { (styles-sour…lper.html:4 -> styles-source-lines-inline-helper.html:4:7)
     color: blue;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-recovery-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-recovery-expected.txt
index 0aa69e7..b8be4a5 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-recovery-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-source-lines-recovery-expected.txt
@@ -4,15 +4,15 @@
 element.style { ()
 
 [expanded] 
-#main { (styles-source-l…helper.html:25 -> styles-source-lines-recovery-helper.html:25:8)
+#main { (styles-sour…per.html:25 -> styles-source-lines-recovery-helper.html:25:8)
     color: white;
 
 [expanded] 
-#main { (styles-source-l…helper.html:16 -> styles-source-lines-recovery-helper.html:16:8)
+#main { (styles-sour…per.html:16 -> styles-source-lines-recovery-helper.html:16:8)
 /-- overloaded --/     color: blue;
 
 [expanded] 
-#main { (styles-source-l…-helper.html:7 -> styles-source-lines-recovery-helper.html:7:8)
+#main { (styles-sour…lper.html:7 -> styles-source-lines-recovery-helper.html:7:8)
 /-- overloaded --/     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-from-js-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-from-js-expected.txt
index 8a57ee3..d6ddd97c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-from-js-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-from-js-expected.txt
@@ -93,7 +93,7 @@
 element.style { ()
 
 [expanded] 
-.red div:first-child { (<style>…</style>)
+.red div:first-child { (<style>)
     background-color: red;
 
 [expanded] 
@@ -117,7 +117,7 @@
 element.style { ()
 
 [expanded] 
-div[foo="bar"] + div { (<style>…</style>)
+div[foo="bar"] + div { (<style>)
     background-color: blue;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-1-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-1-expected.txt
index c1445fc..9c1b88c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-1-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-1-expected.txt
@@ -9,32 +9,32 @@
 
 [expanded] 
 @media (min-device-width: 1px)
-.should-change { (styles-update-links.css:11 -> styles-update-links.css:11:21)
+.should-change { (styles-upda…inks.css:11 -> styles-update-links.css:11:21)
     font-family: monospace;
 
 [expanded] 
-.should-change { (styles-update-links.css:7 -> styles-update-links.css:7:79)
+.should-change { (styles-upda…links.css:7 -> styles-update-links.css:7:79)
     position: relative;
     margin: 1em;
 
 [expanded] 
-.should-change { (styles-update-links.css:7 -> styles-update-links.css:7:35)
+.should-change { (styles-upda…links.css:7 -> styles-update-links.css:7:35)
     border: 1px solid black;
 
 [expanded] 
-.should-change { (styles-update-links.css:6 -> styles-update-links.css:6:19)
+.should-change { (styles-upda…links.css:6 -> styles-update-links.css:6:19)
     color: red;
 
 [expanded] 
-.left-intact { (styles-update-links.css:4 -> styles-update-links.css:4:15)
+.left-intact { (styles-upda…links.css:4 -> styles-update-links.css:4:15)
     padding: 1em;
 
 [expanded] 
-.left-intact { (styles-update-links.css:1 -> styles-update-links.css:1:15)
+.left-intact { (styles-upda…links.css:1 -> styles-update-links.css:1:15)
     box-sizing: border-box;
 
 [expanded] 
-.left-intact { (styles-update-links-2.css:19 -> styles-update-links-2.css:19:15)
+.left-intact { (styles-upda…ks-2.css:19 -> styles-update-links-2.css:19:15)
     line-height: 1;
 
 [expanded] 
@@ -56,33 +56,33 @@
 
 [expanded] 
 @media (min-device-width: 1px)
-.should-change { (styles-update-links.css:13 -> styles-update-links.css:13:21)
+.should-change { (styles-upda…inks.css:13 -> styles-update-links.css:13:21)
     font-family: monospace;
 
 [expanded] 
-.should-change { (styles-update-links.css:9 -> styles-update-links.css:9:67)
+.should-change { (styles-upda…links.css:9 -> styles-update-links.css:9:67)
     position: relative;
     margin: 1em;
 
 [expanded] 
-.should-change { (styles-update-links.css:9 -> styles-update-links.css:9:23)
+.should-change { (styles-upda…links.css:9 -> styles-update-links.css:9:23)
     border: 1px solid black;
 
 [expanded] 
-.should-change { (styles-update-links.css:6 -> styles-update-links.css:6:19)
+.should-change { (styles-upda…links.css:6 -> styles-update-links.css:6:19)
     color: red;
 /-- overloaded --/     PROPERTY: INSERTED;
 
 [expanded] 
-.left-intact { (styles-update-links.css:4 -> styles-update-links.css:4:15)
+.left-intact { (styles-upda…links.css:4 -> styles-update-links.css:4:15)
     padding: 1em;
 
 [expanded] 
-.left-intact { (styles-update-links.css:1 -> styles-update-links.css:1:15)
+.left-intact { (styles-upda…links.css:1 -> styles-update-links.css:1:15)
     box-sizing: border-box;
 
 [expanded] 
-.left-intact { (styles-update-links-2.css:19 -> styles-update-links-2.css:19:15)
+.left-intact { (styles-upda…ks-2.css:19 -> styles-update-links-2.css:19:15)
     line-height: 1;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-2-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-2-expected.txt
index 37802cb..c3f72235 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-2-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-2-expected.txt
@@ -14,32 +14,32 @@
 
 [expanded] 
 @media (min-device-width: 1px)
-.should-change { (styles-update-links.css:11 -> styles-update-links.css:11:21)
+.should-change { (styles-upda…inks.css:11 -> styles-update-links.css:11:21)
     font-family: monospace;
 
 [expanded] 
-.should-change { (styles-update-links.css:7 -> styles-update-links.css:7:105)
+.should-change { (styles-upda…links.css:7 -> styles-update-links.css:7:105)
     position: relative;
     margin: 1em;
 
 [expanded] 
-.should-change, .INSERTED-OTHER-SELECTOR { (styles-update-links.css:7 -> styles-update-links.css:7:61)
+.should-change, .INSERTED-OTHER-SELECTOR { (styles-upda…links.css:7 -> styles-update-links.css:7:61)
     border: 1px solid black;
 
 [expanded] 
-.should-change { (styles-update-links.css:6 -> styles-update-links.css:6:19)
+.should-change { (styles-upda…links.css:6 -> styles-update-links.css:6:19)
     color: red;
 
 [expanded] 
-.left-intact { (styles-update-links.css:4 -> styles-update-links.css:4:15)
+.left-intact { (styles-upda…links.css:4 -> styles-update-links.css:4:15)
     padding: 1em;
 
 [expanded] 
-.left-intact { (styles-update-links.css:1 -> styles-update-links.css:1:15)
+.left-intact { (styles-upda…links.css:1 -> styles-update-links.css:1:15)
     box-sizing: border-box;
 
 [expanded] 
-.left-intact { (styles-update-links-2.css:19 -> styles-update-links-2.css:19:15)
+.left-intact { (styles-upda…ks-2.css:19 -> styles-update-links-2.css:19:15)
     line-height: 1;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-3-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-3-expected.txt
index 42ebad4..6f67137 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-3-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-3-expected.txt
@@ -14,32 +14,32 @@
 
 [expanded] 
 @media (min-device-width: 1px)
-.should-change { (styles-update-links.css:11 -> styles-update-links.css:11:21)
+.should-change { (styles-upda…inks.css:11 -> styles-update-links.css:11:21)
     font-family: monospace;
 
 [expanded] 
-.should-change { (styles-update-links.css:7 -> styles-update-links.css:7:83)
+.should-change { (styles-upda…links.css:7 -> styles-update-links.css:7:83)
     position: relative;
     margin: 1em;
 
 [expanded] 
-.should-change { (styles-update-links.css:7 -> styles-update-links.css:7:35)
+.should-change { (styles-upda…links.css:7 -> styles-update-links.css:7:35)
 /-- overloaded --/ /-- disabled --/     /* border: 1px solid black; */
 
 [expanded] 
-.should-change { (styles-update-links.css:6 -> styles-update-links.css:6:19)
+.should-change { (styles-upda…links.css:6 -> styles-update-links.css:6:19)
     color: red;
 
 [expanded] 
-.left-intact { (styles-update-links.css:4 -> styles-update-links.css:4:15)
+.left-intact { (styles-upda…links.css:4 -> styles-update-links.css:4:15)
     padding: 1em;
 
 [expanded] 
-.left-intact { (styles-update-links.css:1 -> styles-update-links.css:1:15)
+.left-intact { (styles-upda…links.css:1 -> styles-update-links.css:1:15)
     box-sizing: border-box;
 
 [expanded] 
-.left-intact { (styles-update-links-2.css:19 -> styles-update-links-2.css:19:15)
+.left-intact { (styles-upda…ks-2.css:19 -> styles-update-links-2.css:19:15)
     line-height: 1;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-4-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-4-expected.txt
index 9a9c19f2..3a2020d8 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-4-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-update-links-4-expected.txt
@@ -23,16 +23,16 @@
 
 ======== Pseudo ::before element ========
 [expanded] 
-#pseudo::before { (<style>…</style>)
+#pseudo::before { (<style>)
     color: blue;
 
 ======== Pseudo ::after element ========
 [expanded] 
-#pseudo::after { (<style>…</style>)
+#pseudo::after { (<style>)
     border: 1px solid black;
 
 [expanded] 
-#pseudo::after { (<style>…</style>)
+#pseudo::after { (<style>)
 /-- overloaded --/     pseudo-property: "12";
 /-- overloaded --/     PROPERTY: INSERTED;
     color: red;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/undo-add-property-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/undo-add-property-expected.txt
index 442ac5c..c2c80e8 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/undo-add-property-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/undo-add-property-expected.txt
@@ -6,7 +6,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
 
 [expanded] 
@@ -23,7 +23,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
     margin-left: 2px;
 
@@ -41,7 +41,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
 
 [expanded] 
@@ -58,7 +58,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
     margin-left: 2px;
 
@@ -77,7 +77,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
     margin-left: 2px;
 
@@ -95,7 +95,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     margin-top: 0px;
     font-weight: bold;
     margin-left: 2px;
@@ -114,7 +114,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
     margin-left: 2px;
 
@@ -132,7 +132,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     margin-top: 0px;
     font-weight: bold;
     margin-left: 2px;
@@ -152,7 +152,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     margin-top: 0px;
     font-weight: bold;
     margin-left: 2px;
@@ -171,7 +171,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     margin-top: 0px;
     margin-right: 1px;
     font-weight: bold;
@@ -191,7 +191,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     margin-top: 0px;
     font-weight: bold;
     margin-left: 2px;
@@ -210,7 +210,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     margin-top: 0px;
     margin-right: 1px;
     font-weight: bold;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/cancel-upon-invalid-property-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/cancel-upon-invalid-property-expected.txt
index ebfbf66..e1e7aa7 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/cancel-upon-invalid-property-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/cancel-upon-invalid-property-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     color: blue;
 
 [expanded] 
@@ -20,7 +20,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     color: blue;
     : ;
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-deprecated-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-deprecated-expected.txt
index 80273b31..d916b1d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-deprecated-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-deprecated-expected.txt
@@ -8,7 +8,7 @@
     color: green;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-expected.txt
index 80273b31..d916b1d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-expected.txt
@@ -8,7 +8,7 @@
     color: green;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-deprecated-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-deprecated-expected.txt
index ff7bed6..75de86b9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-deprecated-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-deprecated-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#container #inspected { (selector-line-s…-header.scss:4 -> selector-line-sourcemap-header.scss:4:16)
+#container #inspected { (selector-li…ader.scss:4 -> selector-line-sourcemap-header.scss:4:16)
     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-expected.txt
index ff7bed6..75de86b9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/selector-line-sourcemap-header-expected.txt
@@ -4,7 +4,7 @@
 element.style { ()
 
 [expanded] 
-#container #inspected { (selector-line-s…-header.scss:4 -> selector-line-sourcemap-header.scss:4:16)
+#container #inspected { (selector-li…ader.scss:4 -> selector-line-sourcemap-header.scss:4:16)
     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/show-all-properties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/show-all-properties-expected.txt
index 45381de..9db810a3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/show-all-properties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/show-all-properties-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     --var-0: 0px;
     --var-1: 1px;
     --var-2: 2px;
@@ -72,7 +72,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     --var-0: 0px;
     --var-1: 1px;
     --var-2: 2px;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-parse-invalid-properties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-parse-invalid-properties-expected.txt
index 39047cf..23be990 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-parse-invalid-properties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-parse-invalid-properties-expected.txt
@@ -5,7 +5,7 @@
 /-- overloaded --/     123: ;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     before property: hey;
 /-- overloaded --/     after property: hey;
 /-- overloaded --/     background color: orange;
@@ -19,7 +19,7 @@
 /-- overloaded --/     bar: foo;
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 /-- overloaded --/     color: blue;
 /-- overloaded --/     a property with spaces: red;
 /-- overloaded --/     --a-property-with-no-value: ;
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-after-cancelled-editing-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-after-cancelled-editing-expected.txt
index 449775e..ad11ee26 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-after-cancelled-editing-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-after-cancelled-editing-expected.txt
@@ -10,7 +10,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     color: blue;
     : ;
 
@@ -31,7 +31,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     color: blue;
 
 [expanded] 
@@ -49,7 +49,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
 
 [expanded] 
 div { (user agent stylesheet)
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-change-property-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-change-property-expected.txt
index 33303f49..124d7565 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-change-property-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-change-property-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
 
 [expanded] 
@@ -22,7 +22,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: normal;
 
 [expanded] 
@@ -39,7 +39,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: bold;
 
 [expanded] 
@@ -56,7 +56,7 @@
 element.style { ()
 
 [expanded] 
-.container { (<style>…</style>)
+.container { (<style>)
     font-weight: normal;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-set-selector-text-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-set-selector-text-expected.txt
index cdfe9943..856f9aed 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-set-selector-text-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/undo-set-selector-text-expected.txt
@@ -5,7 +5,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     color: green;
 
 [expanded] 
@@ -22,7 +22,7 @@
 element.style { ()
 
 [expanded] 
-#inspected, #other { (<style>…</style>)
+#inspected, #other { (<style>)
     color: green;
 
 [expanded] 
@@ -39,7 +39,7 @@
 element.style { ()
 
 [expanded] 
-#inspected { (<style>…</style>)
+#inspected { (<style>)
     color: green;
 
 [expanded] 
@@ -56,7 +56,7 @@
 element.style { ()
 
 [expanded] 
-#inspected, #other { (<style>…</style>)
+#inspected, #other { (<style>)
     color: green;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/shadow-dom-rules-expected.txt b/third_party/blink/web_tests/http/tests/devtools/startup/shadow-dom-rules-expected.txt
index bdc4af8..614c1b5c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/startup/shadow-dom-rules-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/startup/shadow-dom-rules-expected.txt
@@ -8,7 +8,7 @@
 element.style { ()
 
 [expanded] 
-.red { (<style>…</style>)
+.red { (<style>)
     color: red;
 
 [expanded] 
diff --git a/third_party/blink/web_tests/virtual/custom-user-timing/http/tests/performance-timing/custom-user-timing/usertimingl3-mark-type-expected.txt b/third_party/blink/web_tests/virtual/custom-user-timing/http/tests/performance-timing/custom-user-timing/usertimingl3-mark-type-expected.txt
deleted file mode 100644
index be2eaa2..0000000
--- a/third_party/blink/web_tests/virtual/custom-user-timing/http/tests/performance-timing/custom-user-timing/usertimingl3-mark-type-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-PASS Number should be rejected as the mark-options.
-PASS NaN should be rejected as the mark-options.
-PASS Infinity should be rejected as the mark-options.
-PASS String should be rejected as the mark-options.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/README.txt
index 65c317fd..a656a64d 100644
--- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/README.txt
+++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-all/README.txt
@@ -1,3 +1,3 @@
 # This suite runs the tests in LayoutTests/paint/dark-mode
-# with --blink-settings="highContrastMode=3,highContrastImagePolicy=0"
+# with --blink-settings="darkMode=3,darkModeImagePolicy=0"
 # See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-none/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-none/README.txt
index 767087fb..a49e5fe 100644
--- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-none/README.txt
+++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-none/README.txt
@@ -1,3 +1,3 @@
 # This suite runs the tests in LayoutTests/paint/dark-mode
-# with --blink-settings="highContrastMode=3,highContrastImagePolicy=1"
+# with --blink-settings="darkMode=3,darkModeImagePolicy=1"
 # See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-smart/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-smart/README.txt
index 15d882fd..a6ec770 100644
--- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-smart/README.txt
+++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/image-filter-smart/README.txt
@@ -1,3 +1,3 @@
 # This suite runs the tests in LayoutTests/paint/dark-mode
-# with --blink-settings="highContrastMode=3,highContrastImagePolicy=2"
+# with --blink-settings="darkMode=3,darkModeImagePolicy=2"
 # See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/longtask-v2/http/tests/performance-timing/longtask-v2/longtask-executescript-expected.txt b/third_party/blink/web_tests/virtual/longtask-v2/http/tests/performance-timing/longtask-v2/longtask-executescript-expected.txt
deleted file mode 100644
index 8db99da..0000000
--- a/third_party/blink/web_tests/virtual/longtask-v2/http/tests/performance-timing/longtask-v2/longtask-executescript-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Performance longtask entries with execute-script attribute are observable.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/longtask-v2/http/tests/performance-timing/longtask-v2/longtask-v8compile-expected.txt b/third_party/blink/web_tests/virtual/longtask-v2/http/tests/performance-timing/longtask-v2/longtask-v8compile-expected.txt
deleted file mode 100644
index b1fd37b..0000000
--- a/third_party/blink/web_tests/virtual/longtask-v2/http/tests/performance-timing/longtask-v2/longtask-v8compile-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Performance longtask entries with script-compile attribute are observable.
-Harness: the test ran to completion.
-
diff --git a/tools/chrome_proxy/webdriver/bypass.py b/tools/chrome_proxy/webdriver/bypass.py
index 4dcd245..fd691f8 100644
--- a/tools/chrome_proxy/webdriver/bypass.py
+++ b/tools/chrome_proxy/webdriver/bypass.py
@@ -190,7 +190,8 @@
       self.skipTest('This test cannot be run with other experiments.')
     with TestDriver() as test_driver:
       test_driver.AddChromeArg('--enable-spdy-proxy-auth')
-      test_driver.AddChromeArg('--data-reduction-proxy-experiment=client_test_bypass')
+      test_driver.AddChromeArg('--data-reduction-proxy-experiment='
+                               'client_test_bypass')
 
       # Verify that loading a page other than the specific exp directive test
       # page loads through the proxy without being bypassed.
@@ -200,16 +201,16 @@
       for response in responses:
         self.assertHasChromeProxyViaHeader(response)
 
-      # Verify that loading the exp directive test page with "exp=client_test_bypass" triggers
-      # a bypass.
+      # Verify that loading the exp directive test page with
+      # "exp=client_test_bypass" triggers a bypass.
       test_driver.LoadURL('http://check.googlezip.net/exp/')
       responses = test_driver.GetHTTPResponses()
       self.assertNotEqual(0, len(responses))
       for response in responses:
         self.assertNotHasChromeProxyViaHeader(response)
 
-    # Verify that loading the same test page without setting "exp=client_test_bypass" loads
-    # through the proxy without being bypassed.
+    # Verify that loading the same test page without setting
+    #{ }"exp=client_test_bypass" loads through the proxy without being bypassed.
     with TestDriver() as test_driver:
       test_driver.AddChromeArg('--enable-spdy-proxy-auth')
 
@@ -224,10 +225,6 @@
   def testBadHTTPSFallback(self):
     with TestDriver() as test_driver:
       test_driver.AddChromeArg('--enable-spdy-proxy-auth')
-      # Set the primary (HTTPS) proxy to a bad one.
-      # That will force Data Saver to the HTTP proxy for normal page requests.
-      test_driver.AddChromeArg('--spdy-proxy-auth-origin='
-                               'https://nonexistent.googlezip.net')
       test_driver.AddChromeArg('--data-reduction-proxy-http-proxies='
                                'http://compress.googlezip.net')
 
@@ -249,11 +246,13 @@
       self.assertNotEqual(0, len(responses))
       for response in responses:
         self.assertHasChromeProxyViaHeader(response)
-        chrome_proxy_header = response.request_headers['chrome-proxy']
-        chrome_proxy_directives = chrome_proxy_header.split(',')
-        for directive in chrome_proxy_directives:
-            if 'c=' in directive:
-                clientType = directive[3:]
+        if 'chrome-proxy' in response.request_headers:
+            chrome_proxy_header = response.request_headers['chrome-proxy']
+            chrome_proxy_directives = chrome_proxy_header.split(',')
+            for directive in chrome_proxy_directives:
+                if 'c=' in directive:
+                    clientType = directive[3:]
+    self.assertTrue(clientType)
 
     clients = ['android', 'webview', 'ios', 'linux', 'win', 'chromeos']
     for client in clients:
diff --git a/tools/chrome_proxy/webdriver/fallback.py b/tools/chrome_proxy/webdriver/fallback.py
index 2b60ee9d..afb72bd 100644
--- a/tools/chrome_proxy/webdriver/fallback.py
+++ b/tools/chrome_proxy/webdriver/fallback.py
@@ -5,6 +5,7 @@
 import common
 from common import TestDriver
 from common import IntegrationTest
+from decorators import ChromeVersionBeforeM
 
 class Fallback(IntegrationTest):
 
@@ -34,11 +35,12 @@
       self.assertNotEqual(0, len(responses))
       for response in responses:
           self.assertHasChromeProxyViaHeader(response)
-          self.assertEqual(u'http/1.1', response.protocol)
+          self.assertEqual(u'http/2+quic/43', response.protocol)
 
   # Verify that when Chrome receives a non-4xx response through a Data Reduction
   # Proxy that doesn't set a proper via header, Chrome falls back to the next
   # available proxy.
+  @ChromeVersionBeforeM(67)
   def testMissingViaHeaderNon4xxFallback(self):
     with TestDriver() as test_driver:
       test_driver.AddChromeArg('--enable-spdy-proxy-auth')
@@ -68,23 +70,19 @@
       self.assertEqual(1, histogram['count'])
       self.assertIn({'count': 1, 'high': 6, 'low': 5}, histogram['buckets'])
 
-  # DataSaver uses a https proxy by default, if that fails it will fall back to 
+  # DataSaver uses a https proxy by default, if that fails it will fall back to
   # a http proxy; and if that fails, it will fall back to a direct connection
   def testHTTPToDirectFallback(self):
     with TestDriver() as test_driver:
       test_driver.AddChromeArg('--enable-spdy-proxy-auth')
-      # set the primary (https) proxy to a bad one.  
-      # That will force DataSaver to the http proxy for normal page requests.
-      test_driver.AddChromeArg('--spdy-proxy-auth-origin='
-                               'https://nonexistent.googlezip.net')
       test_driver.AddChromeArg('--data-reduction-proxy-http-proxies='
                                'http://nonexistent.googlezip.net;'
-                               'http://compress.googlezip.net')  
-          
+                               'http://compress.googlezip.net')
+
       test_driver.LoadURL('http://check.googlezip.net/fallback/')
-      responses = test_driver.GetHTTPResponses()      
+      responses = test_driver.GetHTTPResponses()
       self.assertNotEqual(0, len(responses))
-      for response in responses:        
+      for response in responses:
         self.assertEqual(80, response.port)
 
       test_driver.LoadURL('http://check.googlezip.net/block/')
@@ -92,6 +90,6 @@
       self.assertNotEqual(0, len(responses))
       for response in responses:
         self.assertNotHasChromeProxyViaHeader(response)
-        
+
 if __name__ == '__main__':
   IntegrationTest.RunAllTests()
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 68a70e9..1190249 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -1911,7 +1911,7 @@
     },
 
     'cfi': {
-      'gn_args': 'is_cfi=true',
+      'gn_args': 'is_cfi=true use_cfi_icall=true',
     },
 
     'cfi_full': {
diff --git a/tools/metrics/histograms/README.md b/tools/metrics/histograms/README.md
index e6229ed4..e863bcc 100644
--- a/tools/metrics/histograms/README.md
+++ b/tools/metrics/histograms/README.md
@@ -78,11 +78,18 @@
 However, the total count does not have to be meaningful for an enum histogram
 to still be the right choice.
 
+Enumerated histograms are also appropriate for counting events.  Use a simple
+boolean histogram.  It's okay if you only log to one bucket (say, `true`).
+It's usually best (though not necessary), if you have a comparison point in
+the same histogram.  For example, if you want to count pages opened from the
+history page, it might be a useful comparison to have the same histogram
+record the number of times the history page was opened.
+
 If few buckets will be emitted to, consider using a [sparse
 histogram](#When-To-Use-Sparse-Histograms).
 
 You may append to your enum if the possible states/actions grows.  However, you
-should not reorder, renumber, or otherwise reuse existing values. Definitions
+should not reorder, renumber, or otherwise reuse existing values.  Definitions
 for enums recorded in histograms should be prefixed by the following warning:
 ```c++
 // These values are persisted to logs. Entries should not be renumbered and
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index fa9adc78..722a2df 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -5017,6 +5017,11 @@
   <int value="1" label="Has declarative rules"/>
 </enum>
 
+<enum name="BooleanDecodeSwapChainUsed">
+  <int value="0" label="Used video processor blit with flip swap chain"/>
+  <int value="1" label="Used zero copy decode swap chain"/>
+</enum>
+
 <enum name="BooleanDefault">
   <int value="0" label="Not Default"/>
   <int value="1" label="Default"/>
@@ -22244,6 +22249,7 @@
   <int value="2831" label="ImportMap"/>
   <int value="2832" label="RefreshHeader"/>
   <int value="2833" label="SearchEventFired"/>
+  <int value="2834" label="IdleDetectionStart"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
@@ -32462,7 +32468,6 @@
   <int value="-560551550" label="use-memory-pressure-chromeos"/>
   <int value="-560114351" label="OfflinePagesRenovations:disabled"/>
   <int value="-557742250" label="ContentSuggestionsCategories:disabled"/>
-  <int value="-548495403" label="AutofillDynamicForms:enabled"/>
   <int value="-548082154" label="protect-sync-credential:disabled"/>
   <int value="-547301855" label="SyncPseudoUSSSupervisedUsers:enabled"/>
   <int value="-541611402" label="OfflinePagesPrefetching:enabled"/>
@@ -32968,6 +32973,7 @@
   <int value="313303258" label="WebPaymentsModifiers:disabled"/>
   <int value="316182183" label="MediaDocumentDownloadButton:disabled"/>
   <int value="319683583" label="ContentSuggestionsDebugLog:enabled"/>
+  <int value="320121752" label="DelegateOverscrollSwipes:disabled"/>
   <int value="323605372" label="ui-disable-compositor-animation-timelines"/>
   <int value="324060906"
       label="enable-experimental-accessibility-language-detection"/>
@@ -33805,7 +33811,6 @@
   <int value="1659082220" label="EnableManualSaving:disabled"/>
   <int value="1659372520" label="WebXrRenderPath:disabled"/>
   <int value="1661925474" label="silent-debugger-extension-api"/>
-  <int value="1663185040" label="AutofillDynamicForms:disabled"/>
   <int value="1664401033" label="ColorCorrectRendering:enabled"/>
   <int value="1665349789" label="spurious-power-button-window"/>
   <int value="1667584730" label="WebXR:disabled"/>
@@ -34053,6 +34058,7 @@
   <int value="2039276757" label="EnableOverviewRoundedCorners:enabled"/>
   <int value="2040316611" label="IPH_ReopenTab:enabled"/>
   <int value="2043321329" label="OfflinePagesPrefetchingUI:disabled"/>
+  <int value="2047695652" label="DelegateOverscrollSwipes:enabled"/>
   <int value="2047981703" label="IntentPicker:enabled"/>
   <int value="2056572020" label="EnableUsernameCorrection:disabled"/>
   <int value="2058148069" label="UseMessagesStagingUrl:enabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 8bc45f61..369ea20b 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -40220,7 +40220,7 @@
 </histogram>
 
 <histogram name="GPU.DirectComposition.DecodeSwapChainCreationResult"
-    enum="Hresult" expires_after="M75">
+    enum="Hresult" expires_after="M76">
   <owner>sunnyps@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -40231,6 +40231,10 @@
 
 <histogram name="GPU.DirectComposition.DecodeSwapChainPresentResult"
     enum="Hresult" expires_after="M75">
+  <obsolete>
+    Deprecated 3/2019. This either succeeds or fails with DXGI_STATUS_OCCLUDED
+    infrequently which we also handle.
+  </obsolete>
   <owner>sunnyps@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -40240,6 +40244,9 @@
 
 <histogram name="GPU.DirectComposition.DecodeSwapChainSurfaceCreationResult"
     enum="Hresult" expires_after="M75">
+  <obsolete>
+    Deprecated 3/2019. Creating the surface never fails.
+  </obsolete>
   <owner>sunnyps@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -40248,6 +40255,16 @@
   </summary>
 </histogram>
 
+<histogram name="GPU.DirectComposition.DecodeSwapChainUsed"
+    enum="BooleanDecodeSwapChainUsed" expires_after="M76">
+  <owner>sunnyps@chromium.org</owner>
+  <owner>zmo@chromium.org</owner>
+  <summary>
+    Whether zero copy decode swap chain was used to present video frame instead
+    of video processor blit with flip swap chain. Recorded on each present.
+  </summary>
+</histogram>
+
 <histogram name="GPU.DirectComposition.FramesSinceColorSpaceChange"
     units="frames">
   <owner>jbauman@chromium.org</owner>
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 50e973e7..b4ad880 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -2047,6 +2047,7 @@
       // TODO(accessibility) https://github.com/w3c/html-aam/issues/141
       return ATK_ROLE_SECTION;
     case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
       return ATK_ROLE_LANDMARK;
     case ax::mojom::Role::kDate:
       return ATK_ROLE_DATE_EDITOR;
@@ -2355,8 +2356,6 @@
       return ATK_ROLE_PANEL;
     case ax::mojom::Role::kFigcaption:
       return ATK_ROLE_CAPTION;
-    case ax::mojom::Role::kFooter:
-      return ATK_ROLE_FOOTER;
     case ax::mojom::Role::kKeyboard:
     case ax::mojom::Role::kNone:
     case ax::mojom::Role::kPresentational:
diff --git a/ui/accessibility/platform/ax_platform_node_delegate.h b/ui/accessibility/platform/ax_platform_node_delegate.h
index 74fa33c..eccf9db 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -216,6 +216,7 @@
       const = 0;
   virtual base::string16 GetLocalizedStringForImageAnnotationStatus(
       ax::mojom::ImageAnnotationStatus status) const = 0;
+  virtual base::string16 GetLocalizedStringForLandmarkType() const = 0;
 
   //
   // Testing.
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.cc b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
index 6cd7faa3..ca70a981 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
@@ -215,6 +215,11 @@
   return base::string16();
 }
 
+base::string16 AXPlatformNodeDelegateBase::GetLocalizedStringForLandmarkType()
+    const {
+  return base::string16();
+}
+
 bool AXPlatformNodeDelegateBase::ShouldIgnoreHoveredStateForTesting() {
   return true;
 }
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.h b/ui/accessibility/platform/ax_platform_node_delegate_base.h
index dbf5149..8872890 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.h
@@ -186,6 +186,7 @@
   base::string16 GetLocalizedStringForImageAnnotationStatus(
       ax::mojom::ImageAnnotationStatus status) const override;
   base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() const override;
+  base::string16 GetLocalizedStringForLandmarkType() const override;
 
   //
   // Testing.
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index 3b6311dc..ebf36ce 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -7,6 +7,8 @@
 #include <utility>
 #include <vector>
 
+#include "ui/accessibility/platform/ax_platform_node_delegate.h"
+
 #define UIA_VALIDATE_TEXTRANGEPROVIDER_CALL()                        \
   if (!owner() || !owner()->GetDelegate() || !start_->GetAnchor() || \
       !end_->GetAnchor())                                            \
@@ -54,7 +56,20 @@
 STDMETHODIMP AXPlatformNodeTextRangeProviderWin::Compare(
     ITextRangeProvider* other,
     BOOL* result) {
-  return E_NOTIMPL;
+  UIA_VALIDATE_TEXTRANGEPROVIDER_CALL();
+
+  CComPtr<AXPlatformNodeTextRangeProviderWin> other_provider;
+  if (other->QueryInterface(&other_provider) != S_OK) {
+    return UIA_E_INVALIDOPERATION;
+  }
+
+  *result = FALSE;
+  if (*start_ == *(other_provider->start_) &&
+      *end_ == *(other_provider->end_)) {
+    *result = TRUE;
+  }
+
+  return S_OK;
 }
 
 STDMETHODIMP AXPlatformNodeTextRangeProviderWin::CompareEndpoints(
@@ -172,7 +187,17 @@
 
 STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetEnclosingElement(
     IRawElementProviderSimple** element) {
-  return E_NOTIMPL;
+  UIA_VALIDATE_TEXTRANGEPROVIDER_CALL();
+
+  AXPositionInstance common_ancestor = start_->LowestCommonAncestor(*end_);
+  owner()
+      ->GetDelegate()
+      ->GetFromNodeID(common_ancestor->anchor_id())
+      ->GetNativeViewAccessible()
+      ->QueryInterface(IID_PPV_ARGS(element));
+
+  DCHECK(*element);
+  return S_OK;
 }
 
 STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetText(int max_count,
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
index ded7a46..ebfd585 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -368,9 +368,10 @@
 }
 
 TEST_F(AXPlatformNodeTextRangeProviderTest,
-       TestITextRangeProviderCompareEndpointsInvalidProvider) {
-  // Test for when this provider is invalid. Because ax tree is not created,
-  // and there is no valid anchor, so this provider fails validate call.
+       TestITextRangeProviderInvalidCalls) {
+  // Test for when a text range provider is invalid. Because no ax tree is
+  // available, the anchor is invalid, so the text range provider fails the
+  // validate call.
   {
     ui::AXNodeData root_data;
     root_data.id = 1;
@@ -391,15 +392,19 @@
     EXPECT_HRESULT_SUCCEEDED(
         document_provider->get_DocumentRange(&text_range_provider));
 
-    int result;
+    BOOL compare_result;
+    EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->Compare(
+        text_range_provider.Get(), &compare_result));
+
+    int compare_endpoints_result;
     EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->CompareEndpoints(
         TextPatternRangeEndpoint_Start, text_range_provider.Get(),
-        TextPatternRangeEndpoint_Start, &result));
+        TextPatternRangeEndpoint_Start, &compare_endpoints_result));
   }
 
   // Test for when this provider is valid, but the other provider is not an
-  // instance of AXPlatformNodeTextRangeProviderWin, so it cannot be compared
-  // to this provider.
+  // instance of AXPlatformNodeTextRangeProviderWin, so no operation can be
+  // performed on the other provider.
   {
     ui::AXNodeData root_data;
     root_data.id = 1;
@@ -429,14 +434,18 @@
     EXPECT_HRESULT_SUCCEEDED(
         document_provider->get_DocumentRange(&this_provider));
 
-    int result;
     ComPtr<ITextRangeProvider> other_provider_different_type;
     MockAXPlatformNodeTextRangeProviderWin::CreateMockTextRangeProvider(
         &other_provider_different_type);
 
+    BOOL compare_result;
+    EXPECT_UIA_INVALIDOPERATION(this_provider->Compare(
+        other_provider_different_type.Get(), &compare_result));
+
+    int compare_endpoints_result;
     EXPECT_UIA_INVALIDOPERATION(this_provider->CompareEndpoints(
         TextPatternRangeEndpoint_Start, other_provider_different_type.Get(),
-        TextPatternRangeEndpoint_Start, &result));
+        TextPatternRangeEndpoint_Start, &compare_endpoints_result));
 
     AXNodePosition::SetTreeForTesting(nullptr);
   }
@@ -537,6 +546,95 @@
   AXNodePosition::SetTreeForTesting(nullptr);
 }
 
+TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderCompare) {
+  ui::AXNodeData text_data;
+  text_data.id = 2;
+  text_data.role = ax::mojom::Role::kStaticText;
+  text_data.SetName("some text");
+
+  ui::AXNodeData more_text_data;
+  more_text_data.id = 3;
+  more_text_data.role = ax::mojom::Role::kStaticText;
+  more_text_data.SetName("some text");
+
+  ui::AXNodeData root_data;
+  root_data.id = 1;
+  root_data.role = ax::mojom::Role::kRootWebArea;
+  root_data.child_ids.push_back(2);
+  root_data.child_ids.push_back(3);
+
+  ui::AXTreeUpdate update;
+  ui::AXTreeData tree_data;
+  tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+  update.tree_data = tree_data;
+  update.has_tree_data = true;
+  update.root_id = root_data.id;
+  update.nodes.push_back(root_data);
+  update.nodes.push_back(text_data);
+  update.nodes.push_back(more_text_data);
+
+  Init(update);
+
+  AXNode* root_node = GetRootNode();
+  AXNodePosition::SetTreeForTesting(tree_.get());
+  AXNode* text_node = root_node->children()[0];
+  AXNode* more_text_node = root_node->children()[1];
+
+  // Get the textRangeProvider for the document,
+  // which contains text "some textsome text".
+  ComPtr<IRawElementProviderSimple> root_node_raw =
+      QueryInterfaceFromNode<IRawElementProviderSimple>(root_node);
+  ComPtr<ITextProvider> document_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      root_node_raw->GetPatternProvider(UIA_TextPatternId, &document_provider));
+  ComPtr<ITextRangeProvider> document_text_range_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      document_provider->get_DocumentRange(&document_text_range_provider));
+
+  // Get the textRangeProvider for text_node which contains "some text".
+  ComPtr<IRawElementProviderSimple> text_node_raw =
+      QueryInterfaceFromNode<IRawElementProviderSimple>(text_node);
+  ComPtr<ITextProvider> text_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      text_node_raw->GetPatternProvider(UIA_TextPatternId, &text_provider));
+  ComPtr<ITextRangeProvider> text_range_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      text_provider->get_DocumentRange(&text_range_provider));
+
+  // Get the textRangeProvider for more_text_node which also contains
+  // "some text".
+  ComPtr<IRawElementProviderSimple> more_text_node_raw =
+      QueryInterfaceFromNode<IRawElementProviderSimple>(more_text_node);
+  ComPtr<ITextProvider> more_text_provider;
+  EXPECT_HRESULT_SUCCEEDED(more_text_node_raw->GetPatternProvider(
+      UIA_TextPatternId, &more_text_provider));
+  ComPtr<ITextRangeProvider> more_text_range_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      more_text_provider->get_DocumentRange(&more_text_range_provider));
+
+  BOOL result;
+
+  // Compare text range of the entire document with itself, which should return
+  // that they are equal.
+  EXPECT_HRESULT_SUCCEEDED(document_text_range_provider->Compare(
+      document_text_range_provider.Get(), &result));
+  EXPECT_TRUE(result);
+
+  // Compare the text range of the entire document with one of its child, which
+  // should return that they are not equal.
+  EXPECT_HRESULT_SUCCEEDED(document_text_range_provider->Compare(
+      text_range_provider.Get(), &result));
+  EXPECT_FALSE(result);
+
+  // Compare the text range of text_node which contains "some text" with
+  // text range of more_text_node which also contains "some text". Those two
+  // text ranges should not equal, because their endpoints are different, even
+  // though their contents are the same.
+  EXPECT_HRESULT_SUCCEEDED(
+      text_range_provider->Compare(more_text_range_provider.Get(), &result));
+  EXPECT_FALSE(result);
+}
+
 TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderSelection) {
   ui::AXNodeData text_data;
   text_data.id = 2;
@@ -646,4 +744,73 @@
   AXNodePosition::SetTreeForTesting(nullptr);
 }
 
+TEST_F(AXPlatformNodeTextRangeProviderTest,
+       TestITextRangeProviderGetEnclosingElement) {
+  ui::AXNodeData text_data;
+  text_data.id = 2;
+  text_data.role = ax::mojom::Role::kStaticText;
+  text_data.SetName("some text");
+
+  ui::AXNodeData more_text_data;
+  more_text_data.id = 3;
+  more_text_data.role = ax::mojom::Role::kStaticText;
+  more_text_data.SetName("more text");
+
+  ui::AXNodeData root_data;
+  root_data.id = 1;
+  root_data.role = ax::mojom::Role::kRootWebArea;
+  root_data.child_ids.push_back(2);
+  root_data.child_ids.push_back(3);
+
+  ui::AXTreeUpdate update;
+  ui::AXTreeData tree_data;
+  tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+  update.tree_data = tree_data;
+  update.has_tree_data = true;
+  update.root_id = root_data.id;
+  update.nodes.push_back(root_data);
+  update.nodes.push_back(text_data);
+  update.nodes.push_back(more_text_data);
+
+  Init(update);
+
+  // Test GetEnclosingElement for first child text node.
+  AXNode* root_node = GetRootNode();
+  AXNodePosition::SetTreeForTesting(tree_.get());
+  AXNode* text_node = root_node->children()[0];
+
+  ComPtr<IRawElementProviderSimple> text_node_raw =
+      QueryInterfaceFromNode<IRawElementProviderSimple>(text_node);
+
+  ComPtr<ITextProvider> text_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      text_node_raw->GetPatternProvider(UIA_TextPatternId, &text_provider));
+
+  ComPtr<ITextRangeProvider> text_range_provider;
+  EXPECT_HRESULT_SUCCEEDED(
+      text_provider->get_DocumentRange(&text_range_provider));
+
+  ComPtr<IRawElementProviderSimple> enclosing_element;
+  EXPECT_HRESULT_SUCCEEDED(
+      text_range_provider->GetEnclosingElement(&enclosing_element));
+
+  EXPECT_EQ(text_node_raw.Get(), enclosing_element.Get());
+
+  // Test GetEnclosingElement for second child text node.
+  text_node = root_node->children()[1];
+
+  text_node_raw = QueryInterfaceFromNode<IRawElementProviderSimple>(text_node);
+
+  EXPECT_HRESULT_SUCCEEDED(
+      text_node_raw->GetPatternProvider(UIA_TextPatternId, &text_provider));
+
+  EXPECT_HRESULT_SUCCEEDED(
+      text_provider->get_DocumentRange(&text_range_provider));
+
+  EXPECT_HRESULT_SUCCEEDED(
+      text_range_provider->GetEnclosingElement(&enclosing_element));
+
+  EXPECT_EQ(text_node_raw.Get(), enclosing_element.Get());
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index df2f462..0320de4 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -3669,11 +3669,11 @@
 
   UIA_VALIDATE_CALL_1_ARG(result);
 
-  const AXNodeData& data = GetData();
-  int int_attribute;
-  ax::mojom::IntListAttribute relation_attribute;
   result->vt = VT_EMPTY;
 
+  int int_attribute;
+  const AXNodeData& data = GetData();
+
   switch (property_id) {
     // Supported by IAccessibleEx.
     // TODO(suproteem): Implementations where applicable.
@@ -3706,8 +3706,8 @@
 
     case UIA_ControllerForPropertyId:
       result->vt = VT_ARRAY;
-      relation_attribute = ax::mojom::IntListAttribute::kControlsIds;
-      result->parray = CreateUIAElementsArrayForRelation(relation_attribute);
+      result->parray = CreateUIAElementsArrayForRelation(
+          ax::mojom::IntListAttribute::kControlsIds);
       break;
 
     case UIA_ControlTypePropertyId:
@@ -3723,8 +3723,8 @@
 
     case UIA_DescribedByPropertyId:
       result->vt = VT_ARRAY | VT_UNKNOWN;
-      relation_attribute = ax::mojom::IntListAttribute::kDescribedbyIds;
-      result->parray = CreateUIAElementsArrayForRelation(relation_attribute);
+      result->parray = CreateUIAElementsArrayForRelation(
+          ax::mojom::IntListAttribute::kDescribedbyIds);
       break;
 
     case UIA_FlowsFromPropertyId:
@@ -3735,8 +3735,8 @@
 
     case UIA_FlowsToPropertyId:
       result->vt = VT_ARRAY | VT_UNKNOWN;
-      relation_attribute = ax::mojom::IntListAttribute::kFlowtoIds;
-      result->parray = CreateUIAElementsArrayForRelation(relation_attribute);
+      result->parray = CreateUIAElementsArrayForRelation(
+          ax::mojom::IntListAttribute::kFlowtoIds);
       break;
 
     case UIA_FrameworkIdPropertyId:
@@ -3764,23 +3764,20 @@
       break;
 
     case UIA_IsDataValidForFormPropertyId:
-      if (GetIntAttribute(ax::mojom::IntAttribute::kInvalidState,
-                          &int_attribute)) {
+      if (data.GetIntAttribute(ax::mojom::IntAttribute::kInvalidState,
+                               &int_attribute)) {
         result->vt = VT_BOOL;
-        if (int_attribute ==
-            static_cast<int32_t>(ax::mojom::InvalidState::kFalse)) {
-          result->boolVal = VARIANT_TRUE;
-        } else {
-          result->boolVal = VARIANT_FALSE;
-        }
+        result->boolVal =
+            (static_cast<int>(ax::mojom::InvalidState::kFalse) == int_attribute)
+                ? VARIANT_TRUE
+                : VARIANT_FALSE;
       }
       break;
 
     case UIA_IsKeyboardFocusablePropertyId:
       result->vt = VT_BOOL;
-      result->boolVal = (ShouldNodeHaveFocusableState(delegate_->GetData()))
-                            ? VARIANT_TRUE
-                            : VARIANT_FALSE;
+      result->boolVal =
+          ShouldNodeHaveFocusableState(data) ? VARIANT_TRUE : VARIANT_FALSE;
       break;
 
     case UIA_IsOffscreenPropertyId:
@@ -3832,8 +3829,8 @@
       break;
 
     case UIA_LabeledByPropertyId:
-      relation_attribute = ax::mojom::IntListAttribute::kLabelledbyIds;
-      for (int32_t id : GetIntListAttribute(relation_attribute)) {
+      for (int32_t id : data.GetIntListAttribute(
+               ax::mojom::IntListAttribute::kLabelledbyIds)) {
         auto* node_win = GetDelegate()->GetFromNodeID(id);
         if (node_win) {
           DCHECK(node_win);
@@ -3846,7 +3843,8 @@
       break;
 
     case UIA_LocalizedControlTypePropertyId:
-      if (HasStringAttribute(ax::mojom::StringAttribute::kRoleDescription)) {
+      if (data.HasStringAttribute(
+              ax::mojom::StringAttribute::kRoleDescription)) {
         V_VT(result) = VT_BSTR;
         GetStringAttributeAsBstr(ax::mojom::StringAttribute::kRoleDescription,
                                  &V_BSTR(result));
@@ -3906,7 +3904,7 @@
       break;
 
     case UIA_AcceleratorKeyPropertyId:
-      if (HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) {
+      if (data.HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) {
         result->vt = VT_BSTR;
         GetStringAttributeAsBstr(ax::mojom::StringAttribute::kKeyShortcuts,
                                  &result->bstrVal);
@@ -3914,7 +3912,7 @@
       break;
 
     case UIA_AccessKeyPropertyId:
-      if (HasStringAttribute(ax::mojom::StringAttribute::kAccessKey)) {
+      if (data.HasStringAttribute(ax::mojom::StringAttribute::kAccessKey)) {
         result->vt = VT_BSTR;
         GetStringAttributeAsBstr(ax::mojom::StringAttribute::kAccessKey,
                                  &result->bstrVal);
@@ -3927,25 +3925,27 @@
       break;
 
     case UIA_LevelPropertyId:
-      if (HasIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel)) {
+      if (data.GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
+                               &int_attribute)) {
         result->vt = VT_I4;
-        result->intVal =
-            GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel);
+        result->intVal = int_attribute;
       }
       break;
 
-    case UIA_LiveSettingPropertyId:
+    case UIA_LiveSettingPropertyId: {
       result->vt = VT_I4;
       result->intVal = LiveSetting::Off;
-      if (HasStringAttribute(ax::mojom::StringAttribute::kLiveStatus)) {
-        std::string live =
-            GetStringAttribute(ax::mojom::StringAttribute::kLiveStatus);
-        if (live == "polite")
+
+      std::string string_attribute;
+      if (data.GetStringAttribute(ax::mojom::StringAttribute::kLiveStatus,
+                                  &string_attribute)) {
+        if (string_attribute == "polite")
           result->intVal = LiveSetting::Polite;
-        else if (live == "assertive")
+        else if (string_attribute == "assertive")
           result->intVal = LiveSetting::Assertive;
       }
       break;
+    }
 
     case UIA_OptimizeForVisualContentPropertyId:
       result->vt = VT_BOOL;
@@ -3960,12 +3960,32 @@
       break;
 
     case UIA_SizeOfSetPropertyId:
-      if (HasIntAttribute(ax::mojom::IntAttribute::kSetSize)) {
+      if (data.GetIntAttribute(ax::mojom::IntAttribute::kSetSize,
+                               &int_attribute)) {
         result->vt = VT_I4;
-        result->intVal = GetIntAttribute(ax::mojom::IntAttribute::kSetSize);
+        result->intVal = int_attribute;
       }
       break;
 
+    case UIA_LandmarkTypePropertyId: {
+      base::Optional<LONG> landmark_type = ComputeUIALandmarkType();
+      if (landmark_type) {
+        result->vt = VT_I4;
+        result->intVal = landmark_type.value();
+      }
+      break;
+    }
+
+    case UIA_LocalizedLandmarkTypePropertyId: {
+      base::string16 localized_landmark_type =
+          GetDelegate()->GetLocalizedStringForLandmarkType();
+      if (!localized_landmark_type.empty()) {
+        result->vt = VT_BSTR;
+        result->bstrVal = SysAllocString(localized_landmark_type.c_str());
+      }
+      break;
+    }
+
     // Covered by MSAA.
     case UIA_BoundingRectanglePropertyId:
     case UIA_HelpTextPropertyId:
@@ -3982,8 +4002,6 @@
     case UIA_FillTypePropertyId:
     case UIA_GroupControlTypeId:
     case UIA_HeadingLevelPropertyId:
-    case UIA_LandmarkTypePropertyId:
-    case UIA_LocalizedLandmarkTypePropertyId:
     case UIA_MenuControlTypeId:
     case UIA_OutlineColorPropertyId:
     case UIA_OutlineThicknessPropertyId:
@@ -4145,6 +4163,7 @@
       return ROLE_SYSTEM_GROUPING;
 
     case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
       return ROLE_SYSTEM_GROUPING;
 
     case ax::mojom::Role::kDate:
@@ -4248,9 +4267,6 @@
     case ax::mojom::Role::kFeed:
       return ROLE_SYSTEM_GROUPING;
 
-    case ax::mojom::Role::kFooter:
-      return ROLE_SYSTEM_GROUPING;
-
     case ax::mojom::Role::kForm:
       return ROLE_SYSTEM_GROUPING;
 
@@ -4675,8 +4691,8 @@
 
   switch (GetData().role) {
     case ax::mojom::Role::kBanner:
-      // CORE-AAM recommends IA2_ROLE_LANDMARK.
-      ia2_role = IA2_ROLE_HEADER;
+      // CORE-AAM recommends LANDMARK instead of HEADER.
+      ia2_role = IA2_ROLE_LANDMARK;
       break;
     case ax::mojom::Role::kBlockquote:
       ia2_role = IA2_ROLE_SECTION;
@@ -4693,8 +4709,7 @@
       ia2_role = IA2_ROLE_COLOR_CHOOSER;
       break;
     case ax::mojom::Role::kComplementary:
-      // Note: IA2_ROLE_COMPLEMENTARY_CONTENT currently exists but CORE-AAM
-      // maps this to more general IA2_ROLE_LANDMARK.
+      // CORE-AAM recommends LANDMARK instead of COMPLEMENTARY_CONTENT.
       ia2_role = IA2_ROLE_LANDMARK;
       break;
     case ax::mojom::Role::kContentDeletion:
@@ -4704,6 +4719,8 @@
       ia2_role = IA2_ROLE_CONTENT_INSERTION;
       break;
     case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
+      // CORE-AAM recommends LANDMARK instead of FOOTER.
       ia2_role = IA2_ROLE_LANDMARK;
       break;
     case ax::mojom::Role::kDate:
@@ -4768,9 +4785,6 @@
     case ax::mojom::Role::kForm:
       ia2_role = IA2_ROLE_FORM;
       break;
-    case ax::mojom::Role::kFooter:
-      ia2_role = IA2_ROLE_FOOTER;
-      break;
     case ax::mojom::Role::kGenericContainer:
       ia2_role = IA2_ROLE_SECTION;
       break;
@@ -4941,6 +4955,7 @@
       return L"group";
 
     case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
       return L"contentinfo";
 
     case ax::mojom::Role::kDate:
@@ -5044,9 +5059,6 @@
     case ax::mojom::Role::kFigure:
       return L"group";
 
-    case ax::mojom::Role::kFooter:
-      return L"group";
-
     case ax::mojom::Role::kForm:
       return L"form";
 
@@ -5564,6 +5576,7 @@
       return UIA_GroupControlTypeId;
 
     case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
       return UIA_GroupControlTypeId;
 
     case ax::mojom::Role::kDate:
@@ -5667,9 +5680,6 @@
     case ax::mojom::Role::kFigure:
       return UIA_GroupControlTypeId;
 
-    case ax::mojom::Role::kFooter:
-      return UIA_GroupControlTypeId;
-
     case ax::mojom::Role::kForm:
       return UIA_GroupControlTypeId;
 
@@ -6011,6 +6021,37 @@
            data.role == ax::mojom::Role::kIgnored);
 }
 
+base::Optional<LONG> AXPlatformNodeWin::ComputeUIALandmarkType() const {
+  const AXNodeData& data = GetData();
+  switch (data.role) {
+    case ax::mojom::Role::kBanner:
+    case ax::mojom::Role::kComplementary:
+    case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
+      return UIA_CustomLandmarkTypeId;
+
+    case ax::mojom::Role::kForm:
+      return UIA_FormLandmarkTypeId;
+
+    case ax::mojom::Role::kMain:
+      return UIA_MainLandmarkTypeId;
+
+    case ax::mojom::Role::kNavigation:
+      return UIA_NavigationLandmarkTypeId;
+
+    case ax::mojom::Role::kSearch:
+      return UIA_SearchLandmarkTypeId;
+
+    case ax::mojom::Role::kRegion:
+      if (data.HasStringAttribute(ax::mojom::StringAttribute::kName))
+        return UIA_CustomLandmarkTypeId;
+      FALLTHROUGH;
+
+    default:
+      return {};
+  }
+}
+
 base::string16 AXPlatformNodeWin::GetValue() const {
   base::string16 value = AXPlatformNodeBase::GetValue();
 
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 408cd723..3cbae56 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -922,6 +922,8 @@
 
   bool IsUIAControl() const;
 
+  base::Optional<LONG> ComputeUIALandmarkType() const;
+
   // AXPlatformNodeBase overrides.
   void Dispose() override;
 
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 3bfbbbd9..11124fe 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -60,6 +60,14 @@
 // WARNING: These aren't intended to be generic EXPECT_BSTR_EQ macros
 // as the logic is specific to extracting and comparing UIA property
 // values.
+#define EXPECT_UIA_EMPTY(node, property_id)                     \
+  {                                                             \
+    ScopedVariant actual;                                       \
+    ASSERT_HRESULT_SUCCEEDED(                                   \
+        node->GetPropertyValue(property_id, actual.Receive())); \
+    EXPECT_EQ(VT_EMPTY, actual.type());                         \
+  }
+
 #define EXPECT_UIA_VALUE_EQ(node, property_id, expectedVariant) \
   {                                                             \
     ScopedVariant actual;                                       \
@@ -4052,6 +4060,90 @@
       UIA_ControlTypePropertyId, int{UIA_TableControlTypeId});
 }
 
+TEST_F(AXPlatformNodeWinTest, TestUIALandmarkType) {
+  auto TestLandmarkType = [this](ax::mojom::Role node_role,
+                                 base::Optional<LONG> expected_landmark_type,
+                                 const std::string& node_name = {}) {
+    AXNodeData root_data;
+    root_data.id = 0;
+    root_data.role = node_role;
+    if (!node_name.empty())
+      root_data.SetName(node_name);
+    Init(root_data);
+
+    ComPtr<IRawElementProviderSimple> root_provider =
+        GetRootIRawElementProviderSimple();
+
+    if (expected_landmark_type) {
+      EXPECT_UIA_INT_EQ(root_provider, UIA_LandmarkTypePropertyId,
+                        expected_landmark_type.value());
+    } else {
+      EXPECT_UIA_EMPTY(root_provider, UIA_LandmarkTypePropertyId);
+    }
+  };
+
+  TestLandmarkType(ax::mojom::Role::kBanner, UIA_CustomLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kComplementary, UIA_CustomLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kContentInfo, UIA_CustomLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kFooter, UIA_CustomLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kForm, UIA_FormLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kMain, UIA_MainLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kNavigation, UIA_NavigationLandmarkTypeId);
+  TestLandmarkType(ax::mojom::Role::kSearch, UIA_SearchLandmarkTypeId);
+
+  // Only named regions should be exposed as landmarks.
+  TestLandmarkType(ax::mojom::Role::kRegion, {});
+  TestLandmarkType(ax::mojom::Role::kRegion, UIA_CustomLandmarkTypeId, "name");
+
+  TestLandmarkType(ax::mojom::Role::kGroup, {});
+  TestLandmarkType(ax::mojom::Role::kHeading, {});
+  TestLandmarkType(ax::mojom::Role::kList, {});
+  TestLandmarkType(ax::mojom::Role::kTable, {});
+}
+
+TEST_F(AXPlatformNodeWinTest, TestUIALocalizedLandmarkType) {
+  auto TestLocalizedLandmarkType =
+      [this](ax::mojom::Role node_role,
+             const std::wstring& expected_localized_landmark,
+             const std::string& node_name = {}) {
+        AXNodeData root_data;
+        root_data.id = 0;
+        root_data.role = node_role;
+        if (!node_name.empty())
+          root_data.SetName(node_name);
+        Init(root_data);
+
+        ComPtr<IRawElementProviderSimple> root_provider =
+            GetRootIRawElementProviderSimple();
+
+        if (expected_localized_landmark.empty()) {
+          EXPECT_UIA_EMPTY(root_provider, UIA_LocalizedLandmarkTypePropertyId);
+        } else {
+          EXPECT_UIA_BSTR_EQ(root_provider, UIA_LocalizedLandmarkTypePropertyId,
+                             expected_localized_landmark.c_str());
+        }
+      };
+
+  TestLocalizedLandmarkType(ax::mojom::Role::kBanner, L"banner");
+  TestLocalizedLandmarkType(ax::mojom::Role::kComplementary, L"complementary");
+  TestLocalizedLandmarkType(ax::mojom::Role::kContentInfo,
+                            L"content information");
+  TestLocalizedLandmarkType(ax::mojom::Role::kFooter, L"content information");
+
+  // Only named regions should be exposed as landmarks.
+  TestLocalizedLandmarkType(ax::mojom::Role::kRegion, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kRegion, L"region", "name");
+
+  TestLocalizedLandmarkType(ax::mojom::Role::kForm, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kGroup, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kHeading, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kList, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kMain, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kNavigation, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kSearch, {});
+  TestLocalizedLandmarkType(ax::mojom::Role::kTable, {});
+}
+
 TEST_F(AXPlatformNodeWinTest, TestIRawElementProviderSimple2ShowContextMenu) {
   AXNodeData root_data;
   root_data.id = 0;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc
index a572291..a686615 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -405,6 +405,29 @@
   return base::ASCIIToUTF16("Unlabeled image");
 }
 
+base::string16 TestAXNodeWrapper::GetLocalizedStringForLandmarkType() const {
+  const AXNodeData& data = GetData();
+  switch (data.role) {
+    case ax::mojom::Role::kBanner:
+      return base::ASCIIToUTF16("banner");
+
+    case ax::mojom::Role::kComplementary:
+      return base::ASCIIToUTF16("complementary");
+
+    case ax::mojom::Role::kContentInfo:
+    case ax::mojom::Role::kFooter:
+      return base::ASCIIToUTF16("content information");
+
+    case ax::mojom::Role::kRegion:
+      if (data.HasStringAttribute(ax::mojom::StringAttribute::kName))
+        return base::ASCIIToUTF16("region");
+      FALLTHROUGH;
+
+    default:
+      return {};
+  }
+}
+
 base::string16 TestAXNodeWrapper::GetLocalizedStringForImageAnnotationStatus(
     ax::mojom::ImageAnnotationStatus status) const {
   switch (status) {
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h
index 72630e3..7eb76d0 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -87,6 +87,7 @@
   gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
   bool AccessibilityPerformAction(const AXActionData& data) override;
   base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() const override;
+  base::string16 GetLocalizedStringForLandmarkType() const override;
   base::string16 GetLocalizedStringForImageAnnotationStatus(
       ax::mojom::ImageAnnotationStatus status) const override;
   bool ShouldIgnoreHoveredStateForTesting() override;
diff --git a/ui/android/java/res/values-v17/styles.xml b/ui/android/java/res/values-v17/styles.xml
index fcf4e04..472fc605 100644
--- a/ui/android/java/res/values-v17/styles.xml
+++ b/ui/android/java/res/values-v17/styles.xml
@@ -187,6 +187,9 @@
         <item name="android:textSize">@dimen/text_size_medium</item>
         <item name="android:textStyle">bold</item>
     </style>
+    <style name="TextAppearance.Headline.Inverse" parent="TextAppearance.WhiteHeadline" tools:ignore="UnusedResources">
+        <item name="android:textColor">@color/default_text_color_inverse</item>
+    </style>
 
     <!-- Blue Text Styles -->
     <style name="TextAppearance.BlueTitle2" parent="TextAppearance.RobotoMediumStyle" tools:ignore="UnusedResources">
diff --git a/ui/android/java/res/values/colors.xml b/ui/android/java/res/values/colors.xml
index b17c2157..2fa67a37 100644
--- a/ui/android/java/res/values/colors.xml
+++ b/ui/android/java/res/values/colors.xml
@@ -23,6 +23,12 @@
     <color name="default_icon_color_disabled" tools:ignore="UnusedResources">
         @color/default_icon_color_dark_disabled
     </color>
+    <color name="default_icon_color_inverse" tools:ignore="UnusedResources">
+        @color/default_icon_color_white
+    </color>
+    <color name="default_icon_color_inverse_disabled" tools:ignore="UnusedResources">
+        @color/white_alpha_38
+    </color>
     <color name="default_icon_color_blue" tools:ignore="UnusedResources">
         @color/modern_blue_600
     </color>
diff --git a/ui/android/java/res_night/values-night/colors.xml b/ui/android/java/res_night/values-night/colors.xml
index b3d577ad9..29967f1 100644
--- a/ui/android/java/res_night/values-night/colors.xml
+++ b/ui/android/java/res_night/values-night/colors.xml
@@ -14,6 +14,8 @@
     <!-- Common icon colors for drawables. -->
     <color name="default_icon_color">@color/default_icon_color_white</color>
     <color name="default_icon_color_disabled">@color/default_icon_color_white_disabled</color>
+    <color name="default_icon_color_inverse">@color/default_icon_color_dark</color>
+    <color name="default_icon_color_inverse_disabled">@color/default_icon_color_dark_disabled</color>
     <color name="default_icon_color_blue">@color/modern_blue_300</color>
     <color name="hairline_stroke_color">@color/white_alpha_10</color>
 
diff --git a/ui/aura/event_injector.cc b/ui/aura/event_injector.cc
index ac7df55..4fdfc171 100644
--- a/ui/aura/event_injector.cc
+++ b/ui/aura/event_injector.cc
@@ -11,6 +11,7 @@
 #include "services/ws/public/mojom/constants.mojom.h"
 #include "ui/aura/env.h"
 #include "ui/aura/mus/window_tree_client.h"
+#include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/events/event.h"
@@ -27,6 +28,24 @@
   std::move(callback).Run();
 }
 
+// Updates the location of |event| to be relative to the display |host| is
+// on. It is assumed at the time this is called the location of the event is
+// relative to |host|.
+void ConvertHostLocationToDisplayLocation(WindowTreeHost* host,
+                                          ui::LocatedEvent* event) {
+  WindowTreeHostMus* host_mus = WindowTreeHostMus::ForWindow(host->window());
+  DCHECK(host_mus);
+  // WindowTreeHostMus's bounds are in screen coordinates, convert to display
+  // relative.
+  gfx::PointF location =
+      gfx::PointF(host_mus->bounds_in_dip().origin() -
+                  host_mus->GetDisplay().bounds().origin().OffsetFromOrigin());
+  // And then add the event location.
+  location += event->root_location_f().OffsetFromOrigin();
+  event->set_root_location_f(location);
+  event->set_location_f(location);
+}
+
 }  // namespace
 
 EventInjector::EventInjector() {}
@@ -46,6 +65,15 @@
   DCHECK(event);
 
   if (env->mode() == Env::Mode::LOCAL) {
+    if (event->IsLocatedEvent()) {
+      ui::LocatedEvent* located_event = event->AsLocatedEvent();
+      // Transforming the coordinate to the root will apply the screen scale
+      // factor to the event's location and also the screen rotation degree.
+      located_event->UpdateForRootTransform(
+          host->GetRootTransform(),
+          host->GetRootTransformForLocalEventCoordinates());
+    }
+
     ui::EventDispatchDetails details =
         host->event_sink()->OnEventFromSource(event);
     RunCallback(std::move(callback), /*processed=*/true);
@@ -55,18 +83,21 @@
   has_pending_callback_ |= !callback.is_null();
 
   if (event->IsLocatedEvent()) {
-    // The ui-service expects events coming in to have a location matching the
-    // root location. The non-ui-service code does this by way of
-    // OnEventFromSource() ending up in LocatedEvent::UpdateForRootTransform(),
-    // which reset the root_location to match the location.
+    // The window-service expects events coming in to have a location matching
+    // the root location.
     event->AsLocatedEvent()->set_root_location_f(
         event->AsLocatedEvent()->location_f());
+
+    // Convert the location to be display relative. This is *not* needed in the
+    // classic case as the WindowTreeHost and the display are the same.
+    ConvertHostLocationToDisplayLocation(host, event->AsLocatedEvent());
   }
 
   if (!event_injector_) {
     env->window_tree_client_->connector()->BindInterface(
         ws::mojom::kServiceName, &event_injector_);
   }
+
   event_injector_->InjectEvent(
       host->GetDisplayId(), ui::Event::Clone(*event),
       base::BindOnce(&RunCallback, std::move(callback)));
diff --git a/ui/aura/event_injector.h b/ui/aura/event_injector.h
index babe83c..725bfcf 100644
--- a/ui/aura/event_injector.h
+++ b/ui/aura/event_injector.h
@@ -20,7 +20,7 @@
 
 // Used to inject events into the system. In LOCAL mode, it directly injects
 // events into the WindowTreeHost, but in MUS mode, it injects events into the
-// window-server (over the mojom API).
+// window-service (over the mojom API).
 class AURA_EXPORT EventInjector {
  public:
   EventInjector();
@@ -29,7 +29,8 @@
   // Inject |event| to |host|. |callback| is optional that gets invoked after
   // the event is processed by |host|. In LOCAL mode,  |callback| is invoked
   // synchronously. In MUS mode, it is invoked after a response is received
-  // from window-server (via mojo).
+  // from the window service (via mojo). If |event| is a LocatedEvent, then
+  // coordinates are relative to host and in DIPs.
   ui::EventDispatchDetails Inject(
       WindowTreeHost* host,
       ui::Event* event,
diff --git a/ui/events/test/test_event_rewriter.cc b/ui/events/test/test_event_rewriter.cc
index a5bd81e..185f304 100644
--- a/ui/events/test/test_event_rewriter.cc
+++ b/ui/events/test/test_event_rewriter.cc
@@ -17,6 +17,7 @@
     const ui::Event& event,
     const Continuation continuation) {
   ++events_seen_;
+  last_event_ = ui::Event::Clone(event);
   return SendEvent(continuation, &event);
 }
 
diff --git a/ui/events/test/test_event_rewriter.h b/ui/events/test/test_event_rewriter.h
index bb25e041..fa2f782 100644
--- a/ui/events/test/test_event_rewriter.h
+++ b/ui/events/test/test_event_rewriter.h
@@ -5,6 +5,8 @@
 #ifndef UI_EVENTS_TEST_TEST_EVENT_REWRITER_H_
 #define UI_EVENTS_TEST_TEST_EVENT_REWRITER_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "ui/events/event_rewriter.h"
 
@@ -19,6 +21,8 @@
 
   void clear_events_seen() { events_seen_ = 0; }
   int events_seen() const { return events_seen_; }
+  const ui::Event* last_event() const { return last_event_.get(); }
+  void ResetLastEvent() { last_event_.reset(); }
 
   // ui::EventRewriter:
   ui::EventDispatchDetails RewriteEvent(
@@ -27,6 +31,7 @@
 
  private:
   int events_seen_ = 0;
+  std::unique_ptr<ui::Event> last_event_;
 
   DISALLOW_COPY_AND_ASSIGN(TestEventRewriter);
 };
diff --git a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
index 7b18f2a..7aff59d 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
@@ -182,6 +182,9 @@
     const option = document.createElement('option');
     option.innerText = str('ALL_FILES_FILTER');
     option.value = 0;
+    if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) {
+      option.selected = true;
+    }
     this.fileTypeSelector.appendChild(option);
   }
 
diff --git a/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js b/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js
index 562de7e..aa1ae6d 100644
--- a/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js
+++ b/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js
@@ -355,6 +355,12 @@
         'button:not(.crop-aspect-ratio), paper-button, input, cr-slider, cr-input');
     if (input) {
       input.focus();
+      // Fix for crbug/914741 set selection to the end (> 32-bit int)
+      // Note the input element lives in Shadow DOM.
+      if (input.select && input.tagName) {
+        assert(input.tagName === 'CR-INPUT');
+        input.select(12, 12);
+      }
     }
   }
 };
diff --git a/ui/file_manager/integration_tests/file_manager/file_dialog.js b/ui/file_manager/integration_tests/file_manager/file_dialog.js
index 37ce590..118308c 100644
--- a/ui/file_manager/integration_tests/file_manager/file_dialog.js
+++ b/ui/file_manager/integration_tests/file_manager/file_dialog.js
@@ -370,3 +370,42 @@
   const dialog = await remoteCall.waitForWindow('dialog#');
   await unloadOpenFileDialog(dialog);
 };
+
+/**
+ * Tests that the open file dialog's filetype filter does not default to all
+ * types.
+ */
+testcase.openFileDialogDefaultFilter = async () => {
+  const params = {
+    type: 'openFile',
+    accepts: [{extensions: ['jpg']}],
+    acceptsAllTypes: true,
+  };
+  chrome.fileSystem.chooseEntry(params, (entry) => {});
+  const dialog = await remoteCall.waitForWindow('dialog#');
+
+  // Check: 'JPEG image' should be selected.
+  const selectedFilter =
+      await remoteCall.waitForElement(dialog, '.file-type option:checked');
+  chrome.test.assertEq('1', selectedFilter.value);
+  chrome.test.assertEq('JPEG image', selectedFilter.text);
+};
+
+/**
+ * Tests that the save file dialog's filetype filter defaults to all types.
+ */
+testcase.saveFileDialogDefaultFilter = async () => {
+  const params = {
+    type: 'saveFile',
+    accepts: [{extensions: ['jpg']}],
+    acceptsAllTypes: true,
+  };
+  chrome.fileSystem.chooseEntry(params, (entry) => {});
+  const dialog = await remoteCall.waitForWindow('dialog#');
+
+  // Check: 'All files' should be selected.
+  const selectedFilter =
+      await remoteCall.waitForElement(dialog, '.file-type option:checked');
+  chrome.test.assertEq('0', selectedFilter.value);
+  chrome.test.assertEq('All files', selectedFilter.text);
+};
diff --git a/ui/login/OWNERS b/ui/login/OWNERS
index 73d229a..c801b775 100644
--- a/ui/login/OWNERS
+++ b/ui/login/OWNERS
@@ -1,4 +1,5 @@
 achuith@chromium.org
 alemate@chromium.org
 jdufault@chromium.org
+tbarzic@chromium.org
 xiyuan@chromium.org
diff --git a/ui/views/accessibility/ax_tree_source_views_unittest.cc b/ui/views/accessibility/ax_tree_source_views_unittest.cc
index 7ce02c4..dde5046a 100644
--- a/ui/views/accessibility/ax_tree_source_views_unittest.cc
+++ b/ui/views/accessibility/ax_tree_source_views_unittest.cc
@@ -26,7 +26,7 @@
 // TestAXTreeSourceViews provides a root with a default tree ID.
 class TestAXTreeSourceViews : public AXTreeSourceViews {
  public:
-  TestAXTreeSourceViews(AXAuraObjWrapper* root)
+  explicit TestAXTreeSourceViews(AXAuraObjWrapper* root)
       : AXTreeSourceViews(root, ui::AXTreeID::CreateNewAXTreeID()) {}
 
   ~TestAXTreeSourceViews() override = default;
diff --git a/ui/views/accessible_pane_view.cc b/ui/views/accessible_pane_view.cc
index a0b033b1..19f83de 100644
--- a/ui/views/accessible_pane_view.cc
+++ b/ui/views/accessible_pane_view.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/accessible_pane_view.h"
 
+#include <memory>
+
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/views/focus/focus_search.h"
 #include "ui/views/view_tracker.h"
@@ -51,7 +53,7 @@
       right_key_(ui::VKEY_RIGHT, ui::EF_NONE),
       last_focused_view_tracker_(std::make_unique<ViewTracker>()),
       method_factory_(this) {
-  focus_search_.reset(new AccessiblePaneViewFocusSearch(this));
+  focus_search_ = std::make_unique<AccessiblePaneViewFocusSearch>(this);
 }
 
 AccessiblePaneView::~AccessiblePaneView() {
diff --git a/ui/views/accessible_pane_view_unittest.cc b/ui/views/accessible_pane_view_unittest.cc
index 0f41662..b7dc491 100644
--- a/ui/views/accessible_pane_view_unittest.cc
+++ b/ui/views/accessible_pane_view_unittest.cc
@@ -17,7 +17,7 @@
 // TODO(alicet): bring pane rotation into views and add tests.
 //               See browser_view.cc for details.
 
-typedef ViewsTestBase AccessiblePaneViewTest;
+using AccessiblePaneViewTest = ViewsTestBase;
 
 class TestBarView : public AccessiblePaneView,
                     public ButtonListener {
@@ -59,13 +59,13 @@
 void TestBarView::Init() {
   SetLayoutManager(std::make_unique<FillLayout>());
   base::string16 label;
-  child_button_.reset(new LabelButton(this, label));
+  child_button_ = std::make_unique<LabelButton>(this, label);
   AddChildView(child_button_.get());
-  second_child_button_.reset(new LabelButton(this, label));
+  second_child_button_ = std::make_unique<LabelButton>(this, label);
   AddChildView(second_child_button_.get());
-  third_child_button_.reset(new LabelButton(this, label));
+  third_child_button_ = std::make_unique<LabelButton>(this, label);
   AddChildView(third_child_button_.get());
-  not_child_button_.reset(new LabelButton(this, label));
+  not_child_button_ = std::make_unique<LabelButton>(this, label);
 }
 
 View* TestBarView::GetDefaultFocusableChild() {
diff --git a/ui/views/animation/flood_fill_ink_drop_ripple.cc b/ui/views/animation/flood_fill_ink_drop_ripple.cc
index dd0864c..ea53714 100644
--- a/ui/views/animation/flood_fill_ink_drop_ripple.cc
+++ b/ui/views/animation/flood_fill_ink_drop_ripple.cc
@@ -21,7 +21,7 @@
 
 // The minimum radius to use when scaling the painted layers. Smaller values
 // were causing visual anomalies.
-const float kMinRadius = 1.f;
+constexpr float kMinRadius = 1.f;
 
 // All the sub animations that are used to animate each of the InkDropStates.
 // These are used to get time durations with
diff --git a/ui/views/animation/ink_drop_impl.cc b/ui/views/animation/ink_drop_impl.cc
index dcad6d4e..2c8b6c5 100644
--- a/ui/views/animation/ink_drop_impl.cc
+++ b/ui/views/animation/ink_drop_impl.cc
@@ -19,29 +19,29 @@
 
 // The duration, in milliseconds for the highlight state fade in/out animations
 // when it is triggered by a hover changed event.
-const int kHighlightFadeInOnHoverChangeDurationMs = 250;
-const int kHighlightFadeOutOnHoverChangeDurationMs = 250;
+constexpr int kHighlightFadeInOnHoverChangeDurationMs = 250;
+constexpr int kHighlightFadeOutOnHoverChangeDurationMs = 250;
 
 // The duration, in milliseconds for the highlight state fade in/out animations
 // when it is triggered by a focus changed event.
-const int kHighlightFadeInOnFocusChangeDurationMs = 0;
-const int kHighlightFadeOutOnFocusChangeDurationMs = 0;
+constexpr int kHighlightFadeInOnFocusChangeDurationMs = 0;
+constexpr int kHighlightFadeOutOnFocusChangeDurationMs = 0;
 
 // The duration, in milliseconds, for showing/hiding the highlight when
 // triggered by ripple visibility changes for the HIDE_ON_RIPPLE
 // AutoHighlightMode.
-const int kHighlightFadeInOnRippleHidingDurationMs = 250;
-const int kHighlightFadeOutOnRippleShowingDurationMs = 120;
+constexpr int kHighlightFadeInOnRippleHidingDurationMs = 250;
+constexpr int kHighlightFadeOutOnRippleShowingDurationMs = 120;
 
 // The duration, in milliseconds, for showing/hiding the highlight when
 // triggered by ripple visibility changes for the SHOW_ON_RIPPLE
 // AutoHighlightMode.
-const int kHighlightFadeInOnRippleShowingDurationMs = 250;
-const int kHighlightFadeOutOnRippleHidingDurationMs = 120;
+constexpr int kHighlightFadeInOnRippleShowingDurationMs = 250;
+constexpr int kHighlightFadeOutOnRippleHidingDurationMs = 120;
 
 // The amount of time in milliseconds that |highlight_| should delay after a
 // ripple animation before fading in, for highlight due to mouse hover.
-const int kHoverFadeInAfterRippleDelayMs = 1000;
+constexpr int kHoverFadeInAfterRippleDelayMs = 1000;
 
 // Returns true if an ink drop with the given |ink_drop_state| should
 // automatically transition to the InkDropState::HIDDEN state.
@@ -380,7 +380,7 @@
 
 void InkDropImpl::HideHighlightOnRippleHiddenState::
     StartHighlightAfterRippleTimer() {
-  highlight_after_ripple_timer_.reset(new base::OneShotTimer);
+  highlight_after_ripple_timer_ = std::make_unique<base::OneShotTimer>();
   highlight_after_ripple_timer_->Start(
       FROM_HERE,
       base::TimeDelta::FromMilliseconds(kHoverFadeInAfterRippleDelayMs),
diff --git a/ui/views/animation/ink_drop_impl_unittest.cc b/ui/views/animation/ink_drop_impl_unittest.cc
index 3467a8f..267342a 100644
--- a/ui/views/animation/ink_drop_impl_unittest.cc
+++ b/ui/views/animation/ink_drop_impl_unittest.cc
@@ -320,7 +320,7 @@
 // Common AutoHighlightMode tests
 //
 
-typedef InkDropImplAutoHighlightTest InkDropImplCommonAutoHighlightTest;
+using InkDropImplCommonAutoHighlightTest = InkDropImplAutoHighlightTest;
 // Note: First argument is optional and intentionally left blank.
 // (it's a prefix for the generated test cases)
 INSTANTIATE_TEST_SUITE_P(
@@ -368,7 +368,7 @@
 // InkDropImpl::AutoHighlightMode::NONE specific tests
 //
 
-typedef InkDropImplAutoHighlightTest InkDropImplNoAutoHighlightTest;
+using InkDropImplNoAutoHighlightTest = InkDropImplAutoHighlightTest;
 // Note: First argument is optional and intentionally left blank.
 // (it's a prefix for the generated test cases)
 INSTANTIATE_TEST_SUITE_P(,
@@ -404,7 +404,7 @@
 // InkDropImpl::AutoHighlightMode::HIDE_ON_RIPPLE specific tests
 //
 
-typedef InkDropImplAutoHighlightTest InkDropImplHideAutoHighlightTest;
+using InkDropImplHideAutoHighlightTest = InkDropImplAutoHighlightTest;
 // Note: First argument is optional and intentionally left blank.
 // (it's a prefix for the generated test cases)
 INSTANTIATE_TEST_SUITE_P(
@@ -564,7 +564,7 @@
 // InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE specific tests
 //
 
-typedef InkDropImplAutoHighlightTest InkDropImplShowAutoHighlightTest;
+using InkDropImplShowAutoHighlightTest = InkDropImplAutoHighlightTest;
 // Note: First argument is optional and intentionally left blank.
 // (it's a prefix for the generated test cases)
 INSTANTIATE_TEST_SUITE_P(
diff --git a/ui/views/animation/ink_drop_ripple_unittest.cc b/ui/views/animation/ink_drop_ripple_unittest.cc
index 519f0a95c..c44f113a 100644
--- a/ui/views/animation/ink_drop_ripple_unittest.cc
+++ b/ui/views/animation/ink_drop_ripple_unittest.cc
@@ -70,7 +70,8 @@
           new SquareInkDropRipple(gfx::Size(10, 10), 2, gfx::Size(8, 8), 1,
                                   gfx::Point(), SK_ColorBLACK, kVisibleOpacity);
       ink_drop_ripple_.reset(square_ink_drop_ripple);
-      test_api_.reset(new SquareInkDropRippleTestApi(square_ink_drop_ripple));
+      test_api_ =
+          std::make_unique<SquareInkDropRippleTestApi>(square_ink_drop_ripple);
       break;
     }
     case FLOOD_FILL_INK_DROP_RIPPLE: {
@@ -78,8 +79,8 @@
           new FloodFillInkDropRipple(gfx::Size(10, 10), gfx::Point(),
                                      SK_ColorBLACK, kVisibleOpacity);
       ink_drop_ripple_.reset(flood_fill_ink_drop_ripple);
-      test_api_.reset(
-          new FloodFillInkDropRippleTestApi(flood_fill_ink_drop_ripple));
+      test_api_ = std::make_unique<FloodFillInkDropRippleTestApi>(
+          flood_fill_ink_drop_ripple);
       break;
     }
   }
diff --git a/ui/views/animation/ink_drop_unittest.cc b/ui/views/animation/ink_drop_unittest.cc
index 4d620df45..59fcd72 100644
--- a/ui/views/animation/ink_drop_unittest.cc
+++ b/ui/views/animation/ink_drop_unittest.cc
@@ -27,7 +27,7 @@
 class InkDropTest : public testing::TestWithParam<testing::tuple<InkDropType>> {
  public:
   InkDropTest();
-  ~InkDropTest();
+  ~InkDropTest() override;
 
  protected:
   // A dummy InkDropHost required to create an InkDrop.
@@ -49,21 +49,22 @@
 };
 
 InkDropTest::InkDropTest() : ink_drop_(nullptr) {
-  zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode(
-      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
+  zero_duration_mode_ = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
+      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
 
   switch (GetInkDropType()) {
     case INK_DROP_STUB:
-      ink_drop_.reset(new InkDropStub());
+      ink_drop_ = std::make_unique<InkDropStub>();
       break;
     case INK_DROP_IMPL:
-      ink_drop_.reset(new InkDropImpl(&test_ink_drop_host_, gfx::Size()));
+      ink_drop_ =
+          std::make_unique<InkDropImpl>(&test_ink_drop_host_, gfx::Size());
       // The Timer's used by the InkDropImpl class require a
       // base::ThreadTaskRunnerHandle instance.
       scoped_refptr<base::TestMockTimeTaskRunner> task_runner(
           new base::TestMockTimeTaskRunner);
-      thread_task_runner_handle_.reset(
-          new base::ThreadTaskRunnerHandle(task_runner));
+      thread_task_runner_handle_ =
+          std::make_unique<base::ThreadTaskRunnerHandle>(task_runner);
       break;
   }
 }
diff --git a/ui/views/animation/scroll_animator.cc b/ui/views/animation/scroll_animator.cc
index 7d68999..520445e 100644
--- a/ui/views/animation/scroll_animator.cc
+++ b/ui/views/animation/scroll_animator.cc
@@ -11,7 +11,7 @@
 #include "ui/gfx/animation/slide_animation.h"
 
 namespace {
-const float kDefaultAcceleration = -1500.0f; // in pixels per second^2
+constexpr float kDefaultAcceleration = -1500.0f;  // in pixels per second^2
 
 // Assumes that d0 == 0.0f
 float GetPosition(float v0, float a, float t) {
@@ -51,7 +51,7 @@
   velocity_x_ = velocity_x;
   velocity_y_ = velocity_y;
   duration_ = -v / acceleration_; // in seconds
-  animation_.reset(new gfx::SlideAnimation(this));
+  animation_ = std::make_unique<gfx::SlideAnimation>(this);
   animation_->SetSlideDuration(static_cast<int>(duration_ * 1000));
   animation_->Show();
 }
diff --git a/ui/views/animation/square_ink_drop_ripple.cc b/ui/views/animation/square_ink_drop_ripple.cc
index b8a7929..275cc66 100644
--- a/ui/views/animation/square_ink_drop_ripple.cc
+++ b/ui/views/animation/square_ink_drop_ripple.cc
@@ -26,11 +26,11 @@
 
 // The minimum scale factor to use when scaling rectangle layers. Smaller values
 // were causing visual anomalies.
-const float kMinimumRectScale = 0.0001f;
+constexpr float kMinimumRectScale = 0.0001f;
 
 // The minimum scale factor to use when scaling circle layers. Smaller values
 // were causing visual anomalies.
-const float kMinimumCircleScale = 0.001f;
+constexpr float kMinimumCircleScale = 0.001f;
 
 // All the sub animations that are used to animate each of the InkDropStates.
 // These are used to get time durations with
@@ -108,7 +108,7 @@
 };
 
 // The scale factor used to burst the ACTION_TRIGGERED bubble as it fades out.
-const float kQuickActionBurstScale = 1.3f;
+constexpr float kQuickActionBurstScale = 1.3f;
 
 // Duration constants for InkDropStateSubAnimations. See the
 // InkDropStateSubAnimations enum documentation for more info.
diff --git a/ui/views/animation/test/test_ink_drop_host.cc b/ui/views/animation/test/test_ink_drop_host.cc
index c8ab348..3534fb24 100644
--- a/ui/views/animation/test/test_ink_drop_host.cc
+++ b/ui/views/animation/test/test_ink_drop_host.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/animation/test/test_ink_drop_host.h"
 
+#include <memory>
+
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_impl.h"
@@ -38,7 +40,7 @@
 
   test::InkDropRippleTestApi* GetTestApi() override {
     if (!test_api_)
-      test_api_.reset(new test::SquareInkDropRippleTestApi(this));
+      test_api_ = std::make_unique<test::SquareInkDropRippleTestApi>(this);
     return test_api_.get();
   }
 
@@ -62,7 +64,7 @@
 
   test::InkDropHighlightTestApi* GetTestApi() override {
     if (!test_api_)
-      test_api_.reset(new test::InkDropHighlightTestApi(this));
+      test_api_ = std::make_unique<test::InkDropHighlightTestApi>(this);
     return test_api_.get();
   }
 
@@ -106,8 +108,8 @@
 std::unique_ptr<InkDropHighlight> TestInkDropHost::CreateInkDropHighlight()
     const {
   std::unique_ptr<InkDropHighlight> highlight;
-  highlight.reset(
-      new TestInkDropHighlight(size(), 0, gfx::PointF(), SK_ColorBLACK));
+  highlight = std::make_unique<TestInkDropHighlight>(size(), 0, gfx::PointF(),
+                                                     SK_ColorBLACK);
   if (disable_timers_for_test_)
     highlight->GetTestApi()->SetDisableAnimationTimers(true);
   num_ink_drop_highlights_created_++;
diff --git a/ui/views/border_unittest.cc b/ui/views/border_unittest.cc
index eaddbf6..eb108ae 100644
--- a/ui/views/border_unittest.cc
+++ b/ui/views/border_unittest.cc
@@ -155,12 +155,12 @@
   void SetUp() override {
     ViewsTestBase::SetUp();
 
-    view_.reset(new views::View());
+    view_ = std::make_unique<views::View>();
     view_->SetSize(gfx::Size(100, 50));
-    recorder_.reset(new cc::PaintRecorder());
-    canvas_.reset(new gfx::Canvas(
+    recorder_ = std::make_unique<cc::PaintRecorder>();
+    canvas_ = std::make_unique<gfx::Canvas>(
         recorder_->beginRecording(SkRect::MakeWH(kCanvasWidth, kCanvasHeight)),
-        1.0f));
+        1.0f);
   }
 
   void TearDown() override {
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc
index d1f352f..12ca27c 100644
--- a/ui/views/bubble/bubble_border.cc
+++ b/ui/views/bubble/bubble_border.cc
@@ -56,8 +56,6 @@
 
 }  // namespace
 
-const int BubbleBorder::kStroke = 1;
-
 BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color)
     : arrow_(arrow),
       arrow_offset_(0),
diff --git a/ui/views/bubble/bubble_border.h b/ui/views/bubble/bubble_border.h
index 8f49292..9aa8468 100644
--- a/ui/views/bubble/bubble_border.h
+++ b/ui/views/bubble/bubble_border.h
@@ -133,7 +133,7 @@
     // Borders with custom shadow elevations do not draw the 1px border.
     if (!shadow_elevation.has_value()) {
       // Provide a 1 px border outside the bounds.
-      const int kBorderStrokeThicknessPx = 1;
+      constexpr int kBorderStrokeThicknessPx = 1;
       const SkScalar one_pixel =
           SkFloatToScalar(kBorderStrokeThicknessPx / canvas->image_scale());
       rect.outset(one_pixel, one_pixel);
@@ -222,7 +222,7 @@
       SkColor shadow_base_color = SK_ColorBLACK);
 
   // The border and arrow stroke size used in image assets, in pixels.
-  static const int kStroke;
+  static constexpr int kStroke = 1;
 
   gfx::Size GetSizeForContentsSize(const gfx::Size& contents_size) const;
 
diff --git a/ui/views/bubble/bubble_border_unittest.cc b/ui/views/bubble/bubble_border_unittest.cc
index 77fdae7..e53ce4d 100644
--- a/ui/views/bubble/bubble_border_unittest.cc
+++ b/ui/views/bubble/bubble_border_unittest.cc
@@ -16,7 +16,7 @@
 
 namespace views {
 
-typedef views::ViewsTestBase BubbleBorderTest;
+using BubbleBorderTest = views::ViewsTestBase;
 
 TEST_F(BubbleBorderTest, GetMirroredArrow) {
   // Horizontal mirroring.
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
index e41e684..6556a431 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -205,7 +205,7 @@
                                                          bool active) {
 #if defined(OS_MACOSX)
   // Install |mac_bubble_closer_| the first time the widget becomes active.
-  if (active && !mac_bubble_closer_ && GetWidget()) {
+  if (widget == GetWidget() && active && !mac_bubble_closer_) {
     mac_bubble_closer_ = std::make_unique<ui::BubbleCloser>(
         GetWidget()->GetNativeWindow().GetNativeNSWindow(),
         base::BindRepeating(&BubbleDialogDelegateView::OnDeactivate,
diff --git a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
index 9ccdbe1..93b5311 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -34,7 +34,7 @@
 
 class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
  public:
-  TestBubbleDialogDelegateView(View* anchor_view)
+  explicit TestBubbleDialogDelegateView(View* anchor_view)
       : BubbleDialogDelegateView(anchor_view, BubbleBorder::TOP_LEFT) {
     view_->SetFocusBehavior(FocusBehavior::ALWAYS);
     AddChildView(view_);
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index 66198f1..3770189 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -30,7 +30,7 @@
 
 namespace views {
 
-typedef ViewsTestBase BubbleFrameViewTest;
+using BubbleFrameViewTest = ViewsTestBase;
 
 namespace {
 
diff --git a/ui/views/bubble/info_bubble.cc b/ui/views/bubble/info_bubble.cc
index 99b7eea..bce2529 100644
--- a/ui/views/bubble/info_bubble.cc
+++ b/ui/views/bubble/info_bubble.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/bubble/info_bubble.h"
 
+#include <memory>
+
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -19,7 +21,7 @@
 namespace {
 
 // The visible width of bubble borders (differs from the actual width) in px.
-const int kBubbleBorderVisibleWidth = 1;
+constexpr int kBubbleBorderVisibleWidth = 1;
 
 }  // namespace
 
@@ -78,8 +80,8 @@
   DCHECK(!frame_);
   frame_ = new InfoBubbleFrame(margins());
   frame_->set_available_bounds(anchor_widget()->GetWindowBoundsInScreen());
-  frame_->SetBubbleBorder(std::unique_ptr<BubbleBorder>(
-      new BubbleBorder(arrow(), GetShadow(), color())));
+  frame_->SetBubbleBorder(
+      std::make_unique<BubbleBorder>(arrow(), GetShadow(), color()));
   return frame_;
 }
 
diff --git a/ui/views/button_drag_utils.cc b/ui/views/button_drag_utils.cc
index 56b8813..c35cc1e4 100644
--- a/ui/views/button_drag_utils.cc
+++ b/ui/views/button_drag_utils.cc
@@ -25,7 +25,7 @@
 namespace button_drag_utils {
 
 // Maximum width of the link drag image in pixels.
-static const int kLinkDragImageMaxWidth = 150;
+static constexpr int kLinkDragImageMaxWidth = 150;
 
 void SetURLAndDragImage(const GURL& url,
                         const base::string16& title,
diff --git a/ui/views/color_chooser/color_chooser_view.cc b/ui/views/color_chooser/color_chooser_view.cc
index 77d9943e..c7d8ad3 100644
--- a/ui/views/color_chooser/color_chooser_view.cc
+++ b/ui/views/color_chooser/color_chooser_view.cc
@@ -32,13 +32,13 @@
 
 namespace {
 
-const int kHueBarWidth = 20;
-const int kSaturationValueSize = 200;
-const int kMarginWidth = 5;
-const int kSaturationValueIndicatorSize = 6;
-const int kHueIndicatorSize = 5;
-const int kBorderWidth = 1;
-const int kTextfieldLengthInChars = 14;
+constexpr int kHueBarWidth = 20;
+constexpr int kSaturationValueSize = 200;
+constexpr int kMarginWidth = 5;
+constexpr int kSaturationValueIndicatorSize = 6;
+constexpr int kHueIndicatorSize = 5;
+constexpr int kBorderWidth = 1;
+constexpr int kTextfieldLengthInChars = 14;
 
 base::string16 GetColorText(SkColor color) {
   return base::ASCIIToUTF16(base::StringPrintf("#%02x%02x%02x",
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index a2f2003..b10e848 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -38,7 +38,7 @@
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsButtonProperty, false)
 
 // How long the hover animation takes if uninterrupted.
-const int kHoverFadeDurationMs = 150;
+constexpr int kHoverFadeDurationMs = 150;
 
 }  // namespace
 
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h
index 2d2bed52..12ef946 100644
--- a/ui/views/controls/button/button.h
+++ b/ui/views/controls/button/button.h
@@ -273,7 +273,7 @@
   // well.
   class WidgetObserverButtonBridge : public WidgetObserver {
    public:
-    WidgetObserverButtonBridge(Button* owner);
+    explicit WidgetObserverButtonBridge(Button* owner);
     ~WidgetObserverButtonBridge() override;
 
     // WidgetObserver:
diff --git a/ui/views/controls/button/button_unittest.cc b/ui/views/controls/button/button_unittest.cc
index ade7521..818d972 100644
--- a/ui/views/controls/button/button_unittest.cc
+++ b/ui/views/controls/button/button_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/button/button.h"
 
+#include <memory>
+
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
@@ -130,7 +132,7 @@
 
     // Create a widget so that the Button can query the hover state
     // correctly.
-    widget_.reset(new Widget);
+    widget_ = std::make_unique<Widget>();
     Widget::InitParams params =
         CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index c20d3cc..80bd0e2 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -20,8 +20,8 @@
 // Default button size if no image is set. This is ignored if there is an image,
 // and exists for historical reasons (any number of clients could depend on this
 // behaviour).
-static const int kDefaultWidth = 16;
-static const int kDefaultHeight = 14;
+static constexpr int kDefaultWidth = 16;
+static constexpr int kDefaultHeight = 14;
 
 const char ImageButton::kViewClassName[] = "ImageButton";
 
diff --git a/ui/views/controls/button/image_button_factory_unittest.cc b/ui/views/controls/button/image_button_factory_unittest.cc
index 1a5f238c..5a610414 100644
--- a/ui/views/controls/button/image_button_factory_unittest.cc
+++ b/ui/views/controls/button/image_button_factory_unittest.cc
@@ -15,7 +15,7 @@
 
 namespace views {
 
-typedef ViewsTestBase ImageButtonFactoryTest;
+using ImageButtonFactoryTest = ViewsTestBase;
 
 TEST_F(ImageButtonFactoryTest, CreateVectorImageButton) {
   ImageButton* button = CreateVectorImageButton(nullptr);
diff --git a/ui/views/controls/button/image_button_unittest.cc b/ui/views/controls/button/image_button_unittest.cc
index dd25526..129955b 100644
--- a/ui/views/controls/button/image_button_unittest.cc
+++ b/ui/views/controls/button/image_button_unittest.cc
@@ -46,7 +46,7 @@
     ImageButton::ALIGN_TOP;
 }  // namespace
 
-typedef ViewsTestBase ImageButtonTest;
+using ImageButtonTest = ViewsTestBase;
 
 TEST_F(ImageButtonTest, Basics) {
   ImageButton button(nullptr);
diff --git a/ui/views/controls/button/label_button_border.cc b/ui/views/controls/button/label_button_border.cc
index ebcba27..72596230 100644
--- a/ui/views/controls/button/label_button_border.cc
+++ b/ui/views/controls/button/label_button_border.cc
@@ -25,11 +25,11 @@
 
 // Insets for the unified button images. This assumes that the images
 // are of a 9 grid, of 5x5 size each.
-const int kButtonInsets = 5;
+constexpr int kButtonInsets = 5;
 
 // The text-button hot and pushed image IDs; normal is unadorned by default.
-const int kTextHoveredImages[] = IMAGE_GRID(IDR_TEXTBUTTON_HOVER);
-const int kTextPressedImages[] = IMAGE_GRID(IDR_TEXTBUTTON_PRESSED);
+constexpr int kTextHoveredImages[] = IMAGE_GRID(IDR_TEXTBUTTON_HOVER);
+constexpr int kTextPressedImages[] = IMAGE_GRID(IDR_TEXTBUTTON_PRESSED);
 
 // A helper function to paint the appropriate broder images.
 void PaintHelper(LabelButtonAssetBorder* border,
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc
index 1e70e551..375c6a5 100644
--- a/ui/views/controls/button/label_button_unittest.cc
+++ b/ui/views/controls/button/label_button_unittest.cc
@@ -570,7 +570,7 @@
 
     // Create a widget so that the Button can query the hover state
     // correctly.
-    widget_.reset(new Widget);
+    widget_ = std::make_unique<Widget>();
     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     params.bounds = gfx::Rect(0, 0, 20, 20);
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc
index 5a0b566..d8cf558 100644
--- a/ui/views/controls/button/md_text_button.cc
+++ b/ui/views/controls/button/md_text_button.cc
@@ -118,8 +118,8 @@
     const {
   bool is_dark_mode = GetNativeTheme()->SystemDarkModeEnabled();
   // The prominent button hover effect is a shadow.
-  const int kYOffset = 1;
-  const int kSkiaBlurRadius = 2;
+  constexpr int kYOffset = 1;
+  constexpr int kSkiaBlurRadius = 2;
   const int shadow_alpha = is_prominent_ ? 0x3D : 0x1A;
   const SkColor shadow_color =
       is_dark_mode && is_prominent_ ? gfx::kGoogleBlue300 : SK_ColorBLACK;
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc
index c58a17d..3d2a5ae 100644
--- a/ui/views/controls/button/menu_button.cc
+++ b/ui/views/controls/button/menu_button.cc
@@ -14,8 +14,8 @@
 namespace views {
 // static
 const char MenuButton::kViewClassName[] = "MenuButton";
-const int MenuButton::kMenuMarkerPaddingLeft = 3;
-const int MenuButton::kMenuMarkerPaddingRight = -1;
+constexpr int MenuButton::kMenuMarkerPaddingLeft = 3;
+constexpr int MenuButton::kMenuMarkerPaddingRight = -1;
 
 MenuButton::MenuButton(const base::string16& text,
                        MenuButtonListener* menu_button_listener,
diff --git a/ui/views/controls/button/toggle_button_unittest.cc b/ui/views/controls/button/toggle_button_unittest.cc
index e43c60b7..eed10160 100644
--- a/ui/views/controls/button/toggle_button_unittest.cc
+++ b/ui/views/controls/button/toggle_button_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/button/toggle_button.h"
 
+#include <memory>
+
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -55,7 +57,7 @@
 
     // Create a widget so that the ToggleButton can query the hover state
     // correctly.
-    widget_.reset(new Widget);
+    widget_ = std::make_unique<Widget>();
     Widget::InitParams params =
         CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 011f652..9fc8f31 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/combobox/combobox.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/logging.h"
 #include "build/build_config.h"
@@ -626,10 +628,10 @@
   // Allow |menu_runner_| to be set by the testing API, but if this method is
   // ever invoked recursively, ensure the old menu is closed.
   if (!menu_runner_ || menu_runner_->IsRunning()) {
-    menu_runner_.reset(new MenuRunner(
+    menu_runner_ = std::make_unique<MenuRunner>(
         menu_model_.get(), MenuRunner::COMBOBOX,
         base::BindRepeating(&Combobox::OnMenuClosed, base::Unretained(this),
-                            original_state)));
+                            original_state));
   }
   menu_runner_->RunMenuAt(GetWidget(), nullptr, bounds, MENU_ANCHOR_TOPLEFT,
                           source_type);
@@ -673,7 +675,7 @@
 
 PrefixSelector* Combobox::GetPrefixSelector() {
   if (!selector_)
-    selector_.reset(new PrefixSelector(this, this));
+    selector_ = std::make_unique<PrefixSelector>(this, this);
   return selector_.get();
 }
 
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h
index ec4fb68..df7998c 100644
--- a/ui/views/controls/combobox/combobox.h
+++ b/ui/views/controls/combobox/combobox.h
@@ -39,8 +39,8 @@
  public:
   // The combobox's class name.
   static const char kViewClassName[];
-  static const int kDefaultComboboxTextContext = style::CONTEXT_BUTTON;
-  static const int kDefaultComboboxTextStyle = style::STYLE_PRIMARY;
+  static constexpr int kDefaultComboboxTextContext = style::CONTEXT_BUTTON;
+  static constexpr int kDefaultComboboxTextStyle = style::STYLE_PRIMARY;
 
   // |model| is owned by the combobox when using this constructor.
   explicit Combobox(std::unique_ptr<ui::ComboboxModel> model,
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc
index 0748eaa..843ecf5 100644
--- a/ui/views/controls/combobox/combobox_unittest.cc
+++ b/ui/views/controls/combobox/combobox_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ui/views/controls/combobox/combobox.h"
 
+#include <memory>
 #include <set>
 
 #include "base/macros.h"
@@ -122,7 +123,9 @@
   void set_default_index(int default_index) { default_index_ = default_index; }
 
   // ui::ComboboxModel:
-  int GetItemCount() const override { return (int)values_->size(); }
+  int GetItemCount() const override {
+    return static_cast<int>(values_->size());
+  }
   base::string16 GetItemAt(int index) override {
     return ASCIIToUTF16(values_->at(index));
   }
@@ -198,14 +201,14 @@
   }
 
   void InitCombobox(const std::set<int>* separators) {
-    model_.reset(new TestComboboxModel());
+    model_ = std::make_unique<TestComboboxModel>();
 
     if (separators)
       model_->SetSeparators(*separators);
 
     ASSERT_FALSE(combobox_);
     combobox_ = new TestCombobox(model_.get());
-    test_api_.reset(new ComboboxTestApi(combobox_));
+    test_api_ = std::make_unique<ComboboxTestApi>(combobox_);
     test_api_->InstallTestMenuRunner(&menu_show_count_);
     combobox_->set_id(1);
 
@@ -329,7 +332,7 @@
 // Check that if a combobox is disabled before it has a native wrapper, then the
 // native wrapper inherits the disabled state when it gets created.
 TEST_F(ComboboxTest, DisabilityTest) {
-  model_.reset(new TestComboboxModel());
+  model_ = std::make_unique<TestComboboxModel>();
 
   ASSERT_FALSE(combobox_);
   combobox_ = new TestCombobox(model_.get());
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h
index df43c345..9fba33c 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -39,8 +39,8 @@
  public:
   // The class name.
   static const char kViewClassName[];
-  static const int kDefaultTextContext = style::CONTEXT_BUTTON;
-  static const int kDefaultTextStyle = style::STYLE_PRIMARY;
+  static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON;
+  static constexpr int kDefaultTextStyle = style::STYLE_PRIMARY;
 
   // |combobox_model|: The ComboboxModel that gives us the items to show in the
   // menu.
diff --git a/ui/views/controls/focusable_border.cc b/ui/views/controls/focusable_border.cc
index 63e5b87..b572dd4 100644
--- a/ui/views/controls/focusable_border.cc
+++ b/ui/views/controls/focusable_border.cc
@@ -18,7 +18,7 @@
 
 namespace {
 
-const int kInsetSize = 1;
+constexpr int kInsetSize = 1;
 
 }  // namespace
 
@@ -41,12 +41,12 @@
   gfx::ScopedCanvas scoped(canvas);
   float dsf = canvas->UndoDeviceScaleFactor();
 
-  const int stroke_width_px = 1;
-  flags.setStrokeWidth(SkIntToScalar(stroke_width_px));
+  constexpr int kStrokeWidthPx = 1;
+  flags.setStrokeWidth(SkIntToScalar(kStrokeWidthPx));
 
   // Scale the rect and snap to pixel boundaries.
   gfx::RectF rect(gfx::ScaleToEnclosedRect(view.GetLocalBounds(), dsf));
-  rect.Inset(gfx::InsetsF(stroke_width_px / 2.0f));
+  rect.Inset(gfx::InsetsF(kStrokeWidthPx / 2.0f));
 
   SkPath path;
     flags.setAntiAlias(true);
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index c0fca3c..e814f741 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -52,9 +52,12 @@
 Label::Label(const base::string16& text)
     : Label(text, style::CONTEXT_LABEL, style::STYLE_PRIMARY) {}
 
-Label::Label(const base::string16& text, int text_context, int text_style)
+Label::Label(const base::string16& text,
+             int text_context,
+             int text_style,
+             gfx::DirectionalityMode directionality_mode)
     : text_context_(text_context), context_menu_contents_(this) {
-  Init(text, style::GetFont(text_context, text_style));
+  Init(text, style::GetFont(text_context, text_style), directionality_mode);
   SetLineHeight(style::GetLineHeight(text_context, text_style));
 
   // If an explicit style is given, ignore color changes due to the NativeTheme.
@@ -64,7 +67,7 @@
 
 Label::Label(const base::string16& text, const CustomFont& font)
     : text_context_(style::CONTEXT_LABEL), context_menu_contents_(this) {
-  Init(text, font.font_list);
+  Init(text, font.font_list, gfx::DirectionalityMode::DIRECTIONALITY_FROM_TEXT);
 }
 
 Label::~Label() = default;
@@ -644,9 +647,9 @@
   if (!GetRenderTextForSelectionController())
     return;
 
-  context_menu_runner_.reset(
-      new MenuRunner(&context_menu_contents_,
-                     MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU));
+  context_menu_runner_ = std::make_unique<MenuRunner>(
+      &context_menu_contents_,
+      MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU);
   context_menu_runner_->RunMenuAt(GetWidget(), nullptr,
                                   gfx::Rect(point, gfx::Size()),
                                   MENU_ANCHOR_TOPLEFT, source_type);
@@ -784,11 +787,13 @@
   return display_text_.get();
 }
 
-void Label::Init(const base::string16& text, const gfx::FontList& font_list) {
+void Label::Init(const base::string16& text,
+                 const gfx::FontList& font_list,
+                 gfx::DirectionalityMode directionality_mode) {
   full_text_ = gfx::RenderText::CreateHarfBuzzInstance();
   DCHECK(full_text_->MultilineSupported());
   full_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-  full_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT);
+  full_text_->SetDirectionalityMode(directionality_mode);
   // NOTE: |full_text_| should not be elided at all. This is used to keep
   // some properties and to compute the size of the string.
   full_text_->SetElideBehavior(gfx::NO_ELIDE);
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h
index 6f01e96..44c0a27f 100644
--- a/ui/views/controls/label.h
+++ b/ui/views/controls/label.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/gfx/render_text.h"
+#include "ui/gfx/text_constants.h"
 #include "ui/views/context_menu_controller.h"
 #include "ui/views/selection_controller_delegate.h"
 #include "ui/views/style/typography.h"
@@ -54,9 +55,13 @@
 
   // Construct a Label in the given |text_context|. The |text_style| can change
   // later, so provide a default. The |text_context| is fixed.
+  // By default text directionality will be derived from the label text, however
+  // it can be overriden with |directionality_mode|.
   Label(const base::string16& text,
         int text_context,
-        int text_style = style::STYLE_PRIMARY);
+        int text_style = style::STYLE_PRIMARY,
+        gfx::DirectionalityMode directionality_mode =
+            gfx::DirectionalityMode::DIRECTIONALITY_FROM_TEXT);
 
   // Construct a Label with the given |font| description.
   Label(const base::string16& text, const CustomFont& font);
@@ -301,7 +306,9 @@
 
   const gfx::RenderText* GetRenderTextForSelectionController() const;
 
-  void Init(const base::string16& text, const gfx::FontList& font_list);
+  void Init(const base::string16& text,
+            const gfx::FontList& font_list,
+            gfx::DirectionalityMode directionality_mode);
 
   void ResetLayout();
 
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 86b4360d..b537932 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -75,23 +75,23 @@
 int menu_selection_hold_time_ms = kMinimumMsPressedToActivate;
 
 // Period of the scroll timer (in milliseconds).
-const int kScrollTimerMS = 30;
+constexpr int kScrollTimerMS = 30;
 
 // Amount of time from when the drop exits the menu and the menu is hidden.
-const int kCloseOnExitTime = 1200;
+constexpr int kCloseOnExitTime = 1200;
 
 // If a context menu is invoked by touch, we shift the menu by this offset so
 // that the finger does not obscure the menu.
-const int kTouchYPadding = 15;
+constexpr int kTouchYPadding = 15;
 
 // The spacing offset for the bubble tip.
-const int kBubbleTipSizeLeftRight = 12;
-const int kBubbleTipSizeTopBottom = 11;
+constexpr int kBubbleTipSizeLeftRight = 12;
+constexpr int kBubbleTipSizeTopBottom = 11;
 
 // The maximum distance (in DIPS) that the mouse can be moved before it should
 // trigger a mouse menu item activation (regardless of how long the menu has
 // been showing).
-const float kMaximumLengthMovedToActivate = 4.0f;
+constexpr float kMaximumLengthMovedToActivate = 4.0f;
 
 // Time to complete a cycle of the menu item alert animation.
 constexpr base::TimeDelta kAlertAnimationThrobDuration =
@@ -2827,7 +2827,7 @@
     return;
 
   if (!scroll_task_.get())
-    scroll_task_.reset(new MenuScrollTask());
+    scroll_task_ = std::make_unique<MenuScrollTask>();
   scroll_task_->Update(part);
 }
 
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 157a2e5..4d39e49 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -736,8 +736,8 @@
   }
 
   void SetupMenuItem() {
-    menu_delegate_.reset(new TestMenuDelegate);
-    menu_item_.reset(new TestMenuItemViewShown(menu_delegate_.get()));
+    menu_delegate_ = std::make_unique<TestMenuDelegate>();
+    menu_item_ = std::make_unique<TestMenuItemViewShown>(menu_delegate_.get());
     menu_item_->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
     menu_item_->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
     menu_item_->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three"));
@@ -745,7 +745,7 @@
   }
 
   void SetupMenuController() {
-    menu_controller_delegate_.reset(new TestMenuControllerDelegate);
+    menu_controller_delegate_ = std::make_unique<TestMenuControllerDelegate>();
     const bool for_drop = false;
     menu_controller_ =
         new MenuController(for_drop, menu_controller_delegate_.get());
diff --git a/ui/views/controls/menu/menu_host.cc b/ui/views/controls/menu/menu_host.cc
index 91b584b0..7e686b13 100644
--- a/ui/views/controls/menu/menu_host.cc
+++ b/ui/views/controls/menu/menu_host.cc
@@ -139,8 +139,9 @@
   Init(params);
 
 #if !defined(OS_MACOSX)
-  pre_dispatch_handler_.reset(new internal::PreMenuEventDispatchHandler(
-      menu_controller, submenu_, GetNativeView()));
+  pre_dispatch_handler_ =
+      std::make_unique<internal::PreMenuEventDispatchHandler>(
+          menu_controller, submenu_, GetNativeView());
 #endif
 
   DCHECK(!owner_);
diff --git a/ui/views/controls/menu/menu_image_util.h b/ui/views/controls/menu/menu_image_util.h
index 5097c48..bda8226 100644
--- a/ui/views/controls/menu/menu_image_util.h
+++ b/ui/views/controls/menu/menu_image_util.h
@@ -11,8 +11,8 @@
 namespace views {
 
 // The width/height of the check and submenu arrows.
-const int kMenuCheckSize = 16;
-const int kSubmenuArrowSize = 8;
+constexpr int kMenuCheckSize = 16;
+constexpr int kSubmenuArrowSize = 8;
 
 // Returns the Menu Check box image (always checked).
 gfx::ImageSkia GetMenuCheckImage(SkColor icon_color);
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 46d2e3be..74d5bca 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -71,7 +71,7 @@
 }  // namespace
 
 // Padding between child views.
-static const int kChildXPadding = 8;
+static constexpr int kChildXPadding = 8;
 
 // MenuItemView ---------------------------------------------------------------
 
diff --git a/ui/views/controls/menu/menu_item_view_unittest.cc b/ui/views/controls/menu/menu_item_view_unittest.cc
index 3001243..792f2bd 100644
--- a/ui/views/controls/menu/menu_item_view_unittest.cc
+++ b/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -274,16 +274,16 @@
   // ViewsTestBase implementation.
   void SetUp() override {
     ViewsTestBase::SetUp();
-    menu_delegate_.reset(new test::TestMenuDelegate);
+    menu_delegate_ = std::make_unique<test::TestMenuDelegate>();
     menu_item_view_ = new MenuItemView(menu_delegate_.get());
 
-    widget_.reset(new Widget);
+    widget_ = std::make_unique<Widget>();
     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     widget_->Init(params);
     widget_->Show();
 
-    menu_runner_.reset(new MenuRunner(menu_item_view_, 0));
+    menu_runner_ = std::make_unique<MenuRunner>(menu_item_view_, 0);
   }
 
   void TearDown() override {
diff --git a/ui/views/controls/menu/menu_model_adapter_unittest.cc b/ui/views/controls/menu/menu_model_adapter_unittest.cc
index b0eaf9e..8ebf856 100644
--- a/ui/views/controls/menu/menu_model_adapter_unittest.cc
+++ b/ui/views/controls/menu/menu_model_adapter_unittest.cc
@@ -258,7 +258,7 @@
 
 namespace views {
 
-typedef ViewsTestBase MenuModelAdapterTest;
+using MenuModelAdapterTest = ViewsTestBase;
 
 TEST_F(MenuModelAdapterTest, BasicTest) {
   // Build model and adapter.
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc
index cc3ff7d..8edb223 100644
--- a/ui/views/controls/menu/menu_runner_impl.cc
+++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/menu/menu_runner_impl.h"
 
+#include <memory>
+
 #include "build/build_config.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/controls/button/menu_button.h"
@@ -60,7 +62,7 @@
     // Swap in a different delegate. That way we know the original MenuDelegate
     // won't be notified later on (when it's likely already been deleted).
     if (!empty_delegate_.get())
-      empty_delegate_.reset(new MenuDelegate());
+      empty_delegate_ = std::make_unique<MenuDelegate>();
     menu_->set_delegate(empty_delegate_.get());
 
     // Verify that the MenuController is still active. It may have been
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
index 4886786..8743751 100644
--- a/ui/views/controls/menu/menu_runner_impl_cocoa.mm
+++ b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -20,8 +20,8 @@
 namespace internal {
 namespace {
 
-const CGFloat kNativeCheckmarkWidth = 18;
-const CGFloat kNativeMenuItemHeight = 18;
+constexpr CGFloat kNativeCheckmarkWidth = 18;
+constexpr CGFloat kNativeMenuItemHeight = 18;
 
 // Returns the first item in |menu_controller|'s menu that will be checked.
 NSMenuItem* FirstCheckedItem(MenuControllerCocoa* menu_controller) {
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc
index 54dfbd4..2e5b731 100644
--- a/ui/views/controls/message_box_view.cc
+++ b/ui/views/controls/message_box_view.cc
@@ -29,7 +29,7 @@
 
 namespace {
 
-const int kDefaultMessageWidth = 400;
+constexpr int kDefaultMessageWidth = 400;
 
 // Paragraph separators are defined in
 // http://www.unicode.org/Public/6.0.0/ucd/extracted/DerivedBidiClass.txt
diff --git a/ui/views/controls/native/native_view_host_aura.cc b/ui/views/controls/native/native_view_host_aura.cc
index 42a69ff..9dd0bab 100644
--- a/ui/views/controls/native/native_view_host_aura.cc
+++ b/ui/views/controls/native/native_view_host_aura.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/native/native_view_host_aura.h"
 
+#include <memory>
+
 #include "base/logging.h"
 #include "base/optional.h"
 #include "build/build_config.h"
@@ -182,8 +184,8 @@
 }
 
 void NativeViewHostAura::InstallClip(int x, int y, int w, int h) {
-  clip_rect_.reset(
-      new gfx::Rect(host_->ConvertRectToWidget(gfx::Rect(x, y, w, h))));
+  clip_rect_ = std::make_unique<gfx::Rect>(
+      host_->ConvertRectToWidget(gfx::Rect(x, y, w, h)));
 }
 
 int NativeViewHostAura::GetHitTestTopInset() const {
diff --git a/ui/views/controls/native/native_view_host_aura_unittest.cc b/ui/views/controls/native/native_view_host_aura_unittest.cc
index d8a2bad5..2587ff5 100644
--- a/ui/views/controls/native/native_view_host_aura_unittest.cc
+++ b/ui/views/controls/native/native_view_host_aura_unittest.cc
@@ -442,7 +442,7 @@
 
 class TestFocusChangeListener : public FocusChangeListener {
  public:
-  TestFocusChangeListener(FocusManager* focus_manager)
+  explicit TestFocusChangeListener(FocusManager* focus_manager)
       : focus_manager_(focus_manager) {
     focus_manager_->AddFocusChangeListener(this);
   }
diff --git a/ui/views/controls/native/native_view_host_test_base.cc b/ui/views/controls/native/native_view_host_test_base.cc
index 694a693..013bbea 100644
--- a/ui/views/controls/native/native_view_host_test_base.cc
+++ b/ui/views/controls/native/native_view_host_test_base.cc
@@ -35,7 +35,7 @@
 }
 
 void NativeViewHostTestBase::CreateTopLevel() {
-  toplevel_.reset(new Widget);
+  toplevel_ = std::make_unique<Widget>();
   Widget::InitParams toplevel_params =
       CreateParams(Widget::InitParams::TYPE_WINDOW);
   toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
@@ -43,7 +43,7 @@
 }
 
 void NativeViewHostTestBase::CreateTestingHost() {
-  host_.reset(new NativeViewHostTesting(this));
+  host_ = std::make_unique<NativeViewHostTesting>(this);
 }
 
 Widget* NativeViewHostTestBase::CreateChildForHost(
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc
index 44191bfd..f0cde332 100644
--- a/ui/views/controls/prefix_selector.cc
+++ b/ui/views/controls/prefix_selector.cc
@@ -22,7 +22,7 @@
 
 namespace {
 
-const int64_t kTimeBeforeClearingMS = 1000;
+constexpr int64_t kTimeBeforeClearingMS = 1000;
 
 }  // namespace
 
diff --git a/ui/views/controls/prefix_selector_unittest.cc b/ui/views/controls/prefix_selector_unittest.cc
index 010af5b7..42b39971c4 100644
--- a/ui/views/controls/prefix_selector_unittest.cc
+++ b/ui/views/controls/prefix_selector_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ui/views/controls/prefix_selector.h"
 
+#include <memory>
 #include <string>
 
 #include "base/macros.h"
@@ -45,7 +46,7 @@
 class PrefixSelectorTest : public ViewsTestBase {
  public:
   PrefixSelectorTest() {
-    selector_.reset(new PrefixSelector(&delegate_, &delegate_));
+    selector_ = std::make_unique<PrefixSelector>(&delegate_, &delegate_);
   }
   ~PrefixSelectorTest() override {
     // Explicitly release |selector_| here which can happen before releasing
diff --git a/ui/views/controls/progress_bar.cc b/ui/views/controls/progress_bar.cc
index f8da9e8..deb1d931 100644
--- a/ui/views/controls/progress_bar.cc
+++ b/ui/views/controls/progress_bar.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <cmath>
+#include <memory>
 #include <string>
 
 #include "base/logging.h"
@@ -25,7 +26,7 @@
 
 // In DP, the amount to round the corners of the progress bar (both bg and
 // fg, aka slice).
-const int kCornerRadius = 3;
+constexpr int kCornerRadius = 3;
 
 // Adds a rectangle to the path. The corners will be rounded if there is room.
 void AddPossiblyRoundRectToPath(const gfx::Rect& rectangle,
@@ -110,7 +111,7 @@
 
   current_value_ = adjusted_value;
   if (IsIndeterminate()) {
-    indeterminate_bar_animation_.reset(new gfx::LinearAnimation(this));
+    indeterminate_bar_animation_ = std::make_unique<gfx::LinearAnimation>(this);
     indeterminate_bar_animation_->SetDuration(base::TimeDelta::FromSeconds(2));
     indeterminate_bar_animation_->Start();
   } else {
diff --git a/ui/views/controls/resize_area_unittest.cc b/ui/views/controls/resize_area_unittest.cc
index 3194521..0a3bbcbe 100644
--- a/ui/views/controls/resize_area_unittest.cc
+++ b/ui/views/controls/resize_area_unittest.cc
@@ -118,7 +118,7 @@
 void ResizeAreaTest::SetUp() {
   views::ViewsTestBase::SetUp();
 
-  delegate_.reset(new TestResizeAreaDelegate);
+  delegate_ = std::make_unique<TestResizeAreaDelegate>();
   resize_area_ = new ResizeArea(delegate_.get());
 
   gfx::Size size(10, 10);
diff --git a/ui/views/controls/scrollbar/base_scroll_bar.cc b/ui/views/controls/scrollbar/base_scroll_bar.cc
index f5cbb69..c33458c 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar.cc
+++ b/ui/views/controls/scrollbar/base_scroll_bar.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/scrollbar/base_scroll_bar.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
@@ -229,7 +231,7 @@
 
   if (event->type() == ui::ET_SCROLL_FLING_START) {
     if (!scroll_animator_.get())
-      scroll_animator_.reset(new ScrollAnimator(this));
+      scroll_animator_ = std::make_unique<ScrollAnimator>(this);
     scroll_animator_->Start(
         IsHorizontal() ?  event->details().velocity_x() : 0.f,
         IsHorizontal() ? 0.f : event->details().velocity_y());
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc b/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
index a8a264f..aec1188 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
+++ b/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
@@ -11,7 +11,7 @@
 namespace {
 // The distance the mouse can be dragged outside the bounds of the thumb during
 // dragging before the scrollbar will snap back to its regular position.
-static const int kScrollThumbDragOutSnap = 100;
+static constexpr int kScrollThumbDragOutSnap = 100;
 }
 
 namespace views {
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index a764fba..e9642e77 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -21,38 +21,40 @@
 namespace {
 
 // The length of the fade animation.
-const int kFadeDurationMs = 240;
+constexpr int kFadeDurationMs = 240;
 
 // The length of the expand animation.
-const int kExpandDurationMs = 240;
+constexpr int kExpandDurationMs = 240;
 
 // How long we should wait before hiding the scrollbar.
-const int kScrollbarHideTimeoutMs = 500;
+constexpr int kScrollbarHideTimeoutMs = 500;
 
 // The thickness of the normal and expanded scrollbars.
-const int kScrollbarThickness = 12;
-const int kExpandedScrollbarThickness = 16;
+constexpr int kScrollbarThickness = 12;
+constexpr int kExpandedScrollbarThickness = 16;
 
 // The width of the scroller track border.
-const int kScrollerTrackBorderWidth = 1;
+constexpr int kScrollerTrackBorderWidth = 1;
 
 // The amount the thumb is inset from the ends and the inside edge of track
 // border.
-const int kScrollbarThumbInset = 2;
+constexpr int kScrollbarThumbInset = 2;
 
 // Scrollbar thumb colors.
-const SkColor kScrollerDefaultThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
-const SkColor kScrollerHoverThumbColor = SkColorSetARGB(0x80, 0, 0, 0);
+constexpr SkColor kScrollerDefaultThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
+constexpr SkColor kScrollerHoverThumbColor = SkColorSetARGB(0x80, 0, 0, 0);
 
 // Opacity of the overlay scrollbar.
-const float kOverlayOpacity = 0.8f;
+constexpr float kOverlayOpacity = 0.8f;
 
 // Scroller track colors.
-const SkColor kScrollerTrackGradientColors[] = {
+constexpr SkColor kScrollerTrackGradientColors[] = {
     SkColorSetRGB(0xEF, 0xEF, 0xEF), SkColorSetRGB(0xF9, 0xF9, 0xF9),
     SkColorSetRGB(0xFD, 0xFD, 0xFD), SkColorSetRGB(0xF6, 0xF6, 0xF6)};
-const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
-const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
+constexpr SkColor kScrollerTrackInnerBorderColor =
+    SkColorSetRGB(0xE4, 0xE4, 0xE4);
+constexpr SkColor kScrollerTrackOuterBorderColor =
+    SkColorSetRGB(0xEF, 0xEF, 0xEF);
 
 }  // namespace
 
diff --git a/ui/views/controls/scrollbar/scrollbar_unittest.cc b/ui/views/controls/scrollbar/scrollbar_unittest.cc
index c2974d7..0cf2dd75 100644
--- a/ui/views/controls/scrollbar/scrollbar_unittest.cc
+++ b/ui/views/controls/scrollbar/scrollbar_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
+
 #include "build/build_config.h"
 #include "ui/views/controls/scrollbar/scroll_bar.h"
 #include "ui/views/controls/scrollbar/scroll_bar_views.h"
@@ -51,7 +53,7 @@
 
   void SetUp() override {
     ViewsTestBase::SetUp();
-    controller_.reset(new TestScrollBarController());
+    controller_ = std::make_unique<TestScrollBarController>();
 
     widget_ = new Widget;
     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc
index 04df7096..eba7f1a 100644
--- a/ui/views/controls/slider.cc
+++ b/ui/views/controls/slider.cc
@@ -5,6 +5,7 @@
 #include "ui/views/controls/slider.h"
 
 #include <algorithm>
+#include <memory>
 
 #include "base/logging.h"
 #include "base/message_loop/message_loop_current.h"
@@ -24,7 +25,7 @@
 #include "ui/views/widget/widget.h"
 
 namespace {
-const int kSlideValueChangeDurationMs = 150;
+constexpr int kSlideValueChangeDurationMs = 150;
 
 // The image chunks.
 enum BorderElements {
@@ -40,8 +41,8 @@
 namespace {
 
 // Color of slider at the active and the disabled state, respectively.
-const SkColor kActiveColor = SkColorSetARGB(0xFF, 0x42, 0x85, 0xF4);
-const SkColor kDisabledColor = SkColorSetARGB(0xFF, 0xBD, 0xBD, 0xBD);
+constexpr SkColor kActiveColor = SkColorSetARGB(0xFF, 0x42, 0x85, 0xF4);
+constexpr SkColor kDisabledColor = SkColorSetARGB(0xFF, 0xBD, 0xBD, 0xBD);
 constexpr uint8_t kHighlightColorAlpha = 0x4D;
 
 // The thickness of the slider.
@@ -144,7 +145,7 @@
     // There is no message-loop when running tests. So we cannot animate then.
     if (!move_animation_) {
       initial_animating_value_ = old_value;
-      move_animation_.reset(new gfx::SlideAnimation(this));
+      move_animation_ = std::make_unique<gfx::SlideAnimation>(this);
       move_animation_->SetSlideDuration(kSlideValueChangeDurationMs);
       move_animation_->Show();
     }
@@ -206,8 +207,8 @@
 }
 
 gfx::Size Slider::CalculatePreferredSize() const {
-  const int kSizeMajor = 200;
-  const int kSizeMinor = 40;
+  constexpr int kSizeMajor = 200;
+  constexpr int kSizeMinor = 40;
 
   return gfx::Size(std::max(width(), kSizeMajor), kSizeMinor);
 }
@@ -272,17 +273,17 @@
       is_active_ ? kActiveColor : kDisabledColor;
 
   // Extra space used to hide slider ends behind the thumb.
-  const int extra_padding = 1;
+  constexpr int kExtraPadding = 1;
 
   cc::PaintFlags slider_flags;
   slider_flags.setAntiAlias(true);
   slider_flags.setColor(current_thumb_color);
   canvas->DrawRoundRect(
-      gfx::Rect(content.x(), y, full + extra_padding, kLineThickness),
+      gfx::Rect(content.x(), y, full + kExtraPadding, kLineThickness),
       kSliderRoundedRadius, slider_flags);
   slider_flags.setColor(kDisabledColor);
-  canvas->DrawRoundRect(gfx::Rect(x + kThumbRadius - extra_padding, y,
-                                  empty + extra_padding, kLineThickness),
+  canvas->DrawRoundRect(gfx::Rect(x + kThumbRadius - kExtraPadding, y,
+                                  empty + kExtraPadding, kLineThickness),
                         kSliderRoundedRadius, slider_flags);
 
   gfx::Point thumb_center(x, content.height() / 2);
diff --git a/ui/views/controls/slider.h b/ui/views/controls/slider.h
index 034b9bba..64869aa 100644
--- a/ui/views/controls/slider.h
+++ b/ui/views/controls/slider.h
@@ -11,7 +11,7 @@
 #include "ui/views/view.h"
 #include "ui/views/views_export.h"
 
-typedef unsigned int SkColor;
+using SkColor = unsigned int;
 
 namespace views {
 
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc
index c35ab6f..37ec7ad 100644
--- a/ui/views/controls/styled_label.cc
+++ b/ui/views/controls/styled_label.cc
@@ -49,10 +49,11 @@
 
     result.reset(link);
   } else if (style_info.custom_font) {
-    result.reset(new Label(text, {style_info.custom_font.value()}));
+    result = std::make_unique<Label>(
+        text, Label::CustomFont{style_info.custom_font.value()});
   } else {
-    result.reset(new Label(text, text_context,
-                           style_info.text_style.value_or(default_style)));
+    result = std::make_unique<Label>(
+        text, text_context, style_info.text_style.value_or(default_style));
   }
   if (style_info.override_color != SK_ColorTRANSPARENT)
     result->SetEnabledColor(style_info.override_color);
diff --git a/ui/views/controls/styled_label.h b/ui/views/controls/styled_label.h
index 66695f4..e4ca7cc 100644
--- a/ui/views/controls/styled_label.h
+++ b/ui/views/controls/styled_label.h
@@ -169,7 +169,7 @@
     gfx::Range range;
     RangeStyleInfo style_info;
   };
-  typedef std::list<StyleRange> StyleRanges;
+  using StyleRanges = std::list<StyleRange>;
 
   // Returns the default line height, based on the default style.
   int GetDefaultLineHeight() const;
diff --git a/ui/views/controls/styled_label_unittest.cc b/ui/views/controls/styled_label_unittest.cc
index c32965c..7378798 100644
--- a/ui/views/controls/styled_label_unittest.cc
+++ b/ui/views/controls/styled_label_unittest.cc
@@ -46,7 +46,7 @@
   StyledLabel* styled() { return styled_.get(); }
 
   void InitStyledLabel(const std::string& ascii_text) {
-    styled_.reset(new StyledLabel(ASCIIToUTF16(ascii_text), this));
+    styled_ = std::make_unique<StyledLabel>(ASCIIToUTF16(ascii_text), this);
     styled_->set_owned_by_client();
   }
 
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 720aed1..f16cac0e 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
 
+#include <memory>
+
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -42,9 +44,9 @@
 constexpr SkColor kTabTitleColor_InactiveHighlight = gfx::kGoogleGrey700;
 constexpr SkColor kTabTitleColor_ActiveBorder = SK_ColorBLACK;
 constexpr SkColor kTabTitleColor_ActiveHighlight = gfx::kGoogleBlue600;
-const SkColor kTabTitleColor_Hovered = SK_ColorBLACK;
-const SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8);
-const SkScalar kTabBorderThickness = 1.0f;
+constexpr SkColor kTabTitleColor_Hovered = SK_ColorBLACK;
+constexpr SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8);
+constexpr SkScalar kTabBorderThickness = 1.0f;
 constexpr SkColor kTabHighlightBackgroundColor_Active =
     SkColorSetARGB(0xFF, 0xE8, 0xF0, 0xFE);
 constexpr SkColor kTabHighlightBackgroundColor_Focused =
@@ -53,15 +55,16 @@
 constexpr int kTabHighlightPreferredHeight = 32;
 constexpr int kTabHighlightPreferredWidth = 192;
 
-const gfx::Font::Weight kHoverWeightBorder = gfx::Font::Weight::NORMAL;
-const gfx::Font::Weight kHoverWeightHighlight = gfx::Font::Weight::MEDIUM;
-const gfx::Font::Weight kActiveWeight = gfx::Font::Weight::BOLD;
-const gfx::Font::Weight kInactiveWeightBorder = gfx::Font::Weight::NORMAL;
-const gfx::Font::Weight kInactiveWeightHighlight = gfx::Font::Weight::MEDIUM;
+constexpr gfx::Font::Weight kHoverWeightBorder = gfx::Font::Weight::NORMAL;
+constexpr gfx::Font::Weight kHoverWeightHighlight = gfx::Font::Weight::MEDIUM;
+constexpr gfx::Font::Weight kActiveWeight = gfx::Font::Weight::BOLD;
+constexpr gfx::Font::Weight kInactiveWeightBorder = gfx::Font::Weight::NORMAL;
+constexpr gfx::Font::Weight kInactiveWeightHighlight =
+    gfx::Font::Weight::MEDIUM;
 
 constexpr int kLabelFontSizeDeltaHighlight = 1;
 
-const int kHarmonyTabStripTabHeight = 32;
+constexpr int kHarmonyTabStripTabHeight = 32;
 constexpr int kBorderThickness = 2;
 
 }  // namespace
@@ -140,13 +143,13 @@
     title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
 
   if (is_highlight_style && is_vertical) {
-    const int kTabVerticalPadding = 8;
-    const int kTabHorizontalPadding = 32;
+    constexpr int kTabVerticalPadding = 8;
+    constexpr int kTabHorizontalPadding = 32;
     SetBorder(CreateEmptyBorder(gfx::Insets(
         kTabVerticalPadding, kTabHorizontalPadding, kTabVerticalPadding, 0)));
   } else {
-    const int kTabVerticalPadding = 5;
-    const int kTabHorizontalPadding = 10;
+    constexpr int kTabVerticalPadding = 5;
+    constexpr int kTabHorizontalPadding = 10;
     SetBorder(CreateEmptyBorder(
         gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding)));
   }
@@ -409,13 +412,13 @@
     : orientation_(orientation), style_(style) {
   std::unique_ptr<BoxLayout> layout;
   if (orientation == TabbedPane::Orientation::kHorizontal) {
-    const int kTabStripLeadingEdgePadding = 9;
+    constexpr int kTabStripLeadingEdgePadding = 9;
     layout = std::make_unique<BoxLayout>(
         BoxLayout::kHorizontal, gfx::Insets(0, kTabStripLeadingEdgePadding));
     layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END);
   } else {
-    const int kTabStripEdgePadding = 8;
-    const int kTabSpacing = 8;
+    constexpr int kTabStripEdgePadding = 8;
+    constexpr int kTabSpacing = 8;
     layout = std::make_unique<BoxLayout>(
         BoxLayout::kVertical, gfx::Insets(kTabStripEdgePadding, 0, 0, 0),
         kTabSpacing);
@@ -538,10 +541,10 @@
   // These durations are taken from the Paper Tabs source:
   // https://github.com/PolymerElements/paper-tabs/blob/master/paper-tabs.html
   // See |selectionBar.expand| and |selectionBar.contract|.
-  expand_animation_.reset(new gfx::LinearAnimation(this));
+  expand_animation_ = std::make_unique<gfx::LinearAnimation>(this);
   expand_animation_->SetDuration(base::TimeDelta::FromMilliseconds(150));
 
-  contract_animation_.reset(new gfx::LinearAnimation(this));
+  contract_animation_ = std::make_unique<gfx::LinearAnimation>(this);
   contract_animation_->SetDuration(base::TimeDelta::FromMilliseconds(180));
 }
 
@@ -572,8 +575,8 @@
   if (style() == TabbedPane::TabStripStyle::kHighlight)
     return;
 
-  const int kUnselectedBorderThickness = 1;
-  const int kSelectedBorderThickness = 2;
+  constexpr int kUnselectedBorderThickness = 1;
+  constexpr int kSelectedBorderThickness = 2;
   const bool is_horizontal =
       orientation() == TabbedPane::Orientation::kHorizontal;
 
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.h b/ui/views/controls/tabbed_pane/tabbed_pane.h
index 50a34ab..b4285dc 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.h
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.h
@@ -43,8 +43,8 @@
     kHighlight,  // Highlight background and text of the selected tab.
   };
 
-  TabbedPane(Orientation orientation = Orientation::kHorizontal,
-             TabStripStyle style = TabStripStyle::kBorder);
+  explicit TabbedPane(Orientation orientation = Orientation::kHorizontal,
+                      TabStripStyle style = TabStripStyle::kBorder);
   ~TabbedPane() override;
 
   TabbedPaneListener* listener() const { return listener_; }
diff --git a/ui/views/controls/table/table_header.cc b/ui/views/controls/table/table_header.cc
index 852c60c7..6656988 100644
--- a/ui/views/controls/table/table_header.cc
+++ b/ui/views/controls/table/table_header.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "cc/paint/paint_flags.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkPath.h"
@@ -46,10 +48,10 @@
 // static
 const int TableHeader::kHorizontalPadding = 7;
 // static
-const int TableHeader::kSortIndicatorWidth = kSortIndicatorSize +
-    TableHeader::kHorizontalPadding * 2;
+const int TableHeader::kSortIndicatorWidth =
+    kSortIndicatorSize + TableHeader::kHorizontalPadding * 2;
 
-typedef std::vector<TableView::VisibleColumn> Columns;
+using Columns = std::vector<TableView::VisibleColumn>;
 
 TableHeader::TableHeader(TableView* table) : table_(table) {}
 
@@ -265,7 +267,7 @@
   if (index == -1)
     return false;
 
-  resize_details_.reset(new ColumnResizeDetails);
+  resize_details_ = std::make_unique<ColumnResizeDetails>();
   resize_details_->column_index = index;
   resize_details_->initial_x = event.root_location().x();
   resize_details_->initial_width = table_->GetVisibleColumn(index).width;
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h
index 76980a3..aa9a297 100644
--- a/ui/views/controls/table/table_view.h
+++ b/ui/views/controls/table/table_view.h
@@ -102,7 +102,7 @@
     bool ascending;
   };
 
-  typedef std::vector<SortDescriptor> SortDescriptors;
+  using SortDescriptors = std::vector<SortDescriptor>;
 
   // Creates a new table using the model and columns specified.
   // The table type applies to the content of the first column (text, icon and
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc
index 6bb4c28f..94b09e3 100644
--- a/ui/views/controls/table/table_view_unittest.cc
+++ b/ui/views/controls/table/table_view_unittest.cc
@@ -262,7 +262,7 @@
   void SetUp() override {
     ViewsTestBase::SetUp();
 
-    model_.reset(new TestTableModel2);
+    model_ = std::make_unique<TestTableModel2>();
     std::vector<ui::TableColumn> columns(2);
     columns[0].title = base::ASCIIToUTF16("Title Column 0");
     columns[0].sortable = true;
@@ -273,7 +273,7 @@
     View* parent = table_->CreateParentIfNecessary();
     parent->SetBounds(0, 0, 10000, 10000);
     parent->Layout();
-    helper_.reset(new TableViewTestHelper(table_));
+    helper_ = std::make_unique<TableViewTestHelper>(table_);
 
     widget_ = std::make_unique<Widget>();
     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 73c2f61d..4a793b6 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -88,14 +88,14 @@
 namespace {
 
 #if defined(OS_MACOSX)
-const gfx::SelectionBehavior kLineSelectionBehavior = gfx::SELECTION_EXTEND;
-const gfx::SelectionBehavior kWordSelectionBehavior = gfx::SELECTION_CARET;
-const gfx::SelectionBehavior kMoveParagraphSelectionBehavior =
+constexpr gfx::SelectionBehavior kLineSelectionBehavior = gfx::SELECTION_EXTEND;
+constexpr gfx::SelectionBehavior kWordSelectionBehavior = gfx::SELECTION_CARET;
+constexpr gfx::SelectionBehavior kMoveParagraphSelectionBehavior =
     gfx::SELECTION_CARET;
 #else
-const gfx::SelectionBehavior kLineSelectionBehavior = gfx::SELECTION_RETAIN;
-const gfx::SelectionBehavior kWordSelectionBehavior = gfx::SELECTION_RETAIN;
-const gfx::SelectionBehavior kMoveParagraphSelectionBehavior =
+constexpr gfx::SelectionBehavior kLineSelectionBehavior = gfx::SELECTION_RETAIN;
+constexpr gfx::SelectionBehavior kWordSelectionBehavior = gfx::SELECTION_RETAIN;
+constexpr gfx::SelectionBehavior kMoveParagraphSelectionBehavior =
     gfx::SELECTION_RETAIN;
 #endif
 
@@ -1231,7 +1231,7 @@
                         GetWidget()->GetCompositor()->is_pixel_canvas())
           .context(),
       label.size()));
-  const gfx::Vector2d kOffset(-15, 0);
+  constexpr gfx::Vector2d kOffset(-15, 0);
   gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, raster_scale));
   data->provider().SetDragImage(image, kOffset);
   if (controller_)
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 5d9e17b..6c15dc15 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -464,7 +464,7 @@
     container->AddChildView(textfield_);
     textfield_->SetBoundsRect(params.bounds);
     textfield_->set_id(1);
-    test_api_.reset(new TextfieldTestApi(textfield_));
+    test_api_ = std::make_unique<TextfieldTestApi>(textfield_);
 
     for (int i = 1; i < count; i++) {
       Textfield* textfield = new Textfield();
@@ -3363,7 +3363,7 @@
 
   new_textfield->SetBoundsRect(params.bounds);
   new_textfield->set_id(1);
-  test_api_.reset(new TextfieldTestApi(new_textfield));
+  test_api_ = std::make_unique<TextfieldTestApi>(new_textfield);
   widget->Show();
   EXPECT_FALSE(new_textfield->HasFocus());
   EXPECT_FALSE(test_api_->IsCursorVisible());
diff --git a/ui/views/controls/throbber.cc b/ui/views/controls/throbber.cc
index f2ced13..f54ecca 100644
--- a/ui/views/controls/throbber.cc
+++ b/ui/views/controls/throbber.cc
@@ -21,10 +21,10 @@
 
 // The default diameter of a Throbber. If you change this, also change
 // kCheckmarkDipSize.
-static const int kDefaultDiameter = 16;
+static constexpr int kDefaultDiameter = 16;
 // The size of the checkmark, in DIP. This magic number matches the default
 // diamater plus padding inherent in the checkmark SVG.
-static const int kCheckmarkDipSize = 18;
+static constexpr int kCheckmarkDipSize = 18;
 
 Throbber::Throbber() : checked_(false) {
 }
@@ -38,7 +38,7 @@
     return;
 
   start_time_ = base::TimeTicks::Now();
-  const int kFrameTimeMs = 30;
+  constexpr int kFrameTimeMs = 30;
   timer_.Start(
       FROM_HERE, base::TimeDelta::FromMilliseconds(kFrameTimeMs),
       base::BindRepeating(&Throbber::SchedulePaint, base::Unretained(this)));
@@ -90,10 +90,10 @@
 // Smoothed throbber ---------------------------------------------------------
 
 // Delay after work starts before starting throbber, in milliseconds.
-static const int kStartDelay = 200;
+static constexpr int kStartDelay = 200;
 
 // Delay after work stops before stopping, in milliseconds.
-static const int kStopDelay = 50;
+static constexpr int kStopDelay = 50;
 
 SmoothedThrobber::SmoothedThrobber()
     : start_delay_ms_(kStartDelay), stop_delay_ms_(kStopDelay) {
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
index 80b66ed..f5157820 100644
--- a/ui/views/controls/tree/tree_view.cc
+++ b/ui/views/controls/tree/tree_view.cc
@@ -42,16 +42,16 @@
 namespace views {
 
 // Insets around the view.
-static const int kHorizontalInset = 2;
+static constexpr int kHorizontalInset = 2;
 // Padding before/after the image.
-static const int kImagePadding = 4;
+static constexpr int kImagePadding = 4;
 // Size of the arrow region.
-static const int kArrowRegionSize = 12;
+static constexpr int kArrowRegionSize = 12;
 // Padding around the text (on each side).
-static const int kTextVerticalPadding = 3;
-static const int kTextHorizontalPadding = 2;
+static constexpr int kTextVerticalPadding = 3;
+static constexpr int kTextHorizontalPadding = 2;
 // How much children are indented from their parent.
-static const int kIndent = 20;
+static constexpr int kIndent = 20;
 
 // static
 const char TreeView::kViewClassName[] = "TreeView";
@@ -1107,7 +1107,7 @@
 
 PrefixSelector* TreeView::GetPrefixSelector() {
   if (!selector_)
-    selector_.reset(new PrefixSelector(this, this));
+    selector_ = std::make_unique<PrefixSelector>(this, this);
   return selector_.get();
 }
 
diff --git a/ui/views/controls/webview/webview_unittest.cc b/ui/views/controls/webview/webview_unittest.cc
index 4072d02..d59d40b 100644
--- a/ui/views/controls/webview/webview_unittest.cc
+++ b/ui/views/controls/webview/webview_unittest.cc
@@ -146,7 +146,7 @@
         std::make_unique<views::WebView::ScopedWebContentsCreatorForTesting>(
             creator);
     set_views_delegate(base::WrapUnique(new views::TestViewsDelegate));
-    browser_context_.reset(new content::TestBrowserContext);
+    browser_context_ = std::make_unique<content::TestBrowserContext>();
     WidgetTest::SetUp();
     // Set the test content browser client to avoid pulling in needless
     // dependencies from content.
diff --git a/ui/views/corewm/cursor_height_provider_win.cc b/ui/views/corewm/cursor_height_provider_win.cc
index 2b4c803..075a1aa 100644
--- a/ui/views/corewm/cursor_height_provider_win.cc
+++ b/ui/views/corewm/cursor_height_provider_win.cc
@@ -20,11 +20,11 @@
 
 const uint32_t kBitsPeruint32 = sizeof(uint32_t) * 8;
 // All bits are 1 for transparent portion of monochromatic mask.
-const uint32_t kTransparentMask = 0xffffffff;
+constexpr uint32_t kTransparentMask = 0xffffffff;
 // This is height of default pointer arrow in Windows 7.
-const int kDefaultHeight = 20;
+constexpr int kDefaultHeight = 20;
 // Masks are monochromatic.
-const size_t kNumberOfColors = 2;
+constexpr size_t kNumberOfColors = 2;
 const size_t KHeaderAndPalette =
       sizeof(BITMAPINFOHEADER) + kNumberOfColors * sizeof(RGBQUAD);
 
diff --git a/ui/views/corewm/desktop_capture_controller_unittest.cc b/ui/views/corewm/desktop_capture_controller_unittest.cc
index b5eeec9b..4a46b67 100644
--- a/ui/views/corewm/desktop_capture_controller_unittest.cc
+++ b/ui/views/corewm/desktop_capture_controller_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "ui/wm/core/capture_controller.h"
 
+#include <memory>
+
 #include "base/logging.h"
 #include "base/macros.h"
 #include "ui/aura/env.h"
@@ -110,8 +112,8 @@
   internal::RootView* root1 =
       static_cast<internal::RootView*>(widget1->GetRootView());
 
-  desktop_position_client1.reset(
-      new DesktopScreenPositionClient(params.context->GetRootWindow()));
+  desktop_position_client1 = std::make_unique<DesktopScreenPositionClient>(
+      params.context->GetRootWindow());
   aura::client::SetScreenPositionClient(
       widget1->GetNativeView()->GetRootWindow(),
       desktop_position_client1.get());
@@ -132,8 +134,8 @@
 
   internal::RootView* root2 =
       static_cast<internal::RootView*>(widget2->GetRootView());
-  desktop_position_client2.reset(
-      new DesktopScreenPositionClient(params.context->GetRootWindow()));
+  desktop_position_client2 = std::make_unique<DesktopScreenPositionClient>(
+      params.context->GetRootWindow());
   aura::client::SetScreenPositionClient(
       widget2->GetNativeView()->GetRootWindow(),
       desktop_position_client2.get());
diff --git a/ui/views/corewm/tooltip_aura.cc b/ui/views/corewm/tooltip_aura.cc
index 09c9120..f6e9135 100644
--- a/ui/views/corewm/tooltip_aura.cc
+++ b/ui/views/corewm/tooltip_aura.cc
@@ -27,11 +27,11 @@
 
 // Max visual tooltip width. If a tooltip is greater than this width, it will
 // be wrapped.
-const int kTooltipMaxWidthPixels = 400;
+constexpr int kTooltipMaxWidthPixels = 400;
 
 // FIXME: get cursor offset from actual cursor size.
-const int kCursorOffsetX = 10;
-const int kCursorOffsetY = 15;
+constexpr int kCursorOffsetX = 10;
+constexpr int kCursorOffsetY = 15;
 
 // TODO(varkha): Update if native widget can be transparent on Linux.
 bool CanUseTranslucentTooltipWidget() {
@@ -72,9 +72,9 @@
  public:
   TooltipView()
       : render_text_(gfx::RenderText::CreateHarfBuzzInstance()), max_width_(0) {
-    const int kHorizontalPadding = 8;
-    const int kVerticalPaddingTop = 4;
-    const int kVerticalPaddingBottom = 5;
+    constexpr int kHorizontalPadding = 8;
+    constexpr int kVerticalPaddingTop = 4;
+    constexpr int kVerticalPaddingBottom = 5;
     SetBorder(CreateEmptyBorder(kVerticalPaddingTop, kHorizontalPadding,
                                 kVerticalPaddingBottom, kHorizontalPadding));
 
diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index e0480d0..194f67c 100644
--- a/ui/views/corewm/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -31,13 +31,13 @@
 namespace corewm {
 namespace {
 
-const int kDelayForTooltipUpdateInMs = 500;
-const int kDefaultTooltipShownTimeoutMs = 10000;
+constexpr int kDelayForTooltipUpdateInMs = 500;
+constexpr int kDefaultTooltipShownTimeoutMs = 10000;
 #if defined(OS_WIN)
 // Drawing a long word in tooltip is very slow on Windows. crbug.com/513693
-const size_t kMaxTooltipLength = 1024;
+constexpr size_t kMaxTooltipLength = 1024;
 #else
-const size_t kMaxTooltipLength = 2048;
+constexpr size_t kMaxTooltipLength = 2048;
 #endif
 
 // Returns true if |target| is a valid window to get the tooltip from.
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
index 96adea6..dd7580ef 100644
--- a/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -105,9 +105,9 @@
     view_ = new TooltipTestView;
     widget_->GetContentsView()->AddChildView(view_);
     view_->SetBoundsRect(widget_->GetContentsView()->GetLocalBounds());
-    helper_.reset(new TooltipControllerTestHelper(
-                      GetController(widget_.get())));
-    generator_.reset(new ui::test::EventGenerator(GetRootWindow()));
+    helper_ = std::make_unique<TooltipControllerTestHelper>(
+        GetController(widget_.get()));
+    generator_ = std::make_unique<ui::test::EventGenerator>(GetRootWindow());
   }
 
   void TearDown() override {
@@ -604,12 +604,12 @@
     at_exit_manager_ = std::make_unique<base::ShadowingAtExitManager>();
     aura::test::AuraTestBase::SetUp();
     new wm::DefaultActivationClient(root_window());
-    controller_.reset(
-        new TooltipController(std::unique_ptr<corewm::Tooltip>(test_tooltip_)));
+    controller_ = std::make_unique<TooltipController>(
+        std::unique_ptr<corewm::Tooltip>(test_tooltip_));
     root_window()->AddPreTargetHandler(controller_.get());
     SetTooltipClient(root_window(), controller_.get());
-    helper_.reset(new TooltipControllerTestHelper(controller_.get()));
-    generator_.reset(new ui::test::EventGenerator(root_window()));
+    helper_ = std::make_unique<TooltipControllerTestHelper>(controller_.get());
+    generator_ = std::make_unique<ui::test::EventGenerator>(root_window());
   }
 
   void TearDown() override {
@@ -691,7 +691,7 @@
     widget_->GetContentsView()->AddChildView(view_);
     view_->SetBoundsRect(widget_->GetContentsView()->GetLocalBounds());
 
-    generator_.reset(new ui::test::EventGenerator(GetRootWindow()));
+    generator_ = std::make_unique<ui::test::EventGenerator>(GetRootWindow());
     auto tooltip = std::make_unique<TestTooltip>();
     test_tooltip_ = tooltip.get();
     controller_ = std::make_unique<TooltipController>(std::move(tooltip));
@@ -700,7 +700,7 @@
     if (tooltip_controller)
       GetRootWindow()->RemovePreTargetHandler(tooltip_controller);
     GetRootWindow()->AddPreTargetHandler(controller_.get());
-    helper_.reset(new TooltipControllerTestHelper(controller_.get()));
+    helper_ = std::make_unique<TooltipControllerTestHelper>(controller_.get());
     SetTooltipClient(GetRootWindow(), controller_.get());
   }
 
diff --git a/ui/views/examples/menu_example.cc b/ui/views/examples/menu_example.cc
index 3074cdff1..289affcd 100644
--- a/ui/views/examples/menu_example.cc
+++ b/ui/views/examples/menu_example.cc
@@ -4,6 +4,7 @@
 
 #include "ui/views/examples/menu_example.h"
 
+#include <memory>
 #include <set>
 
 #include "base/macros.h"
@@ -95,7 +96,7 @@
   AddSeparator(ui::NORMAL_SEPARATOR);
   AddItem(COMMAND_GO_HOME, ASCIIToUTF16("Go Home"));
 
-  submenu_.reset(new ui::SimpleMenuModel(this));
+  submenu_ = std::make_unique<ui::SimpleMenuModel>(this);
   submenu_->AddItem(COMMAND_DO_SOMETHING, ASCIIToUTF16("Do Something 2"));
   AddSubMenu(0, ASCIIToUTF16("Submenu"), submenu_.get());
 }
@@ -178,7 +179,8 @@
 void ExampleMenuButton::OnMenuButtonClicked(MenuButton* source,
                                             const gfx::Point& point,
                                             const ui::Event* event) {
-  menu_runner_.reset(new MenuRunner(GetMenuModel(), MenuRunner::HAS_MNEMONICS));
+  menu_runner_ =
+      std::make_unique<MenuRunner>(GetMenuModel(), MenuRunner::HAS_MNEMONICS);
 
   menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), this,
                           gfx::Rect(point, gfx::Size()), MENU_ANCHOR_TOPRIGHT,
@@ -187,7 +189,7 @@
 
 ui::SimpleMenuModel* ExampleMenuButton::GetMenuModel() {
   if (!menu_model_.get())
-    menu_model_.reset(new ExampleMenuModel);
+    menu_model_ = std::make_unique<ExampleMenuModel>();
   return menu_model_.get();
 }
 
diff --git a/ui/views/examples/tree_view_example.cc b/ui/views/examples/tree_view_example.cc
index d3bf9b0c..a85ac00e 100644
--- a/ui/views/examples/tree_view_example.cc
+++ b/ui/views/examples/tree_view_example.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/examples/tree_view_example.h"
 
+#include <memory>
+
 #include "base/strings/utf_string_conversions.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/menu/menu_model_adapter.h"
@@ -155,11 +157,12 @@
     View* source,
     const gfx::Point& point,
     ui::MenuSourceType source_type) {
-  context_menu_model_.reset(new ui::SimpleMenuModel(this));
+  context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
   context_menu_model_->AddItem(ID_EDIT, ASCIIToUTF16("Edit"));
   context_menu_model_->AddItem(ID_REMOVE, ASCIIToUTF16("Remove"));
   context_menu_model_->AddItem(ID_ADD, ASCIIToUTF16("Add"));
-  context_menu_runner_.reset(new MenuRunner(context_menu_model_.get(), 0));
+  context_menu_runner_ =
+      std::make_unique<MenuRunner>(context_menu_model_.get(), 0);
   context_menu_runner_->RunMenuAt(source->GetWidget(), nullptr,
                                   gfx::Rect(point, gfx::Size()),
                                   MENU_ANCHOR_TOPLEFT, source_type);
diff --git a/ui/views/examples/tree_view_example.h b/ui/views/examples/tree_view_example.h
index 6677b0f..c158190 100644
--- a/ui/views/examples/tree_view_example.h
+++ b/ui/views/examples/tree_view_example.h
@@ -77,7 +77,7 @@
   LabelButton* remove_;
   LabelButton* change_title_;
 
-  typedef ui::TreeNodeWithValue<int> NodeType;
+  using NodeType = ui::TreeNodeWithValue<int>;
 
   ui::TreeNodeModel<NodeType> model_;
 
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc
index f246424d..3cacff9 100644
--- a/ui/views/focus/focus_manager_unittest.cc
+++ b/ui/views/focus/focus_manager_unittest.cc
@@ -414,7 +414,7 @@
 
 class FocusManagerDtorTest : public FocusManagerTest {
  protected:
-  typedef std::vector<std::string> DtorTrackVector;
+  using DtorTrackVector = std::vector<std::string>;
 
   class FocusManagerDtorTracked : public FocusManager {
    public:
@@ -828,7 +828,7 @@
 
 class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
  public:
-  TestBubbleDialogDelegateView(View* anchor)
+  explicit TestBubbleDialogDelegateView(View* anchor)
       : BubbleDialogDelegateView(anchor, BubbleBorder::NONE) {}
   ~TestBubbleDialogDelegateView() override = default;
 
@@ -875,7 +875,7 @@
   params.bounds = gfx::Rect(10, 10, 100, 100);
   params.parent = GetWidget()->GetNativeView();
   Widget child_widget;
-  delegate.reset(new AdvanceFocusWidgetDelegate(&child_widget));
+  delegate = std::make_unique<AdvanceFocusWidgetDelegate>(&child_widget);
   params.delegate = delegate.get();
   child_widget.Init(params);
   View* view1 = new View;
diff --git a/ui/views/layout/box_layout.h b/ui/views/layout/box_layout.h
index baa4c7e..262a1e5 100644
--- a/ui/views/layout/box_layout.h
+++ b/ui/views/layout/box_layout.h
@@ -107,10 +107,10 @@
   // SSSSSSSSSSSSSSSSSSSS
   // --------------------
   //
-  BoxLayout(Orientation orientation,
-            const gfx::Insets& inside_border_insets = gfx::Insets(),
-            int between_child_spacing = 0,
-            bool collapse_margins_spacing = false);
+  explicit BoxLayout(Orientation orientation,
+                     const gfx::Insets& inside_border_insets = gfx::Insets(),
+                     int between_child_spacing = 0,
+                     bool collapse_margins_spacing = false);
   ~BoxLayout() override;
 
   void set_main_axis_alignment(MainAxisAlignment main_axis_alignment) {
diff --git a/ui/views/layout/box_layout_unittest.cc b/ui/views/layout/box_layout_unittest.cc
index 0343bb0..f5b4532 100644
--- a/ui/views/layout/box_layout_unittest.cc
+++ b/ui/views/layout/box_layout_unittest.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/views/test/test_views.h"
@@ -18,7 +20,7 @@
 
 class BoxLayoutTest : public testing::Test {
  public:
-  void SetUp() override { host_.reset(new View); }
+  void SetUp() override { host_ = std::make_unique<View>(); }
 
   std::unique_ptr<View> host_;
 };
diff --git a/ui/views/mouse_constants.h b/ui/views/mouse_constants.h
index 9545a02..957eee3 100644
--- a/ui/views/mouse_constants.h
+++ b/ui/views/mouse_constants.h
@@ -12,11 +12,11 @@
 // considered intentional. This is to prevent spurious mouse releases from
 // activating controls, especially when some UI element is revealed under the
 // source of the activation (ex. menus showing underneath menu buttons).
-const int kMinimumMsPressedToActivate = 200;
+constexpr int kMinimumMsPressedToActivate = 200;
 
 // The amount of time, in milliseconds, between clicks until they're
 // considered intentionally different.
-const int kMinimumMsBetweenButtonClicks = 100;
+constexpr int kMinimumMsBetweenButtonClicks = 100;
 
 }  // namespace views
 
diff --git a/ui/views/mouse_watcher.cc b/ui/views/mouse_watcher.cc
index 713e15a7..25efd877 100644
--- a/ui/views/mouse_watcher.cc
+++ b/ui/views/mouse_watcher.cc
@@ -22,7 +22,7 @@
 
 // Amount of time between when the mouse moves outside the Host's zone and when
 // the listener is notified.
-const int kNotifyListenerTimeMs = 300;
+constexpr int kNotifyListenerTimeMs = 300;
 
 class MouseWatcher::Observer : public ui::EventObserver {
  public:
diff --git a/ui/views/repeat_controller.cc b/ui/views/repeat_controller.cc
index 95a60418..319ce70c 100644
--- a/ui/views/repeat_controller.cc
+++ b/ui/views/repeat_controller.cc
@@ -10,8 +10,8 @@
 
 // The delay before the first and then subsequent repeats. Values taken from
 // XUL code: http://mxr.mozilla.org/seamonkey/source/layout/xul/base/src/nsRepeatService.cpp#52
-const int kInitialRepeatDelay = 250;
-const int kRepeatDelay = 50;
+constexpr int kInitialRepeatDelay = 250;
+constexpr int kRepeatDelay = 50;
 
 ///////////////////////////////////////////////////////////////////////////////
 // RepeatController, public:
diff --git a/ui/views/selection_controller_unittest.cc b/ui/views/selection_controller_unittest.cc
index 626ff04..96b7465a 100644
--- a/ui/views/selection_controller_unittest.cc
+++ b/ui/views/selection_controller_unittest.cc
@@ -26,7 +26,7 @@
 
 class TestSelectionControllerDelegate : public SelectionControllerDelegate {
  public:
-  TestSelectionControllerDelegate(gfx::RenderText* render_text)
+  explicit TestSelectionControllerDelegate(gfx::RenderText* render_text)
       : render_text_(render_text) {}
   ~TestSelectionControllerDelegate() override = default;
 
diff --git a/ui/views/test/combobox_test_api.cc b/ui/views/test/combobox_test_api.cc
index 5a66d2d..a2bf896 100644
--- a/ui/views/test/combobox_test_api.cc
+++ b/ui/views/test/combobox_test_api.cc
@@ -6,6 +6,8 @@
 
 #include <stdint.h>
 
+#include <memory>
+
 #include "base/macros.h"
 #include "ui/base/models/menu_model.h"
 #include "ui/views/controls/combobox/combobox.h"
@@ -45,8 +47,8 @@
 }
 
 void ComboboxTestApi::InstallTestMenuRunner(int* menu_show_count) {
-  combobox_->menu_runner_.reset(
-      new MenuRunner(menu_model(), MenuRunner::COMBOBOX));
+  combobox_->menu_runner_ =
+      std::make_unique<MenuRunner>(menu_model(), MenuRunner::COMBOBOX);
   test::MenuRunnerTestAPI test_api(combobox_->menu_runner_.get());
   test_api.SetMenuRunnerHandler(
       std::make_unique<TestMenuRunnerHandler>(menu_show_count));
diff --git a/ui/views/test/native_widget_factory.h b/ui/views/test/native_widget_factory.h
index a0aeda8e..f36754a 100644
--- a/ui/views/test/native_widget_factory.h
+++ b/ui/views/test/native_widget_factory.h
@@ -17,9 +17,9 @@
 
 // Values supplied to |behavior|.
 // NativeWidget implementation is not customized in anyway.
-const uint32_t kDefault = 0u;
+constexpr uint32_t kDefault = 0u;
 // Indicates capture should be mocked out and not interact with the system.
-const uint32_t kStubCapture = 1 << 0;
+constexpr uint32_t kStubCapture = 1 << 0;
 
 // Creates the appropriate platform specific NativeWidget implementation.
 // If |destroyed| is non-null it it set to true from the destructor of the
diff --git a/ui/views/test/views_test_base.cc b/ui/views/test/views_test_base.cc
index c193b055..d24485b 100644
--- a/ui/views/test/views_test_base.cc
+++ b/ui/views/test/views_test_base.cc
@@ -114,7 +114,7 @@
   ui::MaterialDesignController::Initialize();
   setup_called_ = true;
   if (!views_delegate_for_setup_)
-    views_delegate_for_setup_.reset(new TestViewsDelegate());
+    views_delegate_for_setup_ = std::make_unique<TestViewsDelegate>();
 
 #if BUILDFLAG(ENABLE_MUS)
   if (is_mus()) {
@@ -143,8 +143,8 @@
   }
 #endif
 
-  test_helper_.reset(
-      new ScopedViewsTestHelper(std::move(views_delegate_for_setup_)));
+  test_helper_ = std::make_unique<ScopedViewsTestHelper>(
+      std::move(views_delegate_for_setup_));
 }
 
 void ViewsTestBase::TearDown() {
diff --git a/ui/views/test/views_test_helper_aura.cc b/ui/views/test/views_test_helper_aura.cc
index 09a196a..012362b 100644
--- a/ui/views/test/views_test_helper_aura.cc
+++ b/ui/views/test/views_test_helper_aura.cc
@@ -25,7 +25,7 @@
     ui::ContextFactoryPrivate* context_factory_private)
     : context_factory_(context_factory),
       context_factory_private_(context_factory_private) {
-  aura_test_helper_.reset(new aura::test::AuraTestHelper());
+  aura_test_helper_ = std::make_unique<aura::test::AuraTestHelper>();
 }
 
 ViewsTestHelperAura::~ViewsTestHelperAura() = default;
@@ -46,7 +46,8 @@
   new wm::DefaultActivationClient(root_window);
 
   if (!aura::client::GetScreenPositionClient(root_window)) {
-    screen_position_client_.reset(new wm::DefaultScreenPositionClient);
+    screen_position_client_ =
+        std::make_unique<wm::DefaultScreenPositionClient>();
     aura::client::SetScreenPositionClient(root_window,
                                           screen_position_client_.get());
   }
diff --git a/ui/views/test/webview_test_helper.cc b/ui/views/test/webview_test_helper.cc
index d1dfa535..fb06394 100644
--- a/ui/views/test/webview_test_helper.cc
+++ b/ui/views/test/webview_test_helper.cc
@@ -10,8 +10,8 @@
 namespace views {
 
 WebViewTestHelper::WebViewTestHelper() {
-  test_content_client_initializer_.reset(
-      new content::TestContentClientInitializer());
+  test_content_client_initializer_ =
+      std::make_unique<content::TestContentClientInitializer>();
 
   // Setup to register a new RenderViewHost factory which manufactures
   // mock render process hosts. This ensures that we never create a 'real'
diff --git a/ui/views/test/widget_test.h b/ui/views/test/widget_test.h
index 155cef00..41ad760 100644
--- a/ui/views/test/widget_test.h
+++ b/ui/views/test/widget_test.h
@@ -125,7 +125,7 @@
 class TestDesktopWidgetDelegate : public WidgetDelegate {
  public:
   TestDesktopWidgetDelegate();
-  TestDesktopWidgetDelegate(Widget* widget);
+  explicit TestDesktopWidgetDelegate(Widget* widget);
   ~TestDesktopWidgetDelegate() override;
 
   // Initialize the Widget, adding some meaningful default InitParams.
diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc
index 6702b3ad..640ee55 100644
--- a/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/ui/views/touchui/touch_selection_controller_impl.cc
@@ -31,7 +31,7 @@
 
 // The distance by which a handle image is offset from the bottom of the
 // selection/text baseline.
-const int kSelectionHandleVerticalVisualOffset = 2;
+constexpr int kSelectionHandleVerticalVisualOffset = 2;
 
 // When a handle is dragged, the drag position reported to the client view is
 // offset vertically to represent the cursor position. This constant specifies
@@ -56,23 +56,23 @@
 //                                  T
 //                          Horizontal Padding
 //
-const int kSelectionHandleVerticalDragOffset = 5;
+constexpr int kSelectionHandleVerticalDragOffset = 5;
 
 // Padding around the selection handle defining the area that will be included
 // in the touch target to make dragging the handle easier (see pic above).
-const int kSelectionHandleHorizPadding = 10;
-const int kSelectionHandleVertPadding = 20;
+constexpr int kSelectionHandleHorizPadding = 10;
+constexpr int kSelectionHandleVertPadding = 20;
 
-const int kQuickMenuTimoutMs = 200;
+constexpr int kQuickMenuTimoutMs = 200;
 
-const int kSelectionHandleQuickFadeDurationMs = 50;
+constexpr int kSelectionHandleQuickFadeDurationMs = 50;
 
 // Minimum height for selection handle bar. If the bar height is going to be
 // less than this value, handle will not be shown.
-const int kSelectionHandleBarMinHeight = 5;
+constexpr int kSelectionHandleBarMinHeight = 5;
 // Maximum amount that selection handle bar can stick out of client view's
 // boundaries.
-const int kSelectionHandleBarBottomAllowance = 3;
+constexpr int kSelectionHandleBarBottomAllowance = 3;
 
 // Creates a widget to host SelectionHandleView.
 views::Widget* CreateTouchSelectionPopupWidget(
diff --git a/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
index f7af93e..414a934 100644
--- a/ui/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -4,6 +4,8 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
@@ -75,7 +77,8 @@
 
   void SetUp() override {
     ViewsTestBase::SetUp();
-    test_cursor_client_.reset(new aura::test::TestCursorClient(GetContext()));
+    test_cursor_client_ =
+        std::make_unique<aura::test::TestCursorClient>(GetContext());
   }
 
   void TearDown() override {
@@ -103,7 +106,7 @@
     textfield_widget_->Show();
 
     textfield_->RequestFocus();
-    textfield_test_api_.reset(new TextfieldTestApi(textfield_));
+    textfield_test_api_ = std::make_unique<TextfieldTestApi>(textfield_);
   }
 
   void CreateWidget() {
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 2070c2a2..0c8a7f4e 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -68,18 +68,18 @@
 namespace {
 
 #if defined(OS_WIN)
-const bool kContextMenuOnMousePress = false;
+constexpr bool kContextMenuOnMousePress = false;
 #else
-const bool kContextMenuOnMousePress = true;
+constexpr bool kContextMenuOnMousePress = true;
 #endif
 
 // Default horizontal drag threshold in pixels.
 // Same as what gtk uses.
-const int kDefaultHorizontalDragThreshold = 8;
+constexpr int kDefaultHorizontalDragThreshold = 8;
 
 // Default vertical drag threshold in pixels.
 // Same as what gtk uses.
-const int kDefaultVerticalDragThreshold = 8;
+constexpr int kDefaultVerticalDragThreshold = 8;
 
 // Returns the top view in |view|'s hierarchy.
 const View* GetHierarchyRoot(const View* view) {
@@ -98,7 +98,7 @@
  public:
   explicit ScopedChildrenLock(const View* view)
       : reset_(&view->iterating_, true) {}
-  ~ScopedChildrenLock() {}
+  ~ScopedChildrenLock() = default;
 
  private:
   base::AutoReset<bool> reset_;
@@ -1121,7 +1121,7 @@
 
 void View::AddAccelerator(const ui::Accelerator& accelerator) {
   if (!accelerators_)
-    accelerators_.reset(new std::vector<ui::Accelerator>());
+    accelerators_ = std::make_unique<std::vector<ui::Accelerator>>();
 
   if (!base::ContainsValue(*accelerators_, accelerator))
     accelerators_->push_back(accelerator);
@@ -2249,7 +2249,7 @@
 void View::AddDescendantToNotify(View* view) {
   DCHECK(view);
   if (!descendants_to_notify_)
-    descendants_to_notify_.reset(new Views);
+    descendants_to_notify_ = std::make_unique<Views>();
   descendants_to_notify_->push_back(view);
 }
 
diff --git a/ui/views/view.h b/ui/views/view.h
index c017e0c..b3858e0 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -190,8 +190,8 @@
   // working with offsets.
   class LayerOffsetData {
    public:
-    LayerOffsetData(float device_scale_factor = 1.f,
-                    const gfx::Vector2d& offset = gfx::Vector2d())
+    explicit LayerOffsetData(float device_scale_factor = 1.f,
+                             const gfx::Vector2d& offset = gfx::Vector2d())
         : device_scale_factor_(device_scale_factor) {
       AddOffset(offset);
     }
diff --git a/ui/views/view_constants.cc b/ui/views/view_constants.cc
index 63a5a22..dc5c736 100644
--- a/ui/views/view_constants.cc
+++ b/ui/views/view_constants.cc
@@ -6,8 +6,8 @@
 
 namespace views {
 
-const int kAutoscrollSize = 10;
-const int kAutoscrollRowTimerMS = 200;
-const int kDropBetweenPixels = 5;
+constexpr int kAutoscrollSize = 10;
+constexpr int kAutoscrollRowTimerMS = 200;
+constexpr int kDropBetweenPixels = 5;
 
 }  // namespace views
diff --git a/ui/views/view_model.h b/ui/views/view_model.h
index 9513bcf..a6df0f9 100644
--- a/ui/views/view_model.h
+++ b/ui/views/view_model.h
@@ -85,7 +85,7 @@
     View* view;
     gfx::Rect ideal_bounds;
   };
-  typedef std::vector<Entry> Entries;
+  using Entries = std::vector<Entry>;
 
 #if !defined(NDEBUG)
   void check_index(int index) const {
@@ -109,7 +109,7 @@
 template <class T>
 class ViewModelT : public ViewModelBase {
  public:
-  ViewModelT<T>() {}
+  ViewModelT<T>() = default;
 
   // Adds |view| to this model. This does not add |view| to a view hierarchy,
   // only to this model.
@@ -125,7 +125,7 @@
 // ViewModel is a collection of views with no specfic type. If all views have
 // the same type, the use of ViewModelT is preferred so that the views can be
 // retrieved without potentially unsafe downcasts.
-typedef ViewModelT<View> ViewModel;
+using ViewModel = ViewModelT<View>;
 
 }  // namespace views
 
diff --git a/ui/views/view_observer.h b/ui/views/view_observer.h
index e2ed593..34cc6e4 100644
--- a/ui/views/view_observer.h
+++ b/ui/views/view_observer.h
@@ -51,7 +51,7 @@
   virtual void OnViewBlurred(View* observed_view) {}
 
  protected:
-  virtual ~ViewObserver() {}
+  virtual ~ViewObserver() = default;
 };
 
 }  // namespace views
diff --git a/ui/views/view_targeter.cc b/ui/views/view_targeter.cc
index ec82f84..37612b24 100644
--- a/ui/views/view_targeter.cc
+++ b/ui/views/view_targeter.cc
@@ -16,7 +16,7 @@
   DCHECK(delegate_);
 }
 
-ViewTargeter::~ViewTargeter() {}
+ViewTargeter::~ViewTargeter() = default;
 
 bool ViewTargeter::DoesIntersectRect(const View* target,
                                      const gfx::Rect& rect) const {
diff --git a/ui/views/view_targeter_delegate.h b/ui/views/view_targeter_delegate.h
index 44dd839..0ba3fe1 100644
--- a/ui/views/view_targeter_delegate.h
+++ b/ui/views/view_targeter_delegate.h
@@ -23,8 +23,8 @@
 // themselves.
 class VIEWS_EXPORT ViewTargeterDelegate {
  public:
-  ViewTargeterDelegate() {}
-  virtual ~ViewTargeterDelegate() {}
+  ViewTargeterDelegate() = default;
+  virtual ~ViewTargeterDelegate() = default;
 
   // Returns true if |target| should be considered as a candidate target for
   // an event having |rect| as its location, where |rect| is in the local
diff --git a/ui/views/view_targeter_unittest.cc b/ui/views/view_targeter_unittest.cc
index f6aadbd..fb5612f0 100644
--- a/ui/views/view_targeter_unittest.cc
+++ b/ui/views/view_targeter_unittest.cc
@@ -22,7 +22,7 @@
 class TestingView : public View, public ViewTargeterDelegate {
  public:
   TestingView() : can_process_events_within_subtree_(true) {}
-  ~TestingView() override {}
+  ~TestingView() override = default;
 
   // Reset all test state.
   void Reset() { can_process_events_within_subtree_ = true; }
@@ -51,8 +51,8 @@
 // A derived class of View having a triangular-shaped hit test mask.
 class TestMaskedView : public View, public MaskedTargeterDelegate {
  public:
-  TestMaskedView() {}
-  ~TestMaskedView() override {}
+  TestMaskedView() = default;
+  ~TestMaskedView() override = default;
 
   // A call-through function to MaskedTargeterDelegate::DoesIntersectRect().
   bool TestDoesIntersectRect(const View* target, const gfx::Rect& rect) const {
@@ -84,8 +84,8 @@
 //                   See crbug.com/355680.
 class ViewTargeterTest : public ViewsTestBase {
  public:
-  ViewTargeterTest() {}
-  ~ViewTargeterTest() override {}
+  ViewTargeterTest() = default;
+  ~ViewTargeterTest() override = default;
 
   void SetGestureHandler(internal::RootView* root_view, View* handler) {
     root_view->gesture_handler_ = handler;
@@ -237,7 +237,7 @@
                      base::TimeTicks(),
                      ui::GestureEventDetails(type)) {}
 
-  GestureEventForTest(ui::GestureEventDetails details)
+  explicit GestureEventForTest(ui::GestureEventDetails details)
       : GestureEvent(details.bounding_box().CenterPoint().x(),
                      details.bounding_box().CenterPoint().y(),
                      0,
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index e450ec6..9b0b53d 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -200,7 +200,7 @@
 
 namespace views {
 
-typedef ViewsTestBase ViewTest;
+using ViewTest = ViewsTestBase;
 
 // A derived class for testing purpose.
 class TestView : public View {
@@ -212,7 +212,7 @@
         did_paint_(false),
         native_theme_(nullptr),
         can_process_events_within_subtree_(true) {}
-  ~TestView() override {}
+  ~TestView() override = default;
 
   // Reset all test state
   void Reset() {
@@ -1272,7 +1272,7 @@
 class TestPaintView : public TestView {
  public:
   TestPaintView() : TestView(), canvas_bounds_(gfx::Rect()) {}
-  ~TestPaintView() override {}
+  ~TestPaintView() override = default;
 
   void OnPaint(gfx::Canvas* canvas) override {
     did_paint_ = true;
@@ -2413,7 +2413,7 @@
 class ToplevelWidgetObserverView : public View {
  public:
   ToplevelWidgetObserverView() : toplevel_(nullptr) {}
-  ~ToplevelWidgetObserverView() override {}
+  ~ToplevelWidgetObserverView() override = default;
 
   // View overrides:
   void ViewHierarchyChanged(
@@ -2481,8 +2481,8 @@
 
 class TransformPaintView : public TestView {
  public:
-  TransformPaintView() {}
-  ~TransformPaintView() override {}
+  TransformPaintView() = default;
+  ~TransformPaintView() override = default;
 
   void ClearScheduledPaintRect() {
     scheduled_paint_rect_ = gfx::Rect();
@@ -2721,7 +2721,7 @@
 class VisibleBoundsView : public View {
  public:
   VisibleBoundsView() : received_notification_(false) {}
-  ~VisibleBoundsView() override {}
+  ~VisibleBoundsView() override = default;
 
   bool received_notification() const { return received_notification_; }
   void set_received_notification(bool received) {
@@ -3174,7 +3174,7 @@
       has_remove_details_(false) {
 }
 
-ObserverView::~ObserverView() {}
+ObserverView::~ObserverView() = default;
 
 void ObserverView::ResetTestState() {
   has_add_details_ = false;
@@ -3352,7 +3352,7 @@
   ResetTestState();
 }
 
-WidgetObserverView::~WidgetObserverView() {}
+WidgetObserverView::~WidgetObserverView() = default;
 
 void WidgetObserverView::ResetTestState() {
   added_to_widget_count_ = 0;
@@ -3708,8 +3708,8 @@
 // status.
 class ActiveWidget : public Widget {
  public:
-  ActiveWidget() {}
-  ~ActiveWidget() override {}
+  ActiveWidget() = default;
+  ~ActiveWidget() override = default;
 
   bool IsActive() const override { return true; }
 
@@ -3777,7 +3777,7 @@
   void SetBounds(const gfx::Rect& bounds) override;
 
  protected:
-  ~TestLayerAnimator() override {}
+  ~TestLayerAnimator() override = default;
 
  private:
   gfx::Rect last_bounds_;
@@ -3799,7 +3799,7 @@
  public:
   ViewLayerTest() : widget_(nullptr) {}
 
-  ~ViewLayerTest() override {}
+  ~ViewLayerTest() override = default;
 
   // Returns the Layer used by the RootView.
   ui::Layer* GetRootLayer() {
@@ -4591,9 +4591,9 @@
 
 class ViewLayerPixelCanvasTest : public ViewLayerTest {
  public:
-  ViewLayerPixelCanvasTest() {}
+  ViewLayerPixelCanvasTest() = default;
 
-  ~ViewLayerPixelCanvasTest() override {}
+  ~ViewLayerPixelCanvasTest() override = default;
 
   void SetUpPixelCanvas() override {
     scoped_feature_list_.InitAndEnableFeature(
@@ -4738,8 +4738,9 @@
 
 class TestEventHandler : public ui::EventHandler {
  public:
-  TestEventHandler(TestView* view) : view_(view), had_mouse_event_(false) {}
-  ~TestEventHandler() override {}
+  explicit TestEventHandler(TestView* view)
+      : view_(view), had_mouse_event_(false) {}
+  ~TestEventHandler() override = default;
 
   void OnMouseEvent(ui::MouseEvent* event) override {
     // The |view_| should have received the event first.
@@ -4791,7 +4792,7 @@
 class WidgetWithCustomTheme : public Widget {
  public:
   explicit WidgetWithCustomTheme(ui::NativeTheme* theme) : theme_(theme) {}
-  ~WidgetWithCustomTheme() override {}
+  ~WidgetWithCustomTheme() override = default;
 
   // Widget:
   const ui::NativeTheme* GetNativeTheme() const override { return theme_; }
@@ -4806,7 +4807,7 @@
 class ViewThatAddsViewInOnNativeThemeChanged : public View {
  public:
   ViewThatAddsViewInOnNativeThemeChanged() { SetPaintToLayer(); }
-  ~ViewThatAddsViewInOnNativeThemeChanged() override {}
+  ~ViewThatAddsViewInOnNativeThemeChanged() override = default;
 
   bool on_native_theme_changed_called() const {
     return on_native_theme_changed_called_;
@@ -4910,7 +4911,7 @@
   static constexpr int VIEW_ID_RAISED = 1000;
 
   OrderableView() : View() {}
-  ~OrderableView() override {}
+  ~OrderableView() override = default;
 
   View::Views GetChildrenInZOrder() override {
     View::Views children;
@@ -5014,7 +5015,7 @@
         view_bounds_changed_(nullptr),
         view_reordered_(nullptr) {}
 
-  ~ViewObserverTest() override {}
+  ~ViewObserverTest() override = default;
 
   // ViewObserver:
   void OnChildViewAdded(View* parent, View* child) override {
diff --git a/ui/views/view_unittest_aura.cc b/ui/views/view_unittest_aura.cc
index edbd645..e99fbfcb 100644
--- a/ui/views/view_unittest_aura.cc
+++ b/ui/views/view_unittest_aura.cc
@@ -45,8 +45,8 @@
 
 class ViewAuraTest : public ViewsTestBase {
  public:
-  ViewAuraTest() {}
-  ~ViewAuraTest() override {}
+  ViewAuraTest() = default;
+  ~ViewAuraTest() override = default;
 
   const View::Views& GetViewsWithLayers(Widget* widget) {
     return widget->GetViewsWithLayers();
diff --git a/ui/views/views_test_suite.cc b/ui/views/views_test_suite.cc
index 1a3001c..dbdb4c18 100644
--- a/ui/views/views_test_suite.cc
+++ b/ui/views/views_test_suite.cc
@@ -32,7 +32,7 @@
 ViewsTestSuite::ViewsTestSuite(int argc, char** argv)
     : base::TestSuite(argc, argv), argc_(argc), argv_(argv) {}
 
-ViewsTestSuite::~ViewsTestSuite() {}
+ViewsTestSuite::~ViewsTestSuite() = default;
 
 int ViewsTestSuite::RunTests() {
   return base::LaunchUnitTests(
diff --git a/ui/views/views_test_suite.h b/ui/views/views_test_suite.h
index f186b2c..8673c84 100644
--- a/ui/views/views_test_suite.h
+++ b/ui/views/views_test_suite.h
@@ -7,13 +7,19 @@
 
 #include "base/test/test_suite.h"
 
-#if defined(USE_AURA)
-#include <memory>
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "base/win/scoped_com_initializer.h"
 #endif
 
+#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#include <memory>
+
 namespace aura {
 class Env;
 }
+#endif
 
 namespace views {
 
@@ -42,6 +48,11 @@
   // ViewsTestBase.
   std::unique_ptr<aura::Env> env_;
 #endif
+
+#if defined(OS_WIN)
+  base::win::ScopedCOMInitializer com_initializer_;
+#endif
+
   int argc_;
   char** argv_;
 
diff --git a/ui/views/views_touch_selection_controller_factory_aura.cc b/ui/views/views_touch_selection_controller_factory_aura.cc
index 8bc232f0..8010719 100644
--- a/ui/views/views_touch_selection_controller_factory_aura.cc
+++ b/ui/views/views_touch_selection_controller_factory_aura.cc
@@ -9,8 +9,8 @@
 
 namespace views {
 
-ViewsTouchEditingControllerFactory::ViewsTouchEditingControllerFactory() {
-}
+ViewsTouchEditingControllerFactory::ViewsTouchEditingControllerFactory() =
+    default;
 
 ui::TouchEditingControllerDeprecated*
 ViewsTouchEditingControllerFactory::Create(
diff --git a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
index d4c4cba..898eacde 100644
--- a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
@@ -146,15 +146,13 @@
   if (!*delegate)
     return;
 
-  data->reset(new OSExchangeData(
-      std::make_unique<OSExchangeDataProviderWin>(data_object)));
+  *data = std::make_unique<OSExchangeData>(
+      std::make_unique<OSExchangeDataProviderWin>(data_object));
   location = root_location;
   aura::Window::ConvertPointToTarget(root_window_, target_window_, &location);
-  event->reset(new ui::DropTargetEvent(
-      *(data->get()),
-      gfx::PointF(location),
-      gfx::PointF(root_location),
-      ui::DragDropTypes::DropEffectToDragOperation(effect)));
+  *event = std::make_unique<ui::DropTargetEvent>(
+      *(data->get()), gfx::PointF(location), gfx::PointF(root_location),
+      ui::DragDropTypes::DropEffectToDragOperation(effect));
   (*event)->set_flags(ConvertKeyStateToAuraEventFlags(key_state));
   if (target_window_changed)
     (*delegate)->OnDragEntered(*event->get());
diff --git a/ui/views/widget/desktop_aura/desktop_event_client.cc b/ui/views/widget/desktop_aura/desktop_event_client.cc
index fe85a724..e96b901 100644
--- a/ui/views/widget/desktop_aura/desktop_event_client.cc
+++ b/ui/views/widget/desktop_aura/desktop_event_client.cc
@@ -8,11 +8,9 @@
 
 namespace views {
 
-DesktopEventClient::DesktopEventClient() {
-}
+DesktopEventClient::DesktopEventClient() = default;
 
-DesktopEventClient::~DesktopEventClient() {
-}
+DesktopEventClient::~DesktopEventClient() = default;
 
 bool DesktopEventClient::CanProcessEventsWithinSubtree(
     const aura::Window* window) const {
diff --git a/ui/views/widget/desktop_aura/desktop_focus_rules.cc b/ui/views/widget/desktop_aura/desktop_focus_rules.cc
index d9396d0..46d726b 100644
--- a/ui/views/widget/desktop_aura/desktop_focus_rules.cc
+++ b/ui/views/widget/desktop_aura/desktop_focus_rules.cc
@@ -14,7 +14,7 @@
 DesktopFocusRules::DesktopFocusRules(aura::Window* content_window)
     : content_window_(content_window) {}
 
-DesktopFocusRules::~DesktopFocusRules() {}
+DesktopFocusRules::~DesktopFocusRules() = default;
 
 bool DesktopFocusRules::CanActivateWindow(const aura::Window* window) const {
   if (window && content_window_->GetRootWindow()->Contains(window) &&
diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
index d073133..627cd37 100644
--- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
@@ -15,8 +15,7 @@
 DesktopNativeCursorManager::DesktopNativeCursorManager()
     : cursor_loader_(ui::CursorLoader::Create()) {}
 
-DesktopNativeCursorManager::~DesktopNativeCursorManager() {
-}
+DesktopNativeCursorManager::~DesktopNativeCursorManager() = default;
 
 gfx::NativeCursor DesktopNativeCursorManager::GetInitializedCursor(
     ui::CursorType type) {
diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
index 6f0342d..31cf5781a 100644
--- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
+++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
@@ -61,7 +61,7 @@
       wm::NativeCursorManagerDelegate* delegate) override;
 
   // The set of hosts to notify of changes in cursor state.
-  typedef std::set<aura::WindowTreeHost*> Hosts;
+  using Hosts = std::set<aura::WindowTreeHost*>;
   Hosts hosts_;
 
   std::unique_ptr<ui::CursorLoader> cursor_loader_;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 217b2b0..82819b38 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/trace_event/trace_event.h"
@@ -164,7 +166,7 @@
   DesktopNativeWidgetTopLevelHandler()
       : top_level_widget_(nullptr), child_window_(nullptr) {}
 
-  ~DesktopNativeWidgetTopLevelHandler() override {}
+  ~DesktopNativeWidgetTopLevelHandler() override = default;
 
   Widget* top_level_widget_;
   aura::Window* child_window_;
@@ -216,7 +218,7 @@
  public:
   explicit RootWindowDestructionObserver(DesktopNativeWidgetAura* parent)
     : parent_(parent) {}
-  ~RootWindowDestructionObserver() override {}
+  ~RootWindowDestructionObserver() override = default;
 
  private:
   // Overridden from aura::WindowObserver:
@@ -470,8 +472,8 @@
   // pre target handlers list. This ensures that it handles input events first
   // when modal windows are at the top of the Zorder.
   if (widget_type_ == Widget::InitParams::TYPE_WINDOW)
-    window_modality_controller_.reset(
-        new wm::WindowModalityController(host_->window()));
+    window_modality_controller_ =
+        std::make_unique<wm::WindowModalityController>(host_->window());
 
   // |root_window_event_filter_| must be created before
   // OnWindowTreeHostCreated() is invoked.
@@ -481,7 +483,7 @@
   //             handed way of accomplishing focus.
   // No event filter for aura::Env. Create CompoundEventFilter per
   // WindowEventDispatcher.
-  root_window_event_filter_.reset(new wm::CompoundEventFilter);
+  root_window_event_filter_ = std::make_unique<wm::CompoundEventFilter>();
   host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
 
   use_desktop_native_cursor_manager_ =
@@ -506,7 +508,7 @@
 
   UpdateWindowTransparency();
 
-  capture_client_.reset(new DesktopCaptureClient(host_->window()));
+  capture_client_ = std::make_unique<DesktopCaptureClient>(host_->window());
 
   wm::FocusController* focus_controller =
       new wm::FocusController(new DesktopFocusRules(content_window_));
@@ -530,16 +532,17 @@
 
   host_->AddObserver(this);
 
-  window_parenting_client_.reset(
-      new DesktopNativeWidgetAuraWindowParentingClient(host_->window()));
-  drop_helper_.reset(new DropHelper(GetWidget()->GetRootView()));
+  window_parenting_client_ =
+      std::make_unique<DesktopNativeWidgetAuraWindowParentingClient>(
+          host_->window());
+  drop_helper_ = std::make_unique<DropHelper>(GetWidget()->GetRootView());
   aura::client::SetDragDropDelegate(content_window_, this);
 
   if (params.type != Widget::InitParams::TYPE_TOOLTIP) {
-    tooltip_manager_.reset(new TooltipManagerAura(GetWidget()));
-    tooltip_controller_.reset(
-        new corewm::TooltipController(
-            desktop_window_tree_host_->CreateTooltip()));
+    tooltip_manager_ = std::make_unique<TooltipManagerAura>(GetWidget());
+    tooltip_controller_ = std::make_unique<corewm::TooltipController>(
+
+        desktop_window_tree_host_->CreateTooltip());
     wm::SetTooltipClient(host_->window(), tooltip_controller_.get());
     host_->window()->AddPreTargetHandler(tooltip_controller_.get());
   }
@@ -557,16 +560,16 @@
         GetWidget(), host_->window());
   }
 
-  event_client_.reset(new DesktopEventClient);
+  event_client_ = std::make_unique<DesktopEventClient>();
   aura::client::SetEventClient(host_->window(), event_client_.get());
 
-  shadow_controller_.reset(new wm::ShadowController(
-      wm::GetActivationClient(host_->window()), nullptr));
+  shadow_controller_ = std::make_unique<wm::ShadowController>(
+      wm::GetActivationClient(host_->window()), nullptr);
 
   OnSizeConstraintsChanged();
 
-  window_reorderer_.reset(new WindowReorderer(content_window_,
-      GetWidget()->GetRootView()));
+  window_reorderer_ = std::make_unique<WindowReorderer>(
+      content_window_, GetWidget()->GetRootView());
 }
 
 void DesktopNativeWidgetAura::OnWidgetInitDone() {
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
index c1b6b7b..1ff12e44 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -621,8 +621,8 @@
 // Provides functionality to create a window modal dialog.
 class ModalDialogDelegate : public DialogDelegateView {
  public:
-  ModalDialogDelegate() {}
-  ~ModalDialogDelegate() override {}
+  ModalDialogDelegate() = default;
+  ~ModalDialogDelegate() override = default;
 
   // WidgetDelegate overrides.
   ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_WINDOW; }
diff --git a/ui/views/widget/desktop_aura/desktop_screen_win.cc b/ui/views/widget/desktop_aura/desktop_screen_win.cc
index 56fba6bc..70553b15 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_win.cc
@@ -17,11 +17,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopScreenWin, public:
 
-DesktopScreenWin::DesktopScreenWin() {
-}
+DesktopScreenWin::DesktopScreenWin() = default;
 
-DesktopScreenWin::~DesktopScreenWin() {
-}
+DesktopScreenWin::~DesktopScreenWin() = default;
 
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopScreenWin, display::win::ScreenWin implementation:
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc b/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc
index 86834c4..21788c2 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc
@@ -54,8 +54,8 @@
 
 namespace views {
 
-const int64_t kFirstDisplay = 5321829;
-const int64_t kSecondDisplay = 928310;
+constexpr int64_t kFirstDisplay = 5321829;
+constexpr int64_t kSecondDisplay = 928310;
 
 class DesktopScreenX11Test : public views::ViewsTestBase,
                              public display::DisplayObserver {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index fa8c23b..eff14bc 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -41,7 +41,7 @@
 
 class VIEWS_EXPORT DesktopWindowTreeHost {
  public:
-  virtual ~DesktopWindowTreeHost() {}
+  virtual ~DesktopWindowTreeHost() = default;
 
   static DesktopWindowTreeHost* Create(
       internal::NativeWidgetDelegate* native_widget_delegate,
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index f39115f9..436d837 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -974,7 +974,7 @@
 
 void DesktopWindowTreeHostWin::HandleMenuLoop(bool in_menu_loop) {
   if (in_menu_loop) {
-    tooltip_disabler_.reset(new wm::ScopedTooltipDisabler(window()));
+    tooltip_disabler_ = std::make_unique<wm::ScopedTooltipDisabler>(window());
   } else {
     tooltip_disabler_.reset();
   }
diff --git a/ui/views/widget/desktop_aura/x11_window_event_filter.cc b/ui/views/widget/desktop_aura/x11_window_event_filter.cc
index bd73d72..7602a27e 100644
--- a/ui/views/widget/desktop_aura/x11_window_event_filter.cc
+++ b/ui/views/widget/desktop_aura/x11_window_event_filter.cc
@@ -26,15 +26,15 @@
 
 // These constants are defined in the Extended Window Manager Hints
 // standard...and aren't in any header that I can find.
-const int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT =     0;
-const int k_NET_WM_MOVERESIZE_SIZE_TOP =         1;
-const int k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT =    2;
-const int k_NET_WM_MOVERESIZE_SIZE_RIGHT =       3;
-const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
-const int k_NET_WM_MOVERESIZE_SIZE_BOTTOM =      5;
-const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT =  6;
-const int k_NET_WM_MOVERESIZE_SIZE_LEFT =        7;
-const int k_NET_WM_MOVERESIZE_MOVE =             8;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_TOP = 1;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
+constexpr int k_NET_WM_MOVERESIZE_SIZE_LEFT = 7;
+constexpr int k_NET_WM_MOVERESIZE_MOVE = 8;
 
 }  // namespace
 
diff --git a/ui/views/widget/drop_helper.cc b/ui/views/widget/drop_helper.cc
index 3cc8b29..e941555d 100644
--- a/ui/views/widget/drop_helper.cc
+++ b/ui/views/widget/drop_helper.cc
@@ -27,8 +27,7 @@
 DropHelper::DropHelper(View* root_view)
     : root_view_(root_view), target_view_(nullptr), deepest_view_(nullptr) {}
 
-DropHelper::~DropHelper() {
-}
+DropHelper::~DropHelper() = default;
 
 // static
 void DropHelper::SetDragEnteredCallbackForTesting(
diff --git a/ui/views/widget/native_widget.h b/ui/views/widget/native_widget.h
index ec1a4ec93..722f45a2 100644
--- a/ui/views/widget/native_widget.h
+++ b/ui/views/widget/native_widget.h
@@ -27,7 +27,7 @@
 //
 class VIEWS_EXPORT NativeWidget {
  public:
-  virtual ~NativeWidget() {}
+  virtual ~NativeWidget() = default;
 
  private:
   friend class Widget;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index bec92dca..dc3e7e1 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -243,9 +243,9 @@
           : ws::mojom::EventTargetingPolicy::NONE);
   DCHECK(GetWidget()->GetRootView());
   if (params.type != Widget::InitParams::TYPE_TOOLTIP)
-    tooltip_manager_.reset(new views::TooltipManagerAura(GetWidget()));
+    tooltip_manager_ = std::make_unique<views::TooltipManagerAura>(GetWidget());
 
-  drop_helper_.reset(new DropHelper(GetWidget()->GetRootView()));
+  drop_helper_ = std::make_unique<DropHelper>(GetWidget()->GetRootView());
   if (params.type != Widget::InitParams::TYPE_TOOLTIP &&
       params.type != Widget::InitParams::TYPE_POPUP) {
     aura::client::SetDragDropDelegate(window_, this);
@@ -258,8 +258,8 @@
 
   wm::SetActivationDelegate(window_, this);
 
-  window_reorderer_.reset(new WindowReorderer(window_,
-      GetWidget()->GetRootView()));
+  window_reorderer_ =
+      std::make_unique<WindowReorderer>(window_, GetWidget()->GetRootView());
 }
 
 void NativeWidgetAura::OnWidgetInitDone() {}
diff --git a/ui/views/widget/native_widget_aura_interactive_uitest.cc b/ui/views/widget/native_widget_aura_interactive_uitest.cc
index 651cff7..c50bcca 100644
--- a/ui/views/widget/native_widget_aura_interactive_uitest.cc
+++ b/ui/views/widget/native_widget_aura_interactive_uitest.cc
@@ -19,8 +19,8 @@
 
 class TestFocusRules : public wm::BaseFocusRules {
  public:
-  TestFocusRules() {}
-  ~TestFocusRules() override {}
+  TestFocusRules() = default;
+  ~TestFocusRules() override = default;
 
   void set_can_activate(bool can_activate) { can_activate_ = can_activate; }
 
diff --git a/ui/views/widget/native_widget_aura_unittest.cc b/ui/views/widget/native_widget_aura_unittest.cc
index 98510e62..e9b54ef 100644
--- a/ui/views/widget/native_widget_aura_unittest.cc
+++ b/ui/views/widget/native_widget_aura_unittest.cc
@@ -44,8 +44,8 @@
 // activatability so that the focus rules can be tested.
 class TestFocusRules : public wm::BaseFocusRules {
  public:
-  TestFocusRules() {}
-  ~TestFocusRules() override {}
+  TestFocusRules() = default;
+  ~TestFocusRules() override = default;
 
   void set_can_activate(bool can_activate) { can_activate_ = can_activate; }
 
@@ -66,8 +66,8 @@
 
 class NativeWidgetAuraTest : public aura::test::AuraTestBase {
  public:
-  NativeWidgetAuraTest() {}
-  ~NativeWidgetAuraTest() override {}
+  NativeWidgetAuraTest() = default;
+  ~NativeWidgetAuraTest() override = default;
 
   TestFocusRules* test_focus_rules() { return test_focus_rules_; }
 
@@ -75,7 +75,8 @@
   void SetUp() override {
     AuraTestBase::SetUp();
     test_focus_rules_ = new TestFocusRules;
-    focus_controller_.reset(new wm::FocusController(test_focus_rules_));
+    focus_controller_ =
+        std::make_unique<wm::FocusController>(test_focus_rules_);
     wm::SetActivationClient(root_window(), focus_controller_.get());
     host()->SetBoundsInPixels(gfx::Rect(640, 480));
   }
@@ -220,8 +221,8 @@
 
 class TestLayoutManagerBase : public aura::LayoutManager {
  public:
-  TestLayoutManagerBase() {}
-  ~TestLayoutManagerBase() override {}
+  TestLayoutManagerBase() = default;
+  ~TestLayoutManagerBase() override = default;
 
   // aura::LayoutManager:
   void OnWindowResized() override {}
@@ -240,8 +241,8 @@
 // Used by ShowMaximizedDoesntBounceAround. See it for details.
 class MaximizeLayoutManager : public TestLayoutManagerBase {
  public:
-  MaximizeLayoutManager() {}
-  ~MaximizeLayoutManager() override {}
+  MaximizeLayoutManager() = default;
+  ~MaximizeLayoutManager() override = default;
 
  private:
   // aura::LayoutManager:
@@ -303,7 +304,7 @@
 class PropertyTestLayoutManager : public TestLayoutManagerBase {
  public:
   PropertyTestLayoutManager() : added_(false) {}
-  ~PropertyTestLayoutManager() override {}
+  ~PropertyTestLayoutManager() override = default;
 
   bool added() const { return added_; }
 
@@ -325,7 +326,7 @@
 class PropertyTestWidgetDelegate : public views::WidgetDelegate {
  public:
   explicit PropertyTestWidgetDelegate(Widget* widget) : widget_(widget) {}
-  ~PropertyTestWidgetDelegate() override {}
+  ~PropertyTestWidgetDelegate() override = default;
 
  private:
   // views::WidgetDelegate:
@@ -603,7 +604,7 @@
 class MoveTestWidgetDelegate : public WidgetDelegateView {
  public:
   MoveTestWidgetDelegate() : got_move_(false) {}
-  ~MoveTestWidgetDelegate() override {}
+  ~MoveTestWidgetDelegate() override = default;
 
   void ClearGotMove() { got_move_ = false; }
   bool got_move() const { return got_move_; }
diff --git a/ui/views/widget/native_widget_delegate.h b/ui/views/widget/native_widget_delegate.h
index 9dc91d0..8965822 100644
--- a/ui/views/widget/native_widget_delegate.h
+++ b/ui/views/widget/native_widget_delegate.h
@@ -38,7 +38,7 @@
 //
 class VIEWS_EXPORT NativeWidgetDelegate {
  public:
-  virtual ~NativeWidgetDelegate() {}
+  virtual ~NativeWidgetDelegate() = default;
 
   // Returns true if the window is modal.
   virtual bool IsModal() const = 0;
diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h
index 3e81517..e594c69 100644
--- a/ui/views/widget/native_widget_private.h
+++ b/ui/views/widget/native_widget_private.h
@@ -46,7 +46,7 @@
 //
 class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
  public:
-  ~NativeWidgetPrivate() override {}
+  ~NativeWidgetPrivate() override = default;
 
   // Creates an appropriate default NativeWidgetPrivate implementation for the
   // current OS/circumstance.
diff --git a/ui/views/widget/native_widget_unittest.cc b/ui/views/widget/native_widget_unittest.cc
index d7aa5ba..2affa7fa 100644
--- a/ui/views/widget/native_widget_unittest.cc
+++ b/ui/views/widget/native_widget_unittest.cc
@@ -35,8 +35,8 @@
 
 class NativeWidgetTest : public ViewsTestBase {
  public:
-  NativeWidgetTest() {}
-  ~NativeWidgetTest() override {}
+  NativeWidgetTest() = default;
+  ~NativeWidgetTest() override = default;
 
   internal::NativeWidgetPrivate* CreateNativeWidgetOfType(
       Widget::InitParams::Type type) {
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index 109328ed..7470786 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -25,7 +25,7 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
-typedef ui::EventDispatchDetails DispatchDetails;
+using DispatchDetails = ui::EventDispatchDetails;
 
 namespace views {
 namespace internal {
@@ -48,7 +48,7 @@
     SetType(type);
   }
 
-  ~MouseEnterExitEvent() override {}
+  ~MouseEnterExitEvent() override = default;
 };
 
 }  // namespace
@@ -106,7 +106,7 @@
   PostEventDispatchHandler()
       : touch_dnd_enabled_(::switches::IsTouchDragDropEnabled()) {
   }
-  ~PostEventDispatchHandler() override {}
+  ~PostEventDispatchHandler() override = default;
 
  private:
   // Overridden from ui::EventHandler:
diff --git a/ui/views/widget/root_view_targeter.cc b/ui/views/widget/root_view_targeter.cc
index 386d940..1871da4c 100644
--- a/ui/views/widget/root_view_targeter.cc
+++ b/ui/views/widget/root_view_targeter.cc
@@ -17,8 +17,7 @@
     : ViewTargeter(delegate), root_view_(root_view) {
 }
 
-RootViewTargeter::~RootViewTargeter() {
-}
+RootViewTargeter::~RootViewTargeter() = default;
 
 View* RootViewTargeter::FindTargetForGestureEvent(
     View* root,
diff --git a/ui/views/widget/root_view_unittest.cc b/ui/views/widget/root_view_unittest.cc
index ca1aa1d..1e298b34 100644
--- a/ui/views/widget/root_view_unittest.cc
+++ b/ui/views/widget/root_view_unittest.cc
@@ -24,7 +24,7 @@
 class DeleteOnKeyEventView : public View {
  public:
   explicit DeleteOnKeyEventView(bool* set_on_key) : set_on_key_(set_on_key) {}
-  ~DeleteOnKeyEventView() override {}
+  ~DeleteOnKeyEventView() override = default;
 
   bool OnKeyPressed(const ui::KeyEvent& event) override {
     *set_on_key_ = true;
@@ -80,7 +80,7 @@
       : show_context_menu_calls_(0),
         menu_source_view_(nullptr),
         menu_source_type_(ui::MENU_SOURCE_NONE) {}
-  ~TestContextMenuController() override {}
+  ~TestContextMenuController() override = default;
 
   int show_context_menu_calls() const { return show_context_menu_calls_; }
   View* menu_source_view() const { return menu_source_view_; }
@@ -169,10 +169,9 @@
 // View which handles all gesture events.
 class GestureHandlingView : public View {
  public:
-  GestureHandlingView() {
-  }
+  GestureHandlingView() = default;
 
-  ~GestureHandlingView() override {}
+  ~GestureHandlingView() override = default;
 
   void OnGestureEvent(ui::GestureEvent* event) override { event->SetHandled(); }
 
@@ -451,7 +450,7 @@
       : widget_(widget) {
   }
 
-  ~DeleteWidgetOnMouseExit() override {}
+  ~DeleteWidgetOnMouseExit() override = default;
 
   void OnMouseExited(const ui::MouseEvent& event) override {
     delete widget_;
@@ -550,7 +549,7 @@
 namespace {
 class RootViewTestDialogDelegate : public DialogDelegateView {
  public:
-  RootViewTestDialogDelegate() {}
+  RootViewTestDialogDelegate() = default;
 
   int layout_count() const { return layout_count_; }
 
diff --git a/ui/views/widget/tooltip_manager.h b/ui/views/widget/tooltip_manager.h
index 4c27c36..2403a81 100644
--- a/ui/views/widget/tooltip_manager.h
+++ b/ui/views/widget/tooltip_manager.h
@@ -33,8 +33,8 @@
   // shown.
   static const char kGroupingPropertyKey[];
 
-  TooltipManager() {}
-  virtual ~TooltipManager() {}
+  TooltipManager() = default;
+  virtual ~TooltipManager() = default;
 
   // Returns the maximum width of the tooltip. |point| gives the location
   // the tooltip is to be displayed on in screen coordinates.
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 8a26761..a6cda6e 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -98,7 +98,7 @@
  public:
   explicit DefaultWidgetDelegate(Widget* widget) : widget_(widget) {
   }
-  ~DefaultWidgetDelegate() override {}
+  ~DefaultWidgetDelegate() override = default;
 
   // Overridden from WidgetDelegate:
   void DeleteDelegate() override { delete this; }
@@ -147,8 +147,7 @@
 
 Widget::InitParams::InitParams(const InitParams& other) = default;
 
-Widget::InitParams::~InitParams() {
-}
+Widget::InitParams::~InitParams() = default;
 
 bool Widget::InitParams::CanActivate() const {
   if (activatable != InitParams::ACTIVATABLE_DEFAULT)
@@ -337,7 +336,7 @@
   ownership_ = params.ownership;
   native_widget_ = CreateNativeWidget(params, this)->AsNativeWidgetPrivate();
   root_view_.reset(CreateRootView());
-  default_theme_provider_.reset(new ui::DefaultThemeProvider);
+  default_theme_provider_ = std::make_unique<ui::DefaultThemeProvider>();
   native_widget_->InitNativeWidget(params);
   if (params.type == InitParams::TYPE_MENU)
     is_mouse_button_pressed_ = native_widget_->IsMouseButtonDown();
diff --git a/ui/views/widget/widget_delegate.cc b/ui/views/widget/widget_delegate.cc
index 4a5a4b0..12be1ad4 100644
--- a/ui/views/widget/widget_delegate.cc
+++ b/ui/views/widget/widget_delegate.cc
@@ -211,8 +211,7 @@
   set_owned_by_client();
 }
 
-WidgetDelegateView::~WidgetDelegateView() {
-}
+WidgetDelegateView::~WidgetDelegateView() = default;
 
 void WidgetDelegateView::DeleteDelegate() {
   delete this;
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc
index c674d13..3ade17fb 100644
--- a/ui/views/widget/widget_interactive_uitest.cc
+++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -79,8 +79,8 @@
 // A view that does a capture on ui::ET_GESTURE_TAP_DOWN events.
 class GestureCaptureView : public View {
  public:
-  GestureCaptureView() {}
-  ~GestureCaptureView() override {}
+  GestureCaptureView() = default;
+  ~GestureCaptureView() override = default;
 
  private:
   // View:
@@ -103,7 +103,7 @@
         exited_(0),
         pressed_(0) {
   }
-  ~MouseView() override {}
+  ~MouseView() override = default;
 
   bool OnMousePressed(const ui::MouseEvent& event) override {
     pressed_++;
@@ -146,7 +146,7 @@
   explicit NestedLoopCaptureView(Widget* widget)
       : run_loop_(base::RunLoop::Type::kNestableTasksAllowed),
         widget_(widget) {}
-  ~NestedLoopCaptureView() override {}
+  ~NestedLoopCaptureView() override = default;
 
   base::OnceClosure GetQuitClosure() { return run_loop_.QuitClosure(); }
 
@@ -383,7 +383,7 @@
 
 class TouchEventHandler : public ui::EventHandler {
  public:
-  TouchEventHandler(Widget* widget) : widget_(widget) {
+  explicit TouchEventHandler(Widget* widget) : widget_(widget) {
     widget_->GetNativeWindow()->GetHost()->window()->AddPreTargetHandler(this);
   }
 
@@ -850,7 +850,7 @@
   WidgetActivationTest()
       : active_(false) {}
 
-  ~WidgetActivationTest() override {}
+  ~WidgetActivationTest() override = default;
 
   bool OnNativeWidgetActivationChanged(bool active) override {
     active_ = active;
@@ -1015,7 +1015,7 @@
 class ModalDialogDelegate : public DialogDelegateView {
  public:
   explicit ModalDialogDelegate(ui::ModalType type) : type_(type) {}
-  ~ModalDialogDelegate() override {}
+  ~ModalDialogDelegate() override = default;
 
   // WidgetDelegate overrides.
   ui::ModalType GetModalType() const override { return type_; }
@@ -1781,7 +1781,7 @@
 class CaptureOnActivationObserver : public WidgetObserver {
  public:
   CaptureOnActivationObserver() : activation_observed_(false) {}
-  ~CaptureOnActivationObserver() override {}
+  ~CaptureOnActivationObserver() override = default;
 
   // WidgetObserver:
   void OnWidgetActivationChanged(Widget* widget, bool active) override {
@@ -1844,7 +1844,7 @@
 class MouseEventTrackingWidget : public Widget {
  public:
   MouseEventTrackingWidget() : got_mouse_event_(false) {}
-  ~MouseEventTrackingWidget() override {}
+  ~MouseEventTrackingWidget() override = default;
 
   bool GetAndClearGotMouseEvent() {
     bool value = got_mouse_event_;
@@ -1908,7 +1908,7 @@
 
 class WidgetInputMethodInteractiveTest : public DesktopWidgetTestInteractive {
  public:
-  WidgetInputMethodInteractiveTest() {}
+  WidgetInputMethodInteractiveTest() = default;
 
   // testing::Test:
   void SetUp() override {
diff --git a/ui/views/widget/widget_observer.h b/ui/views/widget/widget_observer.h
index 698ee1e..51adacf 100644
--- a/ui/views/widget/widget_observer.h
+++ b/ui/views/widget/widget_observer.h
@@ -50,7 +50,7 @@
                                      const gfx::Rect& new_bounds) {}
 
  protected:
-  ~WidgetObserver() override {}
+  ~WidgetObserver() override = default;
 };
 
 }  // namespace views
diff --git a/ui/views/widget/widget_removals_observer.h b/ui/views/widget/widget_removals_observer.h
index d704607..9e6f24e 100644
--- a/ui/views/widget/widget_removals_observer.h
+++ b/ui/views/widget/widget_removals_observer.h
@@ -26,7 +26,7 @@
   virtual void OnWillRemoveView(Widget* widget, View* view) {}
 
  protected:
-  virtual ~WidgetRemovalsObserver() {}
+  virtual ~WidgetRemovalsObserver() = default;
 };
 
 }  // namespace views
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index 4d9000f2..f70f193c 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -75,10 +75,10 @@
 
 class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
  public:
-  TestBubbleDialogDelegateView(View* anchor)
+  explicit TestBubbleDialogDelegateView(View* anchor)
       : BubbleDialogDelegateView(anchor, BubbleBorder::NONE),
         reset_controls_called_(false) {}
-  ~TestBubbleDialogDelegateView() override {}
+  ~TestBubbleDialogDelegateView() override = default;
 
   bool ShouldShowCloseButton() const override {
     reset_controls_called_ = true;
@@ -94,8 +94,8 @@
 // gesture events and ui::ET_SCROLL events.
 class ScrollableEventCountView : public EventCountView {
  public:
-  ScrollableEventCountView() {}
-  ~ScrollableEventCountView() override {}
+  ScrollableEventCountView() = default;
+  ~ScrollableEventCountView() override = default;
 
  private:
   // Overridden from ui::EventHandler:
@@ -126,7 +126,7 @@
 class MinimumSizeFrameView : public NativeFrameView {
  public:
   explicit MinimumSizeFrameView(Widget* frame): NativeFrameView(frame) {}
-  ~MinimumSizeFrameView() override {}
+  ~MinimumSizeFrameView() override = default;
 
  private:
   // Overridden from View:
@@ -139,8 +139,8 @@
 // it receives.
 class EventCountHandler : public ui::EventHandler {
  public:
-  EventCountHandler() {}
-  ~EventCountHandler() override {}
+  EventCountHandler() = default;
+  ~EventCountHandler() override = default;
 
   int GetEventCount(ui::EventType type) {
     return event_count_[type];
@@ -299,8 +299,8 @@
 // A WidgetTest that supplies a toplevel widget for NativeWidget to parent to.
 class WidgetOwnershipTest : public WidgetTest {
  public:
-  WidgetOwnershipTest() {}
-  ~WidgetOwnershipTest() override {}
+  WidgetOwnershipTest() = default;
+  ~WidgetOwnershipTest() override = default;
 
   void SetUp() override {
     WidgetTest::SetUp();
@@ -765,7 +765,7 @@
       : TestWidgetObserver(current_active_widget),
         widget_to_activate_(widget_to_activate) {}
 
-  ~WidgetActivationForwarder() override {}
+  ~WidgetActivationForwarder() override = default;
 
  private:
   // WidgetObserver overrides:
@@ -789,7 +789,7 @@
  public:
   explicit WidgetCloseCounter(Widget* widget) : TestWidgetObserver(widget) {}
 
-  ~WidgetCloseCounter() override {}
+  ~WidgetCloseCounter() override = default;
 
   int close_count() const { return close_count_; }
 
@@ -1746,7 +1746,7 @@
 // ui::EventHandler which handles all mouse press events.
 class MousePressEventConsumer : public ui::EventHandler {
  public:
-  MousePressEventConsumer() {}
+  MousePressEventConsumer() = default;
 
  private:
   // ui::EventHandler:
@@ -1826,7 +1826,7 @@
 // proceeds to take capture.
 class CaptureEventConsumer : public ui::EventHandler {
  public:
-  CaptureEventConsumer(Widget* widget)
+  explicit CaptureEventConsumer(Widget* widget)
       : event_count_view_(new EventCountView()), widget_(widget) {}
   ~CaptureEventConsumer() override { widget_->CloseNow(); }
 
@@ -2140,7 +2140,7 @@
 // See description of RunGetNativeThemeFromDestructor() for details.
 class GetNativeThemeFromDestructorView : public WidgetDelegateView {
  public:
-  GetNativeThemeFromDestructorView() {}
+  GetNativeThemeFromDestructorView() = default;
   ~GetNativeThemeFromDestructorView() override { VerifyNativeTheme(); }
 
  private:
@@ -2205,7 +2205,7 @@
 class AnimationEndObserver : public ui::ImplicitAnimationObserver {
  public:
   AnimationEndObserver() : animation_completed_(false) {}
-  ~AnimationEndObserver() override {}
+  ~AnimationEndObserver() override = default;
 
   bool animation_completed() const { return animation_completed_; }
 
@@ -2221,8 +2221,8 @@
 // An observer that registers the bounds of a widget on destruction.
 class WidgetBoundsObserver : public WidgetObserver {
  public:
-  WidgetBoundsObserver() {}
-  ~WidgetBoundsObserver() override {}
+  WidgetBoundsObserver() = default;
+  ~WidgetBoundsObserver() override = default;
 
   gfx::Rect bounds() { return bounds_; }
 
@@ -2924,8 +2924,8 @@
 // of that View.
 class GestureLocationView : public EventCountView {
  public:
-  GestureLocationView() {}
-  ~GestureLocationView() override {}
+  GestureLocationView() = default;
+  ~GestureLocationView() override = default;
 
   void set_expected_location(gfx::Point expected_location) {
     expected_location_ = expected_location;
@@ -3300,7 +3300,7 @@
  public:
   explicit FullscreenAwareFrame(views::Widget* widget)
       : widget_(widget), fullscreen_layout_called_(false) {}
-  ~FullscreenAwareFrame() override {}
+  ~FullscreenAwareFrame() override = default;
 
   // views::NonClientFrameView overrides:
   gfx::Rect GetBoundsForClientView() const override { return gfx::Rect(); }
@@ -3356,8 +3356,8 @@
 // OnWindowDestroying.
 class IsActiveFromDestroyObserver : public WidgetObserver {
  public:
-  IsActiveFromDestroyObserver() {}
-  ~IsActiveFromDestroyObserver() override {}
+  IsActiveFromDestroyObserver() = default;
+  ~IsActiveFromDestroyObserver() override = default;
   void OnWidgetDestroying(Widget* widget) override { widget->IsActive(); }
 
  private:
@@ -3719,8 +3719,8 @@
 
 class TestWidgetRemovalsObserver : public WidgetRemovalsObserver {
  public:
-  TestWidgetRemovalsObserver() {}
-  ~TestWidgetRemovalsObserver() override {}
+  TestWidgetRemovalsObserver() = default;
+  ~TestWidgetRemovalsObserver() override = default;
 
   void OnWillRemoveView(Widget* widget, View* view) override {
     removed_views_.insert(view);
@@ -3963,7 +3963,7 @@
 class ModalDialogDelegate : public DialogDelegateView {
 public:
   explicit ModalDialogDelegate(ui::ModalType type) : type_(type) {}
-  ~ModalDialogDelegate() override {}
+  ~ModalDialogDelegate() override = default;
 
   // WidgetDelegate overrides.
   ui::ModalType GetModalType() const override { return type_; }
@@ -4081,7 +4081,7 @@
                       Widget::InitParams::TYPE_TOOLTIP,
                       Widget::InitParams::TYPE_BUBBLE,
                       Widget::InitParams::TYPE_DRAG} {}
-  ~CompositingWidgetTest() override {}
+  ~CompositingWidgetTest() override = default;
 
   void CheckAllWidgetsForOpacity(
       const Widget::InitParams::WindowOpacity opacity) {
diff --git a/ui/views/widget/window_reorderer_unittest.cc b/ui/views/widget/window_reorderer_unittest.cc
index 09ae69e..0417e54 100644
--- a/ui/views/widget/window_reorderer_unittest.cc
+++ b/ui/views/widget/window_reorderer_unittest.cc
@@ -48,7 +48,7 @@
   return names;
 }
 
-typedef aura::test::AuraTestBase WindowReordererTest;
+using WindowReordererTest = aura::test::AuraTestBase;
 
 // Test that views with layers and views with associated windows are reordered
 // according to the view hierarchy.
diff --git a/ui/views/win/fullscreen_handler.cc b/ui/views/win/fullscreen_handler.cc
index eba915ea..2cb62e6f 100644
--- a/ui/views/win/fullscreen_handler.cc
+++ b/ui/views/win/fullscreen_handler.cc
@@ -19,8 +19,7 @@
 
 FullscreenHandler::FullscreenHandler() : hwnd_(nullptr), fullscreen_(false) {}
 
-FullscreenHandler::~FullscreenHandler() {
-}
+FullscreenHandler::~FullscreenHandler() = default;
 
 void FullscreenHandler::SetFullscreen(bool fullscreen) {
   if (fullscreen_ == fullscreen)
@@ -61,7 +60,7 @@
   // for several frames, which looks worse than doing other updates
   // non-atomically.
   if (!ui::win::IsAeroGlassEnabled())
-    visibility.reset(new ScopedFullscreenVisibility(hwnd_));
+    visibility = std::make_unique<ScopedFullscreenVisibility>(hwnd_);
 
   // Save current window state if not already fullscreen.
   if (!fullscreen_) {
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 42718187..3046987 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -222,7 +222,7 @@
 }
 
 // The thickness of an auto-hide taskbar in pixels.
-const int kAutoHideTaskbarThicknessPx = 2;
+constexpr int kAutoHideTaskbarThicknessPx = 2;
 
 bool IsTopLevelWindow(HWND window) {
   long style = ::GetWindowLong(window, GWL_STYLE);
@@ -273,14 +273,14 @@
   }
 }
 
-const int kTouchDownContextResetTimeout = 500;
+constexpr int kTouchDownContextResetTimeout = 500;
 
 // Windows does not flag synthesized mouse messages from touch or pen in all
 // cases. This causes us grief as we don't want to process touch and mouse
 // messages concurrently. Hack as per msdn is to check if the time difference
 // between the touch/pen message and the mouse move is within 500 ms and at the
 // same location as the cursor.
-const int kSynthesizedMouseMessagesTimeDifference = 500;
+constexpr int kSynthesizedMouseMessagesTimeDifference = 500;
 
 }  // namespace
 
@@ -438,9 +438,9 @@
       enable_child_window_dpi_message_func(hwnd(), TRUE);
   }
 
-  prop_window_target_.reset(new ui::ViewProp(hwnd(),
-                            ui::WindowEventTarget::kWin32InputEventTarget,
-                            static_cast<ui::WindowEventTarget*>(this)));
+  prop_window_target_ = std::make_unique<ui::ViewProp>(
+      hwnd(), ui::WindowEventTarget::kWin32InputEventTarget,
+      static_cast<ui::WindowEventTarget*>(this));
   DCHECK(delegate_->GetHWNDMessageDelegateInputMethod());
   delegate_->GetHWNDMessageDelegateInputMethod()->AddObserver(this);
 
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index 925996e3..3f0c9e2 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -60,13 +60,13 @@
 // window and paint the standard caption/title over the top of the custom one.
 // So we need to handle these messages in CustomFrameWindow to prevent this
 // from happening.
-const int WM_NCUAHDRAWCAPTION = 0xAE;
-const int WM_NCUAHDRAWFRAME = 0xAF;
+constexpr int WM_NCUAHDRAWCAPTION = 0xAE;
+constexpr int WM_NCUAHDRAWFRAME = 0xAF;
 
 // The HWNDMessageHandler sends this message to itself on
 // WM_WINDOWPOSCHANGING. It's used to inform the client if a
 // WM_WINDOWPOSCHANGED won't be received.
-const int WM_WINDOWSIZINGFINISHED = WM_USER;
+constexpr int WM_WINDOWSIZINGFINISHED = WM_USER;
 
 // An object that handles messages for a HWND that implements the views
 // "Custom Frame" look. The purpose of this class is to isolate the windows-
@@ -180,7 +180,7 @@
   bool is_translucent() const { return is_translucent_; }
 
  private:
-  typedef std::set<DWORD> TouchIDs;
+  using TouchIDs = std::set<DWORD>;
   enum class DwmFrameState { OFF, ON };
 
   // Overridden from WindowImpl:
@@ -494,7 +494,7 @@
   // Receives Windows Session Change notifications.
   void OnSessionChange(WPARAM status_code);
 
-  typedef std::vector<ui::TouchEvent> TouchEvents;
+  using TouchEvents = std::vector<ui::TouchEvent>;
   // Helper to handle the list of touch events passed in. We need this because
   // touch events on windows don't fire if we enter a modal loop in the context
   // of a touch event.
diff --git a/ui/views/win/hwnd_message_handler_delegate.h b/ui/views/win/hwnd_message_handler_delegate.h
index a3c4e34..3b06661e 100644
--- a/ui/views/win/hwnd_message_handler_delegate.h
+++ b/ui/views/win/hwnd_message_handler_delegate.h
@@ -266,7 +266,7 @@
   virtual void HandleWindowScaleFactorChanged(float window_scale_factor) = 0;
 
  protected:
-  virtual ~HWNDMessageHandlerDelegate() {}
+  virtual ~HWNDMessageHandlerDelegate() = default;
 };
 
 }  // namespace views
diff --git a/ui/views/win/pen_event_processor.cc b/ui/views/win/pen_event_processor.cc
index 67ee69fc..6e8f488 100644
--- a/ui/views/win/pen_event_processor.cc
+++ b/ui/views/win/pen_event_processor.cc
@@ -28,7 +28,7 @@
     : id_generator_(id_generator),
       direct_manipulation_enabled_(direct_manipulation_enabled) {}
 
-PenEventProcessor::~PenEventProcessor() {}
+PenEventProcessor::~PenEventProcessor() = default;
 
 std::unique_ptr<ui::Event> PenEventProcessor::GenerateEvent(
     UINT message,
diff --git a/ui/views/window/client_view.h b/ui/views/window/client_view.h
index 1a5d5ca..c0b4e5b 100644
--- a/ui/views/window/client_view.h
+++ b/ui/views/window/client_view.h
@@ -30,7 +30,7 @@
   // |widget|, |contents_view| must be valid if you want the initial size of
   // the widget to be based on |contents_view|'s preferred size.
   ClientView(Widget* widget, View* contents_view);
-  ~ClientView() override {}
+  ~ClientView() override = default;
 
   // Manual RTTI ftw.
   virtual DialogClientView* AsDialogClientView();
diff --git a/ui/views/window/custom_frame_view.cc b/ui/views/window/custom_frame_view.cc
index 15ad371..ef6a381 100644
--- a/ui/views/window/custom_frame_view.cc
+++ b/ui/views/window/custom_frame_view.cc
@@ -40,30 +40,30 @@
 
 // The frame border is only visible in restored mode and is hardcoded to 4 px on
 // each side regardless of the system window border size.
-const int kFrameBorderThickness = 4;
+constexpr int kFrameBorderThickness = 4;
 // In the window corners, the resize areas don't actually expand bigger, but the
 // 16 px at the end of each edge triggers diagonal resizing.
-const int kResizeAreaCornerSize = 16;
+constexpr int kResizeAreaCornerSize = 16;
 // The titlebar never shrinks too short to show the caption button plus some
 // padding below it.
-const int kCaptionButtonHeightWithPadding = 19;
+constexpr int kCaptionButtonHeightWithPadding = 19;
 // The titlebar has a 2 px 3D edge along the top and bottom.
-const int kTitlebarTopAndBottomEdgeThickness = 2;
+constexpr int kTitlebarTopAndBottomEdgeThickness = 2;
 // The icon is inset 2 px from the left frame border.
-const int kIconLeftSpacing = 2;
+constexpr int kIconLeftSpacing = 2;
 // The space between the window icon and the title text.
-const int kTitleIconOffsetX = 4;
+constexpr int kTitleIconOffsetX = 4;
 // The space between the title text and the caption buttons.
-const int kTitleCaptionSpacing = 5;
+constexpr int kTitleCaptionSpacing = 5;
 
 #if defined(OS_CHROMEOS)
 // Chrome OS uses a dark gray.
-const SkColor kDefaultColorFrame = SkColorSetRGB(109, 109, 109);
-const SkColor kDefaultColorFrameInactive = SkColorSetRGB(176, 176, 176);
+constexpr SkColor kDefaultColorFrame = SkColorSetRGB(109, 109, 109);
+constexpr SkColor kDefaultColorFrameInactive = SkColorSetRGB(176, 176, 176);
 #else
 // Windows and Linux use a blue.
-const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201);
-const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228);
+constexpr SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201);
+constexpr SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228);
 #endif
 
 const gfx::FontList& GetTitleFontList() {
@@ -95,8 +95,7 @@
       minimum_title_bar_x_(0),
       maximum_title_bar_x_(-1) {}
 
-CustomFrameView::~CustomFrameView() {
-}
+CustomFrameView::~CustomFrameView() = default;
 
 void CustomFrameView::Init(Widget* frame) {
   frame_ = frame;
@@ -323,7 +322,7 @@
   return display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYSMICON);
 #else
   // The icon never shrinks below 16 px on a side.
-  const int kIconMinimumSize = 16;
+  constexpr int kIconMinimumSize = 16;
   return std::max(GetTitleFontList().GetHeight(), kIconMinimumSize);
 #endif
 }
diff --git a/ui/views/window/custom_frame_view_unittest.cc b/ui/views/window/custom_frame_view_unittest.cc
index 403f3b5..da08cbd0 100644
--- a/ui/views/window/custom_frame_view_unittest.cc
+++ b/ui/views/window/custom_frame_view_unittest.cc
@@ -26,7 +26,7 @@
   MinimizeAndMaximizeStateControlDelegate()
         : can_maximize_(true),
           can_minimize_(true) {}
-  ~MinimizeAndMaximizeStateControlDelegate() override {}
+  ~MinimizeAndMaximizeStateControlDelegate() override = default;
 
   void set_can_maximize(bool can_maximize) {
     can_maximize_ = can_maximize;
@@ -51,8 +51,8 @@
 
 class CustomFrameViewTest : public ViewsTestBase {
  public:
-  CustomFrameViewTest() {}
-  ~CustomFrameViewTest() override {}
+  CustomFrameViewTest() = default;
+  ~CustomFrameViewTest() override = default;
 
   CustomFrameView* custom_frame_view() {
     return custom_frame_view_;
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
index 48a7d15..068aac6 100644
--- a/ui/views/window/dialog_client_view.cc
+++ b/ui/views/window/dialog_client_view.cc
@@ -30,7 +30,7 @@
 
 // The group used by the buttons.  This name is chosen voluntarily big not to
 // conflict with other groups that could be in the dialog content.
-const int kButtonGroup = 6666;
+constexpr int kButtonGroup = 6666;
 
 // Returns true if the given view should be shown (i.e. exists and is
 // visible).
diff --git a/ui/views/window/dialog_client_view_unittest.cc b/ui/views/window/dialog_client_view_unittest.cc
index 09c04b41..403fefea 100644
--- a/ui/views/window/dialog_client_view_unittest.cc
+++ b/ui/views/window/dialog_client_view_unittest.cc
@@ -5,6 +5,7 @@
 #include "ui/views/window/dialog_client_view.h"
 
 #include <map>
+#include <memory>
 
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
@@ -32,7 +33,7 @@
 class DialogClientViewTest : public test::WidgetTest,
                              public DialogDelegateView {
  public:
-  DialogClientViewTest() {}
+  DialogClientViewTest() = default;
 
   // testing::Test:
   void SetUp() override {
@@ -123,7 +124,7 @@
   // Sets the extra view padding.
   void SetExtraViewPadding(int padding) {
     DCHECK(!extra_view_padding_);
-    extra_view_padding_.reset(new int(padding));
+    extra_view_padding_ = std::make_unique<int>(padding);
     DialogModelChanged();
   }
 
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc
index 5d76b48e..e6690ce5 100644
--- a/ui/views/window/dialog_delegate.cc
+++ b/ui/views/window/dialog_delegate.cc
@@ -277,7 +277,7 @@
   UMA_HISTOGRAM_BOOLEAN("Dialog.DialogDelegateView.Create", true);
 }
 
-DialogDelegateView::~DialogDelegateView() {}
+DialogDelegateView::~DialogDelegateView() = default;
 
 void DialogDelegateView::DeleteDelegate() {
   delete this;
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc
index c3689049..2966a19 100644
--- a/ui/views/window/dialog_delegate_unittest.cc
+++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -30,7 +30,7 @@
 class TestDialog : public DialogDelegateView {
  public:
   TestDialog() : input_(new views::Textfield()) { AddChildView(input_); }
-  ~TestDialog() override {}
+  ~TestDialog() override = default;
 
   void Init() {
     // Add the accelerator before being added to the widget hierarchy (before
@@ -116,7 +116,7 @@
 class DialogTest : public ViewsTestBase {
  public:
   DialogTest() : dialog_(nullptr) {}
-  ~DialogTest() override {}
+  ~DialogTest() override = default;
 
   void SetUp() override {
     ViewsTestBase::SetUp();
@@ -348,8 +348,8 @@
 // A dialog for testing initial focus with only an OK button.
 class InitialFocusTestDialog : public DialogDelegateView {
  public:
-  InitialFocusTestDialog() {}
-  ~InitialFocusTestDialog() override {}
+  InitialFocusTestDialog() = default;
+  ~InitialFocusTestDialog() override = default;
 
   views::View* OkButton() { return GetDialogClientView()->ok_button(); }
 
diff --git a/ui/views/window/frame_background.cc b/ui/views/window/frame_background.cc
index a84ce63..f7c9544 100644
--- a/ui/views/window/frame_background.cc
+++ b/ui/views/window/frame_background.cc
@@ -31,8 +31,7 @@
       bottom_right_corner_(nullptr),
       maximized_top_inset_(0) {}
 
-FrameBackground::~FrameBackground() {
-}
+FrameBackground::~FrameBackground() = default;
 
 void FrameBackground::SetSideImages(const gfx::ImageSkia* left,
                                     const gfx::ImageSkia* top,
diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc
index 49026c9..46c1b58 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -27,14 +27,14 @@
 constexpr float kInkDropVisibleOpacity = 0.06f;
 
 // The duration of the crossfade animation when swapping the button's images.
-const int kSwapImagesAnimationDurationMs = 200;
+constexpr int kSwapImagesAnimationDurationMs = 200;
 
 // The duration of the fade out animation of the old icon during a crossfade
 // animation as a ratio of |kSwapImagesAnimationDurationMs|.
-const float kFadeOutRatio = 0.5f;
+constexpr float kFadeOutRatio = 0.5f;
 
 // The ratio applied to the button's alpha when the button is disabled.
-const float kDisabledButtonAlphaRatio = 0.5f;
+constexpr float kDisabledButtonAlphaRatio = 0.5f;
 
 }  // namespace
 
diff --git a/ui/views/window/native_frame_view.cc b/ui/views/window/native_frame_view.cc
index 2f7c439..cbe33286 100644
--- a/ui/views/window/native_frame_view.cc
+++ b/ui/views/window/native_frame_view.cc
@@ -25,8 +25,7 @@
       frame_(frame) {
 }
 
-NativeFrameView::~NativeFrameView() {
-}
+NativeFrameView::~NativeFrameView() = default;
 
 ////////////////////////////////////////////////////////////////////////////////
 // NativeFrameView, NonClientFrameView overrides:
diff --git a/ui/views/window/non_client_view.cc b/ui/views/window/non_client_view.cc
index ca5bf7e0..4b9f937d 100644
--- a/ui/views/window/non_client_view.cc
+++ b/ui/views/window/non_client_view.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/window/non_client_view.h"
 
+#include <memory>
+
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/hit_test.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -26,8 +28,8 @@
 // because the RootView message dispatch sends messages to items higher in the
 // z-order first and we always want the client view to have first crack at
 // handling mouse messages.
-static const int kFrameViewIndex = 0;
-static const int kClientViewIndex = 1;
+static constexpr int kFrameViewIndex = 0;
+static constexpr int kClientViewIndex = 1;
 // The overlay view is always on top (index == child_count() - 1).
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -44,8 +46,7 @@
 NonClientView::NonClientView()
     : client_view_(nullptr),
       overlay_view_(nullptr) {
-  SetEventTargeter(
-      std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
+  SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
 }
 
 NonClientView::~NonClientView() {
@@ -248,8 +249,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // NonClientFrameView, public:
 
-NonClientFrameView::~NonClientFrameView() {
-}
+NonClientFrameView::~NonClientFrameView() = default;
 
 bool NonClientFrameView::ShouldPaintAsActive() const {
   return  GetWidget()->IsAlwaysRenderAsActive() ||
@@ -326,8 +326,7 @@
 
 NonClientFrameView::NonClientFrameView()
     : active_state_override_(nullptr) {
-  SetEventTargeter(
-      std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
+  SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
 }
 
 // ViewTargeterDelegate:
diff --git a/ui/views/window/window_button_order_provider.cc b/ui/views/window/window_button_order_provider.cc
index 678be8e6..272193c 100644
--- a/ui/views/window/window_button_order_provider.cc
+++ b/ui/views/window/window_button_order_provider.cc
@@ -28,8 +28,7 @@
   trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE);
 }
 
-WindowButtonOrderProvider::~WindowButtonOrderProvider() {
-}
+WindowButtonOrderProvider::~WindowButtonOrderProvider() = default;
 
 void WindowButtonOrderProvider::SetWindowButtonOrder(
     const std::vector<views::FrameButton>& leading_buttons,
diff --git a/ui/views/window/window_resources.h b/ui/views/window/window_resources.h
index 55a4a09a..c581204 100644
--- a/ui/views/window/window_resources.h
+++ b/ui/views/window/window_resources.h
@@ -11,7 +11,7 @@
 
 namespace views {
 
-typedef int FramePartImage;
+using FramePartImage = int;
 
 ///////////////////////////////////////////////////////////////////////////////
 // WindowResources
@@ -23,7 +23,7 @@
 //
 class WindowResources {
  public:
-  virtual ~WindowResources() {}
+  virtual ~WindowResources() = default;
 
   virtual gfx::ImageSkia* GetPartImage(FramePartImage part) const = 0;
 };
diff --git a/ui/views/word_lookup_client.h b/ui/views/word_lookup_client.h
index 15b9c795..d65132b 100644
--- a/ui/views/word_lookup_client.h
+++ b/ui/views/word_lookup_client.h
@@ -31,7 +31,7 @@
       gfx::Point* baseline_point) = 0;
 
  protected:
-  virtual ~WordLookupClient() {}
+  virtual ~WordLookupClient() = default;
 };
 
 }  // namespace views
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
index aa62c81..d4d894d 100644
--- a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
+++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
@@ -21,6 +21,10 @@
         pointer-events: none;
       }
 
+      :host([disabled]) cr-icon-button {
+        display: var(--cr-expand-button-disabled-display, initial);
+      }
+
       #label {
         flex: 1;
         padding: var(--cr-section-vertical-padding) 0;
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
index 36c53c96..6b7a68d 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
+++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
@@ -11,7 +11,6 @@
         --cr-icon-button-color: var(--google-grey-refresh-700);
         --cr-icon-button-default-icon-padding: 8px;
         --cr-icon-button-icon-size: 20px;
-        --cr-icon-button-ripple-color: var(--google-grey-900);
         --cr-icon-button-ripple-size: calc(var(--cr-icon-button-icon-size) +
             2 * var(--cr-icon-button-icon-padding,
                     var(--cr-icon-button-default-icon-padding)));
@@ -21,8 +20,10 @@
         background-size: var(--cr-icon-button-icon-size);
         color: var(--cr-icon-button-color);
         cursor: pointer;
+        display: inline-block;
         height: var(--cr-icon-button-size);
-        margin-inline-end: var(--cr-icon-ripple-margin);
+        margin-inline-end: var(--cr-icon-button-margin-end,
+            var(--cr-icon-ripple-margin));
         margin-inline-start: var(--cr-icon-button-margin-start);
         outline: none;
         user-select: none;
@@ -41,12 +42,10 @@
 
       :host-context([dark]) {
         --cr-icon-button-color: var(--google-grey-refresh-500);
-        --cr-icon-button-ripple-color: var(--google-grey-refresh-500);
       }
 
       :host paper-ripple {
-        --paper-ripple-opacity: .15;
-        color: var(--cr-icon-button-ripple-color);
+        --paper-ripple-opacity: .21; /* GG900 .15 is about GG700 .21 */
       }
 
       :host-context([dark]) paper-ripple {
@@ -54,9 +53,11 @@
       }
 
       #icon {
+        display: inline-flex;
         height: var(--cr-icon-button-ripple-size);
         /* The |_rippleContainer| must be position relative. */
         position: relative;
+        vertical-align: middle;
         width: var(--cr-icon-button-ripple-size);
       }
 
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
index 28c4bd80..9c1ee3c 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
+++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
@@ -54,16 +54,17 @@
   },
 
   listeners: {
-    blur: 'hideRipple',
+    blur: 'hideRipple_',
     click: 'onClick_',
     down: 'onDown_',
     focus: 'showRipple_',
     keydown: 'onKeyDown_',
     keyup: 'onKeyUp_',
-    up: 'hideRipple',
+    up: 'hideRipple_',
   },
 
-  hideRipple: function() {
+  /** @private */
+  hideRipple_: function() {
     this.getRipple().holdDown = false;
   },
 
diff --git a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
index 41e5d03..2eb59ef 100644
--- a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
+++ b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
@@ -24,7 +24,6 @@
         min-height: var(--cr-section-min-height);
         outline: none;
         padding: 0;
-        width: 100%;
       }
 
       :host(:not([embedded])) {
diff --git a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js
index 483a1cb6..9f6561f2 100644
--- a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js
+++ b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js
@@ -45,11 +45,6 @@
     ariaDescribedBy_: String,
   },
 
-  listeners: {
-    down: 'onDown_',
-    up: 'onUp_',
-  },
-
   /** @type {boolean} */
   get noink() {
     return this.$.icon.noink;
@@ -65,28 +60,6 @@
   },
 
   /** @private */
-  onDown_: function() {
-    // If the icon has focus, we want to preemptively blur it. Otherwise it will
-    // be blurred immediately after gaining focus. The ripple will either
-    // disappear when the mouse button is held down or the ripple will not
-    // be rendered. This is an issue only when the cr-link-row is clicked, not
-    // the icon itself.
-    if (this.shadowRoot.activeElement == this.$.icon) {
-      this.$.icon.blur();
-    }
-    // When cr-link-row is click, <body> will gain focus after the down event is
-    // handled. We need to wait until the next task to focus on the icon.
-    setTimeout(() => {
-      this.focus();
-    });
-  },
-
-  /** @private */
-  onUp_: function() {
-    this.$.icon.hideRipple();
-  },
-
-  /** @private */
   getIconClass_: function() {
     return this.external ? 'icon-external' : 'subpage-arrow';
   },
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
index be9235e1..397bbbf 100644
--- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
+++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -33,14 +33,12 @@
       }
 
       cr-icon-button {
-        --cr-icon-button-color: white;
         --cr-icon-button-icon-padding: 6px;
-        --cr-icon-button-ripple-color: white;
         margin: 6px;
       }
 
-      :host-context([dark]) cr-icon-button {
-        --cr-icon-button-color: var(--google-grey-200);
+      :host-context(html:not([dark])) cr-icon-button {
+        --cr-icon-button-color: currentColor;
       }
 
       #icon {
diff --git a/ui/webui/resources/js/cr/ui/dialogs.js b/ui/webui/resources/js/cr/ui/dialogs.js
index f18c5a37..95d84fe 100644
--- a/ui/webui/resources/js/cr/ui/dialogs.js
+++ b/ui/webui/resources/js/cr/ui/dialogs.js
@@ -53,6 +53,7 @@
 
     this.frame_ = doc.createElement('div');
     this.frame_.className = 'cr-dialog-frame';
+    this.frame_.setAttribute('role', 'dialog');
     // Elements that have negative tabIndex can be focused but are not traversed
     // by Tab key.
     this.frame_.tabIndex = -1;
@@ -239,9 +240,11 @@
     if (title) {
       this.title_.textContent = title;
       this.title_.hidden = false;
+      this.frame_.setAttribute('aria-label', title);
     } else {
       this.title_.textContent = '';
       this.title_.hidden = true;
+      this.frame_.removeAttribute('aria-label');
     }
 
     const self = this;