diff --git a/DEPS b/DEPS
index 6d0a04b9f..43268be 100644
--- a/DEPS
+++ b/DEPS
@@ -111,11 +111,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '06a4ef497ff1b0986a8c9dd007fcbc91c00ddef6',
+  'skia_revision': '14768f64fba34ab6b7bc0ed853c9cfdb1ab965ca',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'c3ca4c145653efa67b75f146285e7d6b5b33ca03',
+  'v8_revision': '004565cfcf3a22345724c297dade0a983b7c7b20',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -135,7 +135,7 @@
   # 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': '06305f5d71c779a3fa2cd514ec34ee443bd0e5f9',
+  'pdfium_revision': '05e43638cd377444b88def5c02562e771e25a158',
   # 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.
@@ -650,7 +650,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9ab423a548ac7085671685a355af5fd251a1b070',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5a5616f3bb3bc706fbd30d3b4fc6eee710ea2d7a',
       'condition': 'checkout_linux',
   },
 
@@ -675,7 +675,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cb629a482b3d3c13e46a66031ba4c0cc3679d200',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '46f20cd3905595b7485388f743613ed685c1bd89',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1156,7 +1156,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0d55c887e92b645f6effe753528323ab2ffd94c2',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'c640a936d166cd6a9fe5544ae7acc12f0e7ca1ce',
+    Var('webrtc_git') + '/src.git' + '@' + '3b149e4be88059c853cdfc1940d006e5fe456b32',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1187,7 +1187,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6cf33fa7deb48ea67cc7b9310118d83b3af58420',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6f01f2f2b42fd3ab2941e1a76f05ba78d65a2fa2',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 1da818c..5df107c 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -740,10 +740,6 @@
     "system/message_center/fullscreen_notification_blocker.h",
     "system/message_center/inactive_user_notification_blocker.cc",
     "system/message_center/inactive_user_notification_blocker.h",
-    "system/message_center/message_center_bubble.cc",
-    "system/message_center/message_center_bubble.h",
-    "system/message_center/message_center_button_bar.cc",
-    "system/message_center/message_center_button_bar.h",
     "system/message_center/message_center_controller.cc",
     "system/message_center/message_center_controller.h",
     "system/message_center/message_center_scroll_bar.cc",
@@ -752,20 +748,12 @@
     "system/message_center/message_center_ui_controller.cc",
     "system/message_center/message_center_ui_controller.h",
     "system/message_center/message_center_ui_delegate.h",
-    "system/message_center/message_center_view.cc",
-    "system/message_center/message_center_view.h",
-    "system/message_center/message_list_view.cc",
-    "system/message_center/message_list_view.h",
     "system/message_center/notification_swipe_control_view.cc",
     "system/message_center/notification_swipe_control_view.h",
-    "system/message_center/notification_tray.cc",
-    "system/message_center/notification_tray.h",
     "system/message_center/notifier_settings_view.cc",
     "system/message_center/notifier_settings_view.h",
     "system/message_center/session_state_notification_blocker.cc",
     "system/message_center/session_state_notification_blocker.h",
-    "system/message_center/slidable_message_view.cc",
-    "system/message_center/slidable_message_view.h",
     "system/message_center/unified_message_center_view.cc",
     "system/message_center/unified_message_center_view.h",
     "system/message_center/unified_message_list_view.cc",
@@ -1837,9 +1825,6 @@
     "system/message_center/ash_popup_alignment_delegate_unittest.cc",
     "system/message_center/inactive_user_notification_blocker_unittest.cc",
     "system/message_center/message_center_ui_controller_unittest.cc",
-    "system/message_center/message_center_view_unittest.cc",
-    "system/message_center/message_list_view_unittest.cc",
-    "system/message_center/notification_tray_unittest.cc",
     "system/message_center/notifier_settings_view_unittest.cc",
     "system/message_center/session_state_notification_blocker_unittest.cc",
     "system/message_center/unified_message_center_view_unittest.cc",
@@ -1893,7 +1878,6 @@
     "system/tray/tray_event_filter_unittest.cc",
     "system/tray/tray_info_label_unittest.cc",
     "system/tray/tri_view_unittest.cc",
-    "system/tray_caps_lock_unittest.cc",
     "system/tray_tracing_unittest.cc",
     "system/unified/feature_pods_container_view_unittest.cc",
     "system/unified/quiet_mode_feature_pod_controller_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 0a9e7b9..1edb836 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -44,7 +44,6 @@
 #include "ash/system/brightness_control_delegate.h"
 #include "ash/system/ime_menu/ime_menu_tray.h"
 #include "ash/system/keyboard_brightness_control_delegate.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/palette/palette_tray.h"
 #include "ash/system/palette/palette_utils.h"
 #include "ash/system/power/power_button_controller.h"
diff --git a/ash/accessibility/key_accessibility_enabler_unittest.cc b/ash/accessibility/key_accessibility_enabler_unittest.cc
index 42146119..b285864 100644
--- a/ash/accessibility/key_accessibility_enabler_unittest.cc
+++ b/ash/accessibility/key_accessibility_enabler_unittest.cc
@@ -7,7 +7,6 @@
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_observer.h"
 #include "ash/shell.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/run_loop.h"
@@ -23,7 +22,6 @@
   KeyAccessibilityEnablerTest() {}
 
   void SetUp() override {
-    NotificationTray::DisableAnimationsForTest(true);
     ui::SetEventTickClockForTesting(&clock_);
     AshTestBase::SetUp();
     Shell::Get()->accessibility_controller()->AddObserver(this);
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 88ff037..3f31b4f1 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -96,9 +96,6 @@
 // home launcher gestures, if they can be processed.
 constexpr int kAppListHomeLaucherGesturesThreshold = 32;
 
-// Quality of the shield background blur.
-constexpr float kAppListBlurQuality = 0.25f;
-
 // Set animation durations to 0 for testing.
 static bool short_animations_for_testing;
 
@@ -510,8 +507,6 @@
         app_list_background_shield_mask_->layer());
     app_list_background_shield_->layer()->SetBackgroundBlur(
         AppListConfig::instance().blur_radius());
-    app_list_background_shield_->layer()->SetBackdropFilterQuality(
-        kAppListBlurQuality);
   }
   AddChildView(app_list_background_shield_);
   app_list_main_view_ = new AppListMainView(delegate_, this);
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index aeaf24b..d4c6ba97 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -276,6 +276,14 @@
       <message name="IDS_ASH_STATUS_TRAY_CAST_STOP" desc="The label used in the tray popup to stop casting.">
         Stop
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_QUIET_MODE_TOOLTIP" desc="The tooltip text for the status area icon to tell do-not-disturb mode is currently on.">
+        Do Not Disturb is on
+      </message>
+      <message name="IDS_ASH_STATUS_TRAY_NOTIFICATIONS_COUNT_TOOLTIP" desc="The tooltip text for a status area icon to describe number of notifications. [ICU Syntax]">
+        {NUM_NOTIFICATIONS, plural,
+         =1 {1 notification}
+         other {# notifications}}
+      </message>
 
       <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH" desc="The label used as the header in the bluetooth popup.">
         Bluetooth
diff --git a/ash/media/media_notification_view_unittest.cc b/ash/media/media_notification_view_unittest.cc
index fe6acff2..2c1e16ab 100644
--- a/ash/media/media_notification_view_unittest.cc
+++ b/ash/media/media_notification_view_unittest.cc
@@ -11,7 +11,6 @@
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
-#include "ash/system/message_center/message_center_view.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_test_helper.h"
 #include "ash/system/unified/unified_system_tray.h"
@@ -39,8 +38,6 @@
 
     AshTestBase::SetUp();
 
-    MessageCenterView::disable_animation_for_testing = true;
-
     // Set a custom view factory to create and capture the notification view.
     message_center::MessageViewFactory::
         ClearCustomNotificationViewFactoryForTest(
@@ -74,7 +71,6 @@
   }
 
   void TearDown() override {
-    MessageCenterView::disable_animation_for_testing = false;
     view_ = nullptr;
 
     message_center::MessageViewFactory::
diff --git a/ash/session/session_controller_unittest.cc b/ash/session/session_controller_unittest.cc
index 01ca22ab..9acea02 100644
--- a/ash/session/session_controller_unittest.cc
+++ b/ash/session/session_controller_unittest.cc
@@ -14,7 +14,6 @@
 #include "ash/session/session_observer.h"
 #include "ash/session/test_session_controller_client.h"
 #include "ash/shell.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/screen_security/screen_tray_item.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/test/ash_test_base.h"
@@ -592,14 +591,8 @@
   CanSwitchUserTest() = default;
   ~CanSwitchUserTest() override = default;
 
-  void SetUp() override {
-    AshTestBase::SetUp();
-    NotificationTray::DisableAnimationsForTest(true);
-  }
-
   void TearDown() override {
     RunAllPendingInMessageLoop();
-    NotificationTray::DisableAnimationsForTest(false);
     AshTestBase::TearDown();
   }
 
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 46e4e074..2c41ca74 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -36,7 +36,6 @@
 #include "ash/shell.h"
 #include "ash/shell_test_api.h"
 #include "ash/system/flag_warning/flag_warning_tray.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/ash_test_helper.h"
@@ -264,8 +263,6 @@
     model_ = Shell::Get()->shelf_model();
     shelf_view_ = GetPrimaryShelf()->GetShelfViewForTesting();
 
-    NotificationTray::DisableAnimationsForTest(true);
-
     // Several tests in this file are brittle and fail when the shelf width
     // changes due to the flag warning button. Since we won't show this button
     // to users in production, hide it in the tests. https://crbug.com/891080
@@ -290,7 +287,6 @@
   }
 
   void TearDown() override {
-    NotificationTray::DisableAnimationsForTest(false);  // Reenable animation
     test_api_.reset();
     AshTestBase::TearDown();
   }
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 2e20fe9..563ad7d 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -45,7 +45,6 @@
 
 constexpr int kShelfRoundedCornerRadius = 28;
 constexpr int kShelfBlurRadius = 10;
-constexpr float kShelfBlurQuality = 0.25f;
 
 // Return the first or last focusable child of |root|.
 views::View* FindFirstOrLastFocusableChild(views::View* root,
@@ -199,7 +198,6 @@
 
   opaque_background_.SetBackgroundBlur(should_blur_background ? kShelfBlurRadius
                                                               : 0);
-  opaque_background_.SetBackdropFilterQuality(kShelfBlurQuality);
 
   background_is_currently_blurred_ = should_blur_background;
 }
diff --git a/ash/shell.cc b/ash/shell.cc
index 78abc8540..db313f3 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -507,12 +507,6 @@
     Shelf::ForWindow(root)->UpdateVisibilityState();
 }
 
-NotificationTray* Shell::GetNotificationTray() {
-  return GetPrimaryRootWindowController()
-      ->GetStatusAreaWidget()
-      ->notification_tray();
-}
-
 bool Shell::HasPrimaryStatusArea() {
   return !!GetPrimaryRootWindowController()->GetStatusAreaWidget();
 }
diff --git a/ash/shell.h b/ash/shell.h
index 687d853e..871bb6e 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -145,7 +145,6 @@
 class NewWindowController;
 class NightLightController;
 class NoteTakingController;
-class NotificationTray;
 class OverlayEventFilter;
 class PartialMagnificationController;
 class PeripheralBatteryNotifier;
@@ -563,9 +562,6 @@
   // TODO(jamescook): Move to Shelf.
   void UpdateShelfVisibility();
 
-  // Returns NotificationTray on the primary root window.
-  NotificationTray* GetNotificationTray();
-
   // Does the primary display have status area?
   bool HasPrimaryStatusArea();
 
diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc
index 22d6996..95a2b54 100644
--- a/ash/shell/window_type_launcher.cc
+++ b/ash/shell/window_type_launcher.cc
@@ -12,8 +12,6 @@
 #include "ash/shell.h"
 #include "ash/shell/example_factory.h"
 #include "ash/shell/toplevel_window.h"
-#include "ash/system/message_center/notification_tray.h"
-#include "ash/system/status_area_widget.h"
 #include "ash/wm/test_child_modal_parent.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/window.h"
@@ -285,21 +283,18 @@
   } else if (sender == show_hide_window_button_) {
     NonModalTransient::ToggleNonModalTransient(GetWidget()->GetNativeView());
   } else if (sender == show_web_notification_) {
-    std::unique_ptr<message_center::Notification> notification;
-    notification.reset(new message_center::Notification(
-        message_center::NOTIFICATION_TYPE_SIMPLE, "id0",
-        base::ASCIIToUTF16("Test Shell Web Notification"),
-        base::ASCIIToUTF16("Notification message body."), gfx::Image(),
-        base::ASCIIToUTF16("www.testshell.org"), GURL(),
-        message_center::NotifierId(message_center::NotifierId::APPLICATION,
-                                   "test-id"),
-        message_center::RichNotificationData(), NULL /* delegate */));
+    std::unique_ptr<message_center::Notification> notification =
+        std::make_unique<message_center::Notification>(
+            message_center::NOTIFICATION_TYPE_SIMPLE, "id0",
+            base::ASCIIToUTF16("Test Shell Web Notification"),
+            base::ASCIIToUTF16("Notification message body."), gfx::Image(),
+            base::ASCIIToUTF16("www.testshell.org"), GURL(),
+            message_center::NotifierId(message_center::NotifierId::APPLICATION,
+                                       "test-id"),
+            message_center::RichNotificationData(), nullptr /* delegate */);
 
-    Shell::GetPrimaryRootWindowController()
-        ->GetStatusAreaWidget()
-        ->notification_tray()
-        ->message_center()
-        ->AddNotification(std::move(notification));
+    message_center::MessageCenter::Get()->AddNotification(
+        std::move(notification));
   } else if (sender == examples_button_) {
     show_views_examples_callback_.Run();
   }
diff --git a/ash/system/caps_lock_notification_controller_unittest.cc b/ash/system/caps_lock_notification_controller_unittest.cc
index 3a1917c..a692cf5 100644
--- a/ash/system/caps_lock_notification_controller_unittest.cc
+++ b/ash/system/caps_lock_notification_controller_unittest.cc
@@ -7,29 +7,11 @@
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/shell.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/test/ash_test_base.h"
 
 namespace ash {
 
-class CapsLockNotificationControllerTest : public AshTestBase {
- public:
-  CapsLockNotificationControllerTest() = default;
-  ~CapsLockNotificationControllerTest() override = default;
-
-  void SetUp() override {
-    AshTestBase::SetUp();
-    NotificationTray::DisableAnimationsForTest(true);
-  }
-
-  void TearDown() override {
-    NotificationTray::DisableAnimationsForTest(false);
-    AshTestBase::TearDown();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CapsLockNotificationControllerTest);
-};
+using CapsLockNotificationControllerTest = AshTestBase;
 
 // Tests that a11y alert is sent on toggling caps lock.
 TEST_F(CapsLockNotificationControllerTest, A11yAlert) {
diff --git a/ash/system/message_center/arc/arc_notification_content_view.cc b/ash/system/message_center/arc/arc_notification_content_view.cc
index 4c4e7193..ffeda94 100644
--- a/ash/system/message_center/arc/arc_notification_content_view.cc
+++ b/ash/system/message_center/arc/arc_notification_content_view.cc
@@ -536,6 +536,7 @@
 
   // Re-install the mask since the custom mask is unset by
   // |::wm::RecreateLayers()| in |ShowCopiedSurface()| method.
+  mask_insets_.reset();
   UpdateMask();
 }
 
diff --git a/ash/system/message_center/arc/arc_notification_content_view_unittest.cc b/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
index 5d260ea..753ce94 100644
--- a/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
+++ b/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
@@ -18,7 +18,6 @@
 #include "ash/system/message_center/arc/arc_notification_surface_manager_impl.h"
 #include "ash/system/message_center/arc/arc_notification_view.h"
 #include "ash/system/message_center/arc/mock_arc_notification_item.h"
-#include "ash/system/message_center/message_center_view.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_test_helper.h"
 #include "ash/system/unified/unified_system_tray.h"
@@ -114,8 +113,6 @@
   void SetUp() override {
     AshTestBase::SetUp();
 
-    MessageCenterView::disable_animation_for_testing = true;
-
     wm_helper_ = std::make_unique<exo::WMHelper>(ash::Shell::Get()->aura_env());
     exo::WMHelper::SetInstance(wm_helper_.get());
     DCHECK(exo::WMHelper::HasInstance());
diff --git a/ash/system/message_center/message_center_bubble.cc b/ash/system/message_center/message_center_bubble.cc
deleted file mode 100644
index 06d11732..0000000
--- a/ash/system/message_center/message_center_bubble.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/message_center_bubble.h"
-
-#include "ash/public/cpp/app_list/app_list_features.h"
-#include "ash/system/message_center/message_center_view.h"
-#include "ash/system/tray/tray_bubble_view.h"
-#include "base/macros.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/widget/widget.h"
-
-using message_center::MessageCenter;
-
-namespace ash {
-
-namespace {
-constexpr int kDefaultMaxHeight = 400;
-
-constexpr SkColor kBackgroundColorWithBlur =
-    SkColorSetARGB(0xCC, 0xF0, 0xF0, 0xF2);
-constexpr SkColor kBackgroundColor = SkColorSetARGB(0xF2, 0xF0, 0xF0, 0xF2);
-}  // namespace
-
-// ContentsView ////////////////////////////////////////////////////////////////
-
-// Handles changes in MessageCenterView sizes.
-class ContentsView : public views::View {
- public:
-  explicit ContentsView(MessageCenterBubble* bubble, views::View* contents);
-  ~ContentsView() override;
-
-  // Overridden from views::View:
-  int GetHeightForWidth(int width) const override;
-
- protected:
-  // Overridden from views::View:
-  void ChildPreferredSizeChanged(View* child) override;
-
- private:
-  base::WeakPtr<MessageCenterBubble> bubble_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentsView);
-};
-
-ContentsView::ContentsView(MessageCenterBubble* bubble, views::View* contents)
-    : bubble_(bubble->AsWeakPtr()) {
-  SetLayoutManager(std::make_unique<views::FillLayout>());
-
-  SetBackground(views::CreateSolidBackground(
-      app_list_features::IsBackgroundBlurEnabled() ? kBackgroundColorWithBlur
-                                                   : kBackgroundColor));
-  SetPaintToLayer();
-  layer()->SetFillsBoundsOpaquely(false);
-  AddChildView(contents);
-}
-
-ContentsView::~ContentsView() = default;
-
-int ContentsView::GetHeightForWidth(int width) const {
-  DCHECK_EQ(1, child_count());
-  int contents_width = std::max(width - GetInsets().width(), 0);
-  int contents_height = child_at(0)->GetHeightForWidth(contents_width);
-  return contents_height + GetInsets().height();
-}
-
-void ContentsView::ChildPreferredSizeChanged(View* child) {
-  // TODO(dharcourt): Reduce the amount of updating this requires.
-  if (bubble_.get())
-    bubble_->bubble_view()->UpdateBubble();
-}
-
-// MessageCenterBubble /////////////////////////////////////////////////////////
-
-MessageCenterBubble::MessageCenterBubble(MessageCenter* message_center)
-    : message_center_(message_center), max_height_(kDefaultMaxHeight) {}
-
-MessageCenterBubble::~MessageCenterBubble() {
-  // Removs this from the widget observers just in case. MessageCenterBubble
-  // might be destoryed without calling its Widget's Close/CloseNow.
-  if (bubble_view_ && bubble_view_->GetWidget())
-    bubble_view_->GetWidget()->RemoveObserver(this);
-  if (bubble_view_)
-    bubble_view_->ResetDelegate();
-}
-
-void MessageCenterBubble::BubbleViewDestroyed() {
-  bubble_view_ = nullptr;
-  message_center_view_ = nullptr;
-}
-
-void MessageCenterBubble::SetMaxHeight(int height) {
-  // Maximum height makes sense only for the new design.
-  if (height == 0)
-    height = kDefaultMaxHeight;
-  if (height == max_height_)
-    return;
-
-  max_height_ = height;
-  if (bubble_view_)
-    bubble_view_->SetMaxHeight(max_height_);
-  if (message_center_view_)
-    message_center_view_->SetMaxHeight(max_height_);
-}
-
-void MessageCenterBubble::InitializeContents(TrayBubbleView* new_bubble_view) {
-  bubble_view_ = new_bubble_view;
-  bubble_view_->GetWidget()->AddObserver(this);
-  message_center_view_ = new MessageCenterView(message_center_, max_height_);
-  bubble_view_->AddChildView(new ContentsView(this, message_center_view_));
-  message_center_view_->SetMaxHeight(max_height_);
-  // Resize the content of the bubble view to the given bubble size. This is
-  // necessary in case of the bubble border forcing a bigger size then the
-  // |new_bubble_view| actually wants. See crbug.com/169390.
-  bubble_view_->Layout();
-  UpdateBubbleView();
-}
-
-void MessageCenterBubble::OnWidgetClosing(views::Widget* widget) {
-  if (bubble_view_ && bubble_view_->GetWidget())
-    bubble_view_->GetWidget()->RemoveObserver(this);
-  if (message_center_view_)
-    message_center_view_->SetIsClosing(true);
-}
-
-bool MessageCenterBubble::IsVisible() const {
-  return bubble_view() && bubble_view()->GetWidget()->IsVisible();
-}
-
-size_t MessageCenterBubble::NumMessageViewsForTest() const {
-  return message_center_view_->NumMessageViewsForTest();
-}
-
-void MessageCenterBubble::UpdateBubbleView() {
-  if (!bubble_view_)
-    return;  // Could get called after view is closed
-  message_center_view_->SetNotifications(
-      message_center_->GetVisibleNotifications());
-  bubble_view_->GetWidget()->Show();
-  bubble_view_->UpdateBubble();
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/message_center_bubble.h b/ash/system/message_center/message_center_bubble.h
deleted file mode 100644
index e9a900d..0000000
--- a/ash/system/message_center/message_center_bubble.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_BUBBLE_H_
-#define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_BUBBLE_H_
-
-#include <stddef.h>
-
-#include "ash/ash_export.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/views/widget/widget_observer.h"
-
-namespace message_center {
-class MessageCenter;
-}  // namespace message_center
-
-namespace ash {
-
-class MessageCenterView;
-class TrayBubbleView;
-
-// Bubble for message center.
-class MessageCenterBubble : public views::WidgetObserver,
-                            public base::SupportsWeakPtr<MessageCenterBubble> {
- public:
-  explicit MessageCenterBubble(message_center::MessageCenter* message_center);
-  ~MessageCenterBubble() override;
-
-  // Gets called when the bubble view associated with this bubble is
-  // destroyed. Clears |bubble_view_|.
-  void BubbleViewDestroyed();
-
-  // Sets/Gets the maximum height of the bubble view. Setting 0 changes the
-  // bubble to the default size. max_height() will return the default size
-  // if SetMaxHeight() has not been called yet.
-  void SetMaxHeight(int height);
-  int max_height() const { return max_height_; }
-
-  // Called after the bubble view has been constructed. Creates and initializes
-  // the bubble contents.
-  void InitializeContents(TrayBubbleView* bubble_view);
-
-  bool IsVisible() const;
-
-  // Overridden from views::WidgetObserver:
-  void OnWidgetClosing(views::Widget* widget) override;
-
-  size_t ASH_EXPORT NumMessageViewsForTest() const;
-
-  TrayBubbleView* bubble_view() const { return bubble_view_; }
-
- private:
-  void UpdateBubbleView();
-
-  message_center::MessageCenter* message_center_;
-  TrayBubbleView* bubble_view_ = nullptr;
-
-  // |message_center_view_| is a child view of the ContentsView, which is a
-  // child view of |bubble_view_|. They're added to the view tree by calling
-  // InitializeContents.
-  MessageCenterView* message_center_view_ = nullptr;
-
-  int max_height_;
-
-  base::WeakPtrFactory<MessageCenterBubble> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(MessageCenterBubble);
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_BUBBLE_H_
diff --git a/ash/system/message_center/message_center_button_bar.cc b/ash/system/message_center/message_center_button_bar.cc
deleted file mode 100644
index 231cf7e..0000000
--- a/ash/system/message_center/message_center_button_bar.cc
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/message_center_button_bar.h"
-
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
-#include "ash/system/message_center/message_center_style.h"
-#include "ash/system/message_center/message_center_view.h"
-#include "ash/system/tray/tray_constants.h"
-#include "ash/system/tray/tray_popup_utils.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "ui/accessibility/ax_node_data.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/models/simple_menu_model.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/text_constants.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/public/cpp/notifier_id.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
-#include "ui/views/animation/ink_drop_highlight.h"
-#include "ui/views/animation/ink_drop_impl.h"
-#include "ui/views/animation/ink_drop_mask.h"
-#include "ui/views/border.h"
-#include "ui/views/controls/button/button.h"
-#include "ui/views/controls/button/image_button.h"
-#include "ui/views/controls/button/label_button.h"
-#include "ui/views/controls/button/menu_button.h"
-#include "ui/views/controls/button/menu_button_listener.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/grid_layout.h"
-#include "ui/views/painter.h"
-
-using message_center::MessageCenter;
-
-namespace ash {
-
-namespace {
-
-constexpr SkColor kTextColor = SkColorSetARGB(0xFF, 0x0, 0x0, 0x0);
-constexpr SkColor kButtonSeparatorColor = SkColorSetARGB(0x1F, 0x0, 0x0, 0x0);
-constexpr int kTextFontSizeDelta = 2;
-constexpr int kSeparatorHeight = 24;
-constexpr gfx::Insets kSeparatorPadding(12, 0, 12, 0);
-constexpr gfx::Insets kButtonBarBorder(4, 18, 4, 0);
-
-// A ToggleImageButton that implements system menu style ink drop animation.
-class MessageCenterButton : public views::ToggleImageButton {
- public:
-  MessageCenterButton(views::ButtonListener* listener)
-      : ToggleImageButton(listener) {
-    SetBorder(
-        views::CreateEmptyBorder(message_center_style::kActionIconPadding));
-    set_animate_on_state_change(true);
-
-    TrayPopupUtils::ConfigureTrayPopupButton(this);
-  }
-
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    return TrayPopupUtils::CreateInkDrop(this);
-  }
-
-  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override {
-    return TrayPopupUtils::CreateInkDropRipple(
-        TrayPopupInkDropStyle::HOST_CENTERED, this,
-        GetInkDropCenterBasedOnLastEvent());
-  }
-
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override {
-    return TrayPopupUtils::CreateInkDropHighlight(
-        TrayPopupInkDropStyle::HOST_CENTERED, this);
-  }
-
-  std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override {
-    return TrayPopupUtils::CreateInkDropMask(
-        TrayPopupInkDropStyle::HOST_CENTERED, this);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MessageCenterButton);
-};
-
-views::Separator* CreateVerticalSeparator() {
-  views::Separator* separator = new views::Separator;
-  separator->SetPreferredHeight(kSeparatorHeight);
-  separator->SetColor(kButtonSeparatorColor);
-  separator->SetBorder(views::CreateEmptyBorder(kSeparatorPadding));
-  return separator;
-}
-
-}  // namespace
-
-// MessageCenterButtonBar /////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-MessageCenterButtonBar::MessageCenterButtonBar(
-    MessageCenterView* message_center_view,
-    MessageCenter* message_center,
-    bool locked)
-    : message_center_view_(message_center_view),
-      message_center_(message_center),
-      notification_label_(nullptr),
-      button_container_(nullptr),
-      close_all_button_(nullptr),
-      quiet_mode_button_(nullptr),
-      settings_button_(nullptr) {
-  SetPaintToLayer();
-  SetBackground(
-      views::CreateSolidBackground(message_center_style::kBackgroundColor));
-  SetBorder(views::CreateEmptyBorder(kButtonBarBorder));
-
-  notification_label_ = new views::Label(
-      GetTitle(!locked || AshMessageCenterLockScreenController::IsEnabled()));
-  notification_label_->SetAutoColorReadabilityEnabled(false);
-  notification_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  notification_label_->SetEnabledColor(kTextColor);
-  // "Roboto-Medium, 14sp" is specified in the mock.
-  notification_label_->SetFontList(gfx::FontList().Derive(
-      kTextFontSizeDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM));
-  AddChildView(notification_label_);
-
-  button_container_ = new views::View;
-  button_container_->SetPaintToLayer();
-  button_container_->SetBackground(
-      views::CreateSolidBackground(message_center_style::kBackgroundColor));
-  button_container_->SetLayoutManager(
-      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
-  close_all_button_ = new MessageCenterButton(this);
-  close_all_button_->SetImage(
-      views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(kNotificationCenterClearAllIcon, kMenuIconSize,
-                            kMenuIconColor));
-  close_all_button_->SetImage(
-      views::Button::STATE_DISABLED,
-      gfx::CreateVectorIcon(kNotificationCenterClearAllIcon, kMenuIconSize,
-                            kMenuIconColorDisabled));
-  close_all_button_->SetTooltipText(l10n_util::GetStringUTF16(
-      IDS_ASH_MESSAGE_CENTER_CLEAR_ALL_BUTTON_TOOLTIP));
-  button_container_->AddChildView(close_all_button_);
-  separator_1_ = CreateVerticalSeparator();
-  button_container_->AddChildView(separator_1_);
-
-  quiet_mode_button_ = new MessageCenterButton(this);
-  quiet_mode_button_->SetImage(
-      views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(kNotificationCenterDoNotDisturbOffIcon,
-                            kMenuIconSize, kMenuIconColorDisabled));
-  gfx::ImageSkia quiet_mode_toggle_icon = gfx::CreateVectorIcon(
-      kNotificationCenterDoNotDisturbOnIcon, kMenuIconSize, kMenuIconColor);
-  quiet_mode_button_->SetToggledImage(views::Button::STATE_NORMAL,
-                                      &quiet_mode_toggle_icon);
-  quiet_mode_button_->SetTooltipText(l10n_util::GetStringUTF16(
-      IDS_ASH_MESSAGE_CENTER_QUIET_MODE_BUTTON_TOOLTIP));
-  SetQuietModeState(message_center->IsQuietMode());
-  button_container_->AddChildView(quiet_mode_button_);
-  separator_2_ = CreateVerticalSeparator();
-  button_container_->AddChildView(separator_2_);
-
-  settings_button_ = new MessageCenterButton(this);
-  settings_button_->SetImage(
-      views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(kNotificationCenterSettingsIcon, kMenuIconSize,
-                            kMenuIconColor));
-  settings_button_->SetTooltipText(l10n_util::GetStringUTF16(
-      IDS_ASH_MESSAGE_CENTER_SETTINGS_BUTTON_TOOLTIP));
-  button_container_->AddChildView(settings_button_);
-
-  collapse_button_ = new MessageCenterButton(this);
-  collapse_button_->SetVisible(false);
-  collapse_button_->SetBackground(
-      views::CreateSolidBackground(message_center_style::kBackgroundColor));
-  collapse_button_->SetPaintToLayer();
-  collapse_button_->SetImage(
-      views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(kNotificationCenterCollapseIcon, kMenuIconSize,
-                            kMenuIconColor));
-  collapse_button_->SetTooltipText(l10n_util::GetStringUTF16(
-      IDS_ASH_MESSAGE_CENTER_COLLAPSE_BUTTON_TOOLTIP));
-  AddChildView(collapse_button_);
-
-  AddChildView(button_container_);
-
-  SetCloseAllButtonEnabled(true);
-  SetBackArrowVisible(false);
-}
-
-MessageCenterButtonBar::~MessageCenterButtonBar() = default;
-
-void MessageCenterButtonBar::SetSettingsAndQuietModeButtonsEnabled(
-    bool enabled) {
-  settings_button_->SetEnabled(enabled);
-  quiet_mode_button_->SetEnabled(enabled);
-}
-
-void MessageCenterButtonBar::SetCloseAllButtonEnabled(bool enabled) {
-  if (close_all_button_)
-    close_all_button_->SetEnabled(enabled);
-}
-
-views::Button* MessageCenterButtonBar::GetCloseAllButtonForTest() const {
-  return close_all_button_;
-}
-
-views::Button* MessageCenterButtonBar::GetQuietModeButtonForTest() const {
-  return quiet_mode_button_;
-}
-
-views::Button* MessageCenterButtonBar::GetSettingsButtonForTest() const {
-  return settings_button_;
-}
-
-views::Button* MessageCenterButtonBar::GetCollapseButtonForTest() const {
-  return collapse_button_;
-}
-
-void MessageCenterButtonBar::SetBackArrowVisible(bool visible) {
-  if (collapse_button_visible_ == visible)
-    return;
-
-  collapse_button_visible_ = visible;
-
-  collapse_button_->SetVisible(true);
-  button_container_->SetVisible(true);
-
-  collapse_button_->layer()->SetOpacity(visible ? 0.0 : 1.0);
-  button_container_->layer()->SetOpacity(visible ? 1.0 : 0.0);
-
-  ui::ScopedLayerAnimationSettings collapse_settings(
-      collapse_button_->layer()->GetAnimator());
-  collapse_settings.AddObserver(this);
-  collapse_settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
-  collapse_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
-      message_center_style::kSettingsTransitionDurationMs));
-
-  ui::ScopedLayerAnimationSettings container_settings(
-      button_container_->layer()->GetAnimator());
-  container_settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
-  container_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
-      message_center_style::kSettingsTransitionDurationMs));
-
-  collapse_button_->layer()->SetOpacity(visible ? 1.0 : 0.0);
-  button_container_->layer()->SetOpacity(visible ? 0.0 : 1.0);
-}
-
-void MessageCenterButtonBar::OnImplicitAnimationsCompleted() {
-  bool settings_focused =
-      GetFocusManager() &&
-      (GetFocusManager()->GetFocusedView() == collapse_button_ ||
-       GetFocusManager()->GetFocusedView() == settings_button_);
-
-  if (settings_focused) {
-    if (collapse_button_visible_)
-      collapse_button_->RequestFocus();
-    else
-      settings_button_->RequestFocus();
-  }
-
-  collapse_button_->SetVisible(collapse_button_visible_);
-  button_container_->SetVisible(!collapse_button_visible_);
-}
-
-void MessageCenterButtonBar::SetIsLocked(bool locked) {
-  SetButtonsVisible(locked);
-  UpdateLabel(!locked || AshMessageCenterLockScreenController::IsEnabled());
-}
-
-base::string16 MessageCenterButtonBar::GetTitle(
-    bool message_center_visible) const {
-  return message_center_visible
-             ? l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_FOOTER_TITLE)
-             : l10n_util::GetStringUTF16(
-                   IDS_ASH_MESSAGE_CENTER_FOOTER_LOCKSCREEN);
-}
-
-void MessageCenterButtonBar::UpdateLabel(bool message_center_visible) {
-  notification_label_->SetText(GetTitle(message_center_visible));
-  // On lock screen button bar label contains hint for user to unlock device to
-  // view notifications. Making it focusable will invoke ChromeVox spoken
-  // feedback when shown.
-  notification_label_->SetFocusBehavior(
-      message_center_visible ? FocusBehavior::ALWAYS : FocusBehavior::NEVER);
-}
-
-void MessageCenterButtonBar::SetButtonsVisible(bool locked) {
-  bool message_center_visible =
-      !locked || AshMessageCenterLockScreenController::IsEnabled();
-  if (close_all_button_)
-    close_all_button_->SetVisible(message_center_visible);
-  separator_1_->SetVisible(message_center_visible);
-  quiet_mode_button_->SetVisible(message_center_visible);
-  separator_2_->SetVisible(!locked);
-  settings_button_->SetVisible(!locked);
-
-  Layout();
-}
-
-void MessageCenterButtonBar::SetQuietModeState(bool is_quiet_mode) {
-  quiet_mode_button_->SetToggled(is_quiet_mode);
-}
-
-void MessageCenterButtonBar::ChildVisibilityChanged(views::View* child) {
-  InvalidateLayout();
-}
-
-void MessageCenterButtonBar::Layout() {
-  gfx::Rect child_area = GetContentsBounds();
-
-  notification_label_->SetBounds(
-      child_area.x(), child_area.y(),
-      notification_label_->GetPreferredSize().width(), child_area.height());
-
-  int button_container_width = button_container_->GetPreferredSize().width();
-  button_container_->SetBounds(child_area.right() - button_container_width,
-                               child_area.y(), button_container_width,
-                               child_area.height());
-
-  int collapse_button_width = collapse_button_->GetPreferredSize().width();
-  collapse_button_->SetBounds(child_area.right() - collapse_button_width,
-                              child_area.y(), collapse_button_width,
-                              child_area.height());
-}
-
-gfx::Size MessageCenterButtonBar::CalculatePreferredSize() const {
-  int preferred_height =
-      std::max(button_container_->GetPreferredSize().height(),
-               collapse_button_->GetPreferredSize().height()) +
-      GetInsets().height();
-  return gfx::Size(0, preferred_height);
-}
-
-void MessageCenterButtonBar::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  node_data->role = ax::mojom::Role::kDialog;
-  node_data->SetName(notification_label_->text());
-}
-
-void MessageCenterButtonBar::ButtonPressed(views::Button* sender,
-                                           const ui::Event& event) {
-  if (sender == close_all_button_) {
-    message_center_view()->ClearAllClosableNotifications();
-  } else if (sender == settings_button_) {
-    // In order to implement a bit tricky animation specified in UX mock, it
-    // calls ACTION_TRIGGERED of |collapse_button_| on |settings_button_| click.
-    // ACTION_TRIGGERED of |settings_button_| was already called by
-    // has_ink_drop_action_on_click().
-    // |settings_button_| and |collapse_button_| are in the same position,
-    // and SetSettingsVisible() below triggers cross-fading between them.
-    collapse_button_->AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED,
-                                     nullptr);
-    message_center_view()->SetSettingsVisible(true);
-  } else if (sender == collapse_button_) {
-    // Same as above.
-    settings_button_->AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED,
-                                     nullptr);
-    message_center_view()->SetSettingsVisible(false);
-  } else if (sender == quiet_mode_button_) {
-    if (message_center()->IsQuietMode())
-      message_center()->SetQuietMode(false);
-    else
-      message_center()->EnterQuietModeWithExpire(base::TimeDelta::FromDays(1));
-  } else {
-    NOTREACHED();
-  }
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/message_center_button_bar.h b/ash/system/message_center/message_center_button_bar.h
deleted file mode 100644
index a880903..0000000
--- a/ash/system/message_center/message_center_button_bar.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_BUTTON_BAR_H_
-#define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_BUTTON_BAR_H_
-
-#include "ash/ash_export.h"
-#include "base/macros.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/views/controls/button/button.h"
-#include "ui/views/controls/button/image_button.h"
-#include "ui/views/controls/separator.h"
-#include "ui/views/view.h"
-
-namespace views {
-class Label;
-class ToggleImageButton;
-}  // namespace views
-
-namespace message_center {
-class MessageCenter;
-}  // namespace message_center
-
-namespace ash {
-
-class MessageCenterView;
-
-// MessageCenterButtonBar is the class that shows the content outside the main
-// notification area - the label and the buttons.
-class MessageCenterButtonBar : public views::View,
-                               public views::ButtonListener,
-                               public ui::ImplicitAnimationObserver {
- public:
-  MessageCenterButtonBar(MessageCenterView* message_center_view,
-                         message_center::MessageCenter* message_center,
-                         bool locked);
-  ~MessageCenterButtonBar() override;
-
-  void SetQuietModeState(bool is_quiet_mode);
-
-  // Overridden from views::View:
-  void ChildVisibilityChanged(views::View* child) override;
-  void Layout() override;
-  gfx::Size CalculatePreferredSize() const override;
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-
-  // Overridden from views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
-
-  // Overridden from ui::ImplicitAnimationObserver:
-  void OnImplicitAnimationsCompleted() override;
-
-  // Enables or disables all of the buttons in the center.  This is used to
-  // prevent user clicks during the close-all animation.
-  void SetSettingsAndQuietModeButtonsEnabled(bool enabled);
-
-  // Sometimes we shouldn't see the close-all button.
-  void SetCloseAllButtonEnabled(bool enabled);
-
-  ASH_EXPORT views::Button* GetCloseAllButtonForTest() const;
-  ASH_EXPORT views::Button* GetSettingsButtonForTest() const;
-  ASH_EXPORT views::Button* GetQuietModeButtonForTest() const;
-  ASH_EXPORT views::Button* GetCollapseButtonForTest() const;
-
-  // Sometimes we shouldn't see the back arrow (not in settings).
-  void SetBackArrowVisible(bool visible);
-
-  // Updates notification label and buttons for state specified by |locked|.
-  void SetIsLocked(bool locked);
-
- private:
-  MessageCenterView* message_center_view() const {
-    return message_center_view_;
-  }
-  message_center::MessageCenter* message_center() const {
-    return message_center_;
-  }
-
-  // Returns title for state specified by |message_center_visible|.
-  base::string16 GetTitle(bool message_center_visible) const;
-
-  // Updates notification label for state specified by |message_center_visible|.
-  void UpdateLabel(bool message_center_visible);
-
-  void SetButtonsVisible(bool locked);
-
-  MessageCenterView* message_center_view_;
-  message_center::MessageCenter* message_center_;
-
-  // Sub-views of the button bar.
-  views::Label* notification_label_;
-  views::View* button_container_;
-  views::ToggleImageButton* close_all_button_;
-  // A view of a separator between |close_all_button_| and |quiet_mode_button_|.
-  views::Separator* separator_1_;
-  views::ToggleImageButton* quiet_mode_button_;
-  // A view of a separator between |quiet_mode_button_| and |settings_button_|.
-  views::Separator* separator_2_;
-  views::ToggleImageButton* settings_button_;
-  views::ToggleImageButton* collapse_button_;
-
-  bool collapse_button_visible_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageCenterButtonBar);
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_BUTTON_BAR_H_
diff --git a/ash/system/message_center/message_center_style.h b/ash/system/message_center/message_center_style.h
index bab101e..2b4d6a47 100644
--- a/ash/system/message_center/message_center_style.h
+++ b/ash/system/message_center/message_center_style.h
@@ -6,26 +6,21 @@
 #define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_STYLE_H_
 
 #include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/font_list.h"
 #include "ui/gfx/geometry/insets.h"
 
 namespace ash {
 
 namespace message_center_style {
 
-constexpr SkColor kBackgroundColor = SK_ColorWHITE;
 constexpr SkColor kEmptyViewColor = SkColorSetARGB(0x8A, 0x0, 0x0, 0x0);
 constexpr SkColor kScrollShadowColor = SkColorSetARGB(0x24, 0x0, 0x0, 0x0);
 
 constexpr int kEmptyIconSize = 24;
-constexpr gfx::Insets kActionIconPadding(14);
 constexpr gfx::Insets kEmptyIconPadding(0, 0, 4, 0);
 
 constexpr int kScrollShadowOffsetY = 2;
 constexpr int kScrollShadowBlur = 2;
 
-constexpr int kSettingsTransitionDurationMs = 500;
-
 // Layout parameters for swipe control of notifications in message center.
 constexpr int kSwipeControlButtonImageSize = 20;
 constexpr int kSwipeControlButtonSize = 36;
diff --git a/ash/system/message_center/message_center_view.cc b/ash/system/message_center/message_center_view.cc
deleted file mode 100644
index b2d9e4e..0000000
--- a/ash/system/message_center/message_center_view.cc
+++ /dev/null
@@ -1,739 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/message_center_view.h"
-
-#include <list>
-#include <map>
-
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/session/session_controller.h"
-#include "ash/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
-#include "ash/system/message_center/message_center_button_bar.h"
-#include "ash/system/message_center/message_center_scroll_bar.h"
-#include "ash/system/message_center/message_center_style.h"
-#include "ash/system/message_center/notifier_settings_view.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
-#include "build/build_config.h"
-#include "ui/accessibility/ax_node_data.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/compositor/paint_recorder.h"
-#include "ui/gfx/animation/slide_animation.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/skia_paint_util.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/message_center_types.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/views/message_view.h"
-#include "ui/message_center/views/message_view_factory.h"
-#include "ui/message_center/views/notification_control_buttons_view.h"
-#include "ui/views/background.h"
-#include "ui/views/border.h"
-#include "ui/views/controls/button/button.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/controls/scroll_view.h"
-#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/widget/widget.h"
-
-using message_center::MessageCenter;
-using message_center::MessageView;
-using message_center::Notification;
-using message_center::NotificationList;
-
-namespace ash {
-
-// static
-const size_t MessageCenterView::kMaxVisibleNotifications = 100;
-
-// static
-bool MessageCenterView::disable_animation_for_testing = false;
-
-namespace {
-
-constexpr int kMinScrollViewHeight = 77;
-constexpr int kEmptyViewHeight = 96;
-constexpr gfx::Insets kEmptyViewPadding(0, 0, 24, 0);
-constexpr int kScrollShadowOffsetY = -2;
-constexpr int kScrollShadowBlur = 2;
-constexpr SkColor kScrollShadowColor = SkColorSetA(SK_ColorBLACK, 0x24);
-
-void SetViewHierarchyEnabled(views::View* view, bool enabled) {
-  for (int i = 0; i < view->child_count(); i++)
-    SetViewHierarchyEnabled(view->child_at(i), enabled);
-  view->SetEnabled(enabled);
-}
-
-// Create a view that is shown when there are no notifications.
-views::View* CreateEmptyNotificationView() {
-  auto* view = new views::View;
-  auto layout = std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical,
-                                                   kEmptyViewPadding, 0);
-  layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
-  layout->set_cross_axis_alignment(
-      views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
-  view->SetLayoutManager(std::move(layout));
-
-  views::ImageView* icon = new views::ImageView();
-  icon->SetImage(gfx::CreateVectorIcon(kNotificationCenterAllDoneIcon,
-                                       message_center_style::kEmptyIconSize,
-                                       message_center_style::kEmptyViewColor));
-  icon->SetBorder(
-      views::CreateEmptyBorder(message_center_style::kEmptyIconPadding));
-  view->AddChildView(icon);
-
-  views::Label* label = new views::Label(
-      l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_NO_MESSAGES));
-  label->SetEnabledColor(message_center_style::kEmptyViewColor);
-  // "Roboto-Medium, 12sp" is specified in the mock.
-  label->SetFontList(
-      gfx::FontList().DeriveWithWeight(gfx::Font::Weight::MEDIUM));
-  label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-  label->SetSubpixelRenderingEnabled(false);
-  view->AddChildView(label);
-
-  view->SetPaintToLayer();
-  view->layer()->SetFillsBoundsOpaquely(false);
-
-  return view;
-}
-
-class MessageCenterScrollView : public views::ScrollView {
- public:
-  MessageCenterScrollView(MessageCenterView* owner) : owner_(owner) {}
-  ~MessageCenterScrollView() override = default;
-
- private:
-  // views::View:
-  void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
-    node_data->role = ax::mojom::Role::kDialog;
-    node_data->SetName(
-        l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_FOOTER_TITLE));
-  }
-
-  // views::ScrollBarController:
-  void ScrollToPosition(views::ScrollBar* source, int position) override {
-    views::ScrollView::ScrollToPosition(source, position);
-    owner_->UpdateScrollerShadowVisibility();
-  }
-
-  MessageCenterView* const owner_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageCenterScrollView);
-};
-
-// A view that displays a shadow at the bottom when |scroller_| is bounded.
-class ScrollShadowView : public views::View {
- public:
-  ScrollShadowView(int max_scroll_view_height, int button_height)
-      : max_scroll_view_height_(max_scroll_view_height),
-        button_height_(button_height) {
-    SetPaintToLayer();
-    layer()->SetFillsBoundsOpaquely(false);
-    set_can_process_events_within_subtree(false);
-  }
-  ~ScrollShadowView() override = default;
-
- protected:
-  void PaintChildren(const views::PaintInfo& paint_info) override {
-    views::View::PaintChildren(paint_info);
-
-    if (height() != max_scroll_view_height_)
-      return;
-
-    // Draw a shadow at the bottom of the viewport when scrolled.
-    DrawShadow(paint_info.context(),
-               gfx::Rect(0, height(), width(), button_height_));
-  }
-
- private:
-  // Draws a drop shadow above |shadowed_area|.
-  void DrawShadow(const ui::PaintContext& context,
-                  const gfx::Rect& shadowed_area) {
-    ui::PaintRecorder recorder(context, size());
-    gfx::Canvas* canvas = recorder.canvas();
-    cc::PaintFlags flags;
-    gfx::ShadowValues shadow;
-    shadow.emplace_back(gfx::Vector2d(0, kScrollShadowOffsetY),
-                        kScrollShadowBlur, kScrollShadowColor);
-    flags.setLooper(gfx::CreateShadowDrawLooper(shadow));
-    flags.setAntiAlias(true);
-    canvas->ClipRect(shadowed_area, SkClipOp::kDifference);
-    canvas->DrawRect(shadowed_area, flags);
-  }
-
-  const int max_scroll_view_height_;
-  const int button_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScrollShadowView);
-};
-
-}  // namespace
-
-// MessageCenterView ///////////////////////////////////////////////////////////
-
-MessageCenterView::MessageCenterView(MessageCenter* message_center,
-                                     int max_height)
-    : message_center_(message_center),
-      settings_visible_(false),
-      is_locked_(Shell::Get()->session_controller()->IsScreenLocked()) {
-  if (is_locked_ && !AshMessageCenterLockScreenController::IsEnabled())
-    mode_ = Mode::LOCKED;
-
-  message_center_->AddObserver(this);
-  set_notify_enter_exit_on_child(true);
-  SetFocusBehavior(views::View::FocusBehavior::NEVER);
-
-  button_bar_ = new MessageCenterButtonBar(this, message_center, is_locked_);
-  button_bar_->SetCloseAllButtonEnabled(false);
-
-  const int button_height = button_bar_->GetPreferredSize().height();
-  const int max_scroll_view_height = max_height - button_height;
-
-  scroller_shadow_ =
-      new ScrollShadowView(max_scroll_view_height, button_height);
-
-  scroller_ = new MessageCenterScrollView(this);
-  // Need to set the transparent background explicitly, since ScrollView has
-  // set the default opaque background color.
-  scroller_->SetBackgroundColor(SK_ColorTRANSPARENT);
-  scroller_->ClipHeightTo(kMinScrollViewHeight, max_scroll_view_height);
-  scroller_->SetVerticalScrollBar(new MessageCenterScrollBar(nullptr));
-
-  message_list_view_.reset(new MessageListView());
-  message_list_view_->SetBorderPadding();
-  message_list_view_->set_scroller(scroller_);
-  message_list_view_->set_owned_by_client();
-  message_list_view_->AddObserver(this);
-
-  // We want to swap the contents of the scroll view between the empty list
-  // view and the message list view, without constructing them afresh each
-  // time.  So, since the scroll view deletes old contents each time you
-  // set the contents (regardless of the |owned_by_client_| setting) we need
-  // an intermediate view for the contents whose children we can swap in and
-  // out.
-  views::View* scroller_contents = new views::View();
-  scroller_contents->SetLayoutManager(std::make_unique<views::FillLayout>());
-  scroller_contents->AddChildView(message_list_view_.get());
-  scroller_->SetContents(scroller_contents);
-
-  settings_view_ = new NotifierSettingsView();
-  settings_view_->SetBackground(
-      views::CreateSolidBackground(message_center_style::kBackgroundColor));
-
-  no_notifications_view_ = CreateEmptyNotificationView();
-
-  scroller_->SetVisible(false);  // Because it has no notifications at first.
-  settings_view_->SetVisible(mode_ == Mode::SETTINGS);
-  no_notifications_view_->SetVisible(mode_ == Mode::NO_NOTIFICATIONS);
-
-  AddChildView(no_notifications_view_);
-  AddChildView(scroller_);
-  AddChildView(scroller_shadow_);
-  AddChildView(settings_view_);
-  AddChildView(button_bar_);
-}
-
-MessageCenterView::~MessageCenterView() {
-  message_list_view_->RemoveObserver(this);
-
-  if (!is_closing_)
-    message_center_->RemoveObserver(this);
-}
-
-void MessageCenterView::SetNotifications(
-    const NotificationList::Notifications& notifications) {
-  if (is_closing_)
-    return;
-
-  int index = 0;
-  for (NotificationList::Notifications::const_iterator iter =
-           notifications.begin();
-       iter != notifications.end(); ++iter) {
-    AddNotificationAt(*(*iter), index++);
-
-    message_center_->DisplayedNotification(
-        (*iter)->id(), message_center::DISPLAY_SOURCE_MESSAGE_CENTER);
-    if (message_list_view_->GetNotificationCount() >=
-        kMaxVisibleNotifications) {
-      break;
-    }
-  }
-
-  Update(false /* animate */);
-  scroller_->RequestFocus();
-}
-
-void MessageCenterView::SetSettingsVisible(bool visible) {
-  settings_visible_ = visible;
-  Update(true /* animate */);
-}
-
-void MessageCenterView::ClearAllClosableNotifications() {
-  if (is_closing_)
-    return;
-
-  is_clearing_all_notifications_ = true;
-  UpdateButtonBarStatus();
-  SetViewHierarchyEnabled(scroller_, false);
-  message_list_view_->ClearAllClosableNotifications(
-      scroller_->GetVisibleRect());
-}
-
-void MessageCenterView::OnLockStateChanged(bool locked) {
-  is_locked_ = locked;
-  Update(true /* animate */);
-  // Refresh a11y information, because accessible name of the view changes.
-  NotifyAccessibilityEvent(ax::mojom::Event::kAriaAttributeChanged, true);
-}
-
-void MessageCenterView::OnAllNotificationsCleared() {
-  SetViewHierarchyEnabled(scroller_, true);
-  button_bar_->SetCloseAllButtonEnabled(false);
-
-  // The status of buttons will be updated after removing all notifications.
-
-  // Action by user.
-  message_center_->RemoveAllNotifications(
-      true /* by_user */, MessageCenter::RemoveType::NON_PINNED);
-  is_clearing_all_notifications_ = false;
-}
-
-size_t MessageCenterView::NumMessageViewsForTest() const {
-  return message_list_view_->GetNotificationCount();
-}
-
-void MessageCenterView::OnSettingsChanged() {
-  scroller_->InvalidateLayout();
-  PreferredSizeChanged();
-  Layout();
-}
-
-void MessageCenterView::SetIsClosing(bool is_closing) {
-  is_closing_ = is_closing;
-  if (is_closing)
-    message_center_->RemoveObserver(this);
-  else
-    message_center_->AddObserver(this);
-}
-
-void MessageCenterView::UpdateScrollerShadowVisibility() {
-  // |scroller_shadow_| is visible only if |scroller_| is not all scrolled.
-  scroller_shadow_->SetVisible(scroller_->contents()->height() +
-                                   scroller_->contents()->y() !=
-                               scroller_shadow_->height());
-}
-
-void MessageCenterView::Layout() {
-  if (is_closing_)
-    return;
-
-  int button_height = button_bar_->GetHeightForWidth(width());
-  int settings_height =
-      std::min(GetSettingsHeightForWidth(width()), height() - button_height);
-
-  // In order to keep the fix for https://crbug.com/767805 working,
-  // we have to always call SetBounds of scroller_.
-  // TODO(tetsui): Fix the bug above without calling SetBounds, as SetBounds
-  // invokes Layout() which is a heavy operation.
-  scroller_->SetBounds(0, 0, width(), height() - button_height);
-  scroller_shadow_->SetBounds(0, 0, width(), height() - button_height);
-  if (settings_view_->visible()) {
-    settings_view_->SetBounds(0, height() - settings_height, width(),
-                              settings_height);
-  }
-  if (no_notifications_view_->visible())
-    no_notifications_view_->SetBounds(0, 0, width(), kEmptyViewHeight);
-  button_bar_->SetBounds(0, height() - button_height - settings_height, width(),
-                         button_height);
-  if (GetWidget())
-    GetWidget()->GetRootView()->SchedulePaint();
-}
-
-gfx::Size MessageCenterView::CalculatePreferredSize() const {
-  int width = 0;
-  for (int i = 0; i < child_count(); ++i) {
-    const views::View* child = child_at(i);
-    if (child->visible())
-      width = std::max(width, child->GetPreferredSize().width());
-  }
-  return gfx::Size(width, GetHeightForWidth(width));
-}
-
-int MessageCenterView::GetHeightForWidth(int width) const {
-  if (settings_transition_animation_ &&
-      settings_transition_animation_->is_animating()) {
-    return button_bar_->GetHeightForWidth(width) +
-           GetContentHeightDuringAnimation();
-  }
-
-  return button_bar_->GetHeightForWidth(width) +
-         GetContentHeightForMode(mode_, width);
-}
-
-bool MessageCenterView::OnMouseWheel(const ui::MouseWheelEvent& event) {
-  // Do not rely on the default scroll event handler of ScrollView because
-  // the scroll happens only when the focus is on the ScrollView. The
-  // notification center will allow the scrolling even when the focus is on
-  // the buttons.
-  if (scroller_->bounds().Contains(event.location()))
-    return scroller_->OnMouseWheel(event);
-  return views::View::OnMouseWheel(event);
-}
-
-void MessageCenterView::OnMouseExited(const ui::MouseEvent& event) {
-  if (is_closing_)
-    return;
-
-  message_list_view_->ResetRepositionSession();
-  Update(true /* animate */);
-}
-
-void MessageCenterView::OnNotificationAdded(const std::string& id) {
-  int index = 0;
-  const NotificationList::Notifications& notifications =
-      message_center_->GetVisibleNotifications();
-  for (NotificationList::Notifications::const_iterator
-           iter = notifications.begin();
-       iter != notifications.end(); ++iter, ++index) {
-    if ((*iter)->id() == id) {
-      AddNotificationAt(*(*iter), index);
-      break;
-    }
-    if (message_list_view_->GetNotificationCount() >=
-        kMaxVisibleNotifications) {
-      break;
-    }
-  }
-  Update(true /* animate */);
-}
-
-void MessageCenterView::OnNotificationRemoved(const std::string& id,
-                                              bool by_user) {
-  auto view_pair = message_list_view_->GetNotificationById(id);
-  MessageView* view = view_pair.second;
-  if (!view)
-    return;
-  size_t index = view_pair.first;
-
-  // We skip repositioning during clear-all anomation, since we don't need keep
-  // positions.
-  if (by_user && !is_clearing_all_notifications_) {
-    gfx::RectF rect_f(view->x(), view->y(), view->width(), view->height());
-    views::View::ConvertRectToTarget(view, message_list_view_.get(), &rect_f);
-    message_list_view_->SetRepositionTarget(gfx::ToNearestRect(rect_f));
-    // Moves the keyboard focus to the next notification if the removed
-    // notification is focused so that the user can dismiss notifications
-    // without re-focusing by tab key.
-    if (view->IsCloseButtonFocused() || view->HasFocus()) {
-      views::View* next_focused_view = nullptr;
-      if (message_list_view_->GetNotificationCount() > index + 1)
-        next_focused_view = message_list_view_->GetNotificationAt(index + 1);
-      else if (index > 0)
-        next_focused_view = message_list_view_->GetNotificationAt(index - 1);
-
-      if (next_focused_view) {
-        if (view->IsCloseButtonFocused()) {
-          // Safe cast since all views in MessageListView are MessageViews.
-          static_cast<MessageView*>(next_focused_view)
-              ->RequestFocusOnCloseButton();
-        } else {
-          next_focused_view->RequestFocus();
-        }
-      }
-    }
-  }
-  message_list_view_->RemoveNotification(view);
-  Update(true /* animate */);
-}
-
-// This is a separate function so we can override it in tests.
-bool MessageCenterView::SetRepositionTarget() {
-  // Set the item on the mouse cursor as the reposition target so that it
-  // should stick to the current position over the update.
-  if (message_list_view_->IsMouseHovered()) {
-    size_t count = message_list_view_->GetNotificationCount();
-    for (size_t i = 0; i < count; ++i) {
-      const views::View* hover_view = message_list_view_->GetNotificationAt(i);
-
-      if (hover_view->IsMouseHovered()) {
-        message_list_view_->SetRepositionTarget(hover_view->bounds());
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-void MessageCenterView::OnNotificationUpdated(const std::string& id) {
-  // If there is no reposition target anymore, make sure to reset the reposition
-  // session.
-  if (!SetRepositionTarget())
-    message_list_view_->ResetRepositionSession();
-
-  UpdateNotification(id);
-}
-
-void MessageCenterView::OnQuietModeChanged(bool is_quiet_mode) {
-  settings_view_->SetQuietModeState(is_quiet_mode);
-  button_bar_->SetQuietModeState(is_quiet_mode);
-}
-
-void MessageCenterView::AnimationEnded(const gfx::Animation* animation) {
-  DCHECK_EQ(animation, settings_transition_animation_.get());
-
-  if (source_view_) {
-    source_view_->SetVisible(false);
-  }
-  if (target_view_)
-    target_view_->SetVisible(true);
-  if (settings_transition_animation_)
-    NotifyAnimationState(false /* animating */);
-  settings_transition_animation_.reset();
-  PreferredSizeChanged();
-  Layout();
-
-  // We should update minimum fixed height based on new |scroller_| height.
-  // This is required when switching between message list and settings panel.
-  if (!scroller_->visible())
-    message_list_view_->ResetRepositionSession();
-}
-
-void MessageCenterView::AnimationProgressed(const gfx::Animation* animation) {
-  DCHECK_EQ(animation, settings_transition_animation_.get());
-  PreferredSizeChanged();
-  Layout();
-  SchedulePaint();
-}
-
-void MessageCenterView::AnimationCanceled(const gfx::Animation* animation) {
-  DCHECK_EQ(animation, settings_transition_animation_.get());
-  AnimationEnded(animation);
-}
-
-void MessageCenterView::OnViewPreferredSizeChanged(views::View* observed_view) {
-  DCHECK_EQ(std::string(MessageView::kViewClassName),
-            observed_view->GetClassName());
-  UpdateNotification(
-      static_cast<MessageView*>(observed_view)->notification_id());
-}
-
-void MessageCenterView::AddNotificationAt(const Notification& notification,
-                                          int index) {
-  MessageView* view = message_center::MessageViewFactory::Create(notification);
-  // Not top-level.
-  view->SetIsNested();
-  view->AddObserver(this);
-  view->set_scroller(scroller_);
-  message_list_view_->AddNotificationAt(view, index);
-}
-
-void MessageCenterView::Update(bool animate) {
-  bool no_message_views = (message_list_view_->GetNotificationCount() == 0);
-
-  if (is_locked_ && !AshMessageCenterLockScreenController::IsEnabled())
-    SetVisibilityMode(Mode::LOCKED, animate);
-  else if (settings_visible_)
-    SetVisibilityMode(Mode::SETTINGS, animate);
-  else if (no_message_views)
-    SetVisibilityMode(Mode::NO_NOTIFICATIONS, animate);
-  else
-    SetVisibilityMode(Mode::NOTIFICATIONS, animate);
-
-  UpdateButtonBarStatus();
-
-  if (scroller_->visible())
-    scroller_->InvalidateLayout();
-  PreferredSizeChanged();
-  Layout();
-}
-
-void MessageCenterView::SetVisibilityMode(Mode mode, bool animate) {
-  if (is_closing_)
-    return;
-
-  if (mode == mode_)
-    return;
-
-  switch (mode_) {
-    case Mode::NOTIFICATIONS:
-      source_view_ = scroller_;
-      break;
-    case Mode::SETTINGS:
-      source_view_ = settings_view_;
-      break;
-    case Mode::LOCKED:
-      source_view_ = nullptr;
-      break;
-    case Mode::NO_NOTIFICATIONS:
-      source_view_ = no_notifications_view_;
-      break;
-  }
-
-  switch (mode) {
-    case Mode::NOTIFICATIONS:
-      target_view_ = scroller_;
-      break;
-    case Mode::SETTINGS:
-      target_view_ = settings_view_;
-      break;
-    case Mode::LOCKED:
-      target_view_ = nullptr;
-      break;
-    case Mode::NO_NOTIFICATIONS:
-      target_view_ = no_notifications_view_;
-      break;
-  }
-
-  source_height_ = GetContentHeightForMode(mode_, width());
-  target_height_ = GetContentHeightForMode(mode, width());
-
-  mode_ = mode;
-
-  int contents_max_height =
-      max_height_ - button_bar_->GetPreferredSize().height();
-  source_height_ = std::min(contents_max_height, source_height_);
-  target_height_ = std::min(contents_max_height, target_height_);
-
-  if (source_view_)
-    source_view_->SetVisible(true);
-  if (target_view_)
-    target_view_->SetVisible(true);
-
-  if (!animate || disable_animation_for_testing) {
-    AnimationEnded(nullptr);
-    return;
-  }
-
-  NotifyAnimationState(true /* animating */);
-
-  settings_transition_animation_ = std::make_unique<gfx::SlideAnimation>(this);
-  settings_transition_animation_->SetSlideDuration(
-      message_center_style::kSettingsTransitionDurationMs);
-  settings_transition_animation_->SetTweenType(gfx::Tween::EASE_IN_OUT);
-  settings_transition_animation_->Show();
-}
-
-void MessageCenterView::UpdateButtonBarStatus() {
-  // Disables all buttons during animation of cleaning of all notifications.
-  if (is_clearing_all_notifications_) {
-    button_bar_->SetSettingsAndQuietModeButtonsEnabled(false);
-    button_bar_->SetCloseAllButtonEnabled(false);
-    return;
-  }
-
-  button_bar_->SetBackArrowVisible(mode_ == Mode::SETTINGS);
-  button_bar_->SetIsLocked(is_locked_);
-
-  EnableCloseAllIfAppropriate();
-}
-
-void MessageCenterView::EnableCloseAllIfAppropriate() {
-  if (mode_ == Mode::NOTIFICATIONS) {
-    bool no_closable_views = true;
-    size_t count = message_list_view_->GetNotificationCount();
-    for (size_t i = 0; i < count; ++i) {
-      if (message_list_view_->GetNotificationAt(i)->GetMode() ==
-          MessageView::Mode::NORMAL) {
-        no_closable_views = false;
-        break;
-      }
-    }
-    button_bar_->SetCloseAllButtonEnabled(!no_closable_views);
-  } else {
-    // Disable the close-all button since no notification is visible.
-    button_bar_->SetCloseAllButtonEnabled(false);
-  }
-}
-
-void MessageCenterView::SetNotificationViewForTest(MessageView* view) {
-  message_list_view_->AddNotificationAt(view, 0);
-}
-
-void MessageCenterView::UpdateNotification(const std::string& id) {
-  MessageView* view = message_list_view_->GetNotificationById(id).second;
-  if (!view)
-    return;
-  Notification* notification = message_center_->FindVisibleNotificationById(id);
-  if (notification) {
-    int old_width = view->width();
-    int old_height = view->height();
-    MessageView::Mode old_mode = view->GetMode();
-    message_list_view_->UpdateNotification(view, *notification);
-    if (view->GetHeightForWidth(old_width) != old_height) {
-      Update(true /* animate */);
-    } else if (view->GetMode() != old_mode) {
-      // Animate flag is false, since the pinned flag transition doesn't need
-      // animation.
-      Update(false /* animate */);
-    }
-  }
-
-  // Notify accessibility that the contents have changed.
-  view->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
-}
-
-void MessageCenterView::NotifyAnimationState(bool animating) {
-  size_t count = message_list_view_->GetNotificationCount();
-  for (size_t i = 0; i < count; ++i) {
-    MessageView* view = message_list_view_->GetNotificationAt(i);
-
-    if (animating)
-      view->OnContainerAnimationStarted();
-    else
-      view->OnContainerAnimationEnded();
-
-    // Ensure that a notification is not removed or added during iteration.
-    DCHECK_EQ(count, message_list_view_->GetNotificationCount());
-  }
-}
-
-int MessageCenterView::GetSettingsHeightForWidth(int width) const {
-  if (settings_transition_animation_ &&
-      settings_transition_animation_->is_animating() &&
-      (source_view_ == settings_view_ || target_view_ == settings_view_)) {
-    return settings_transition_animation_->CurrentValueBetween(
-        target_view_ == settings_view_ ? 0 : source_height_,
-        source_view_ == settings_view_ ? 0 : target_height_);
-  } else {
-    return mode_ == Mode::SETTINGS ? settings_view_->GetHeightForWidth(width)
-                                   : 0;
-  }
-}
-
-int MessageCenterView::GetContentHeightDuringAnimation() const {
-  DCHECK(settings_transition_animation_);
-  int contents_height = settings_transition_animation_->CurrentValueBetween(
-      target_view_ == settings_view_ ? 0 : source_height_,
-      source_view_ == settings_view_ ? 0 : target_height_);
-  if (target_view_ == settings_view_)
-    contents_height = std::max(source_height_, contents_height);
-  if (source_view_ == settings_view_)
-    contents_height = std::max(target_height_, contents_height);
-  return contents_height;
-}
-
-int MessageCenterView::GetContentHeightForMode(Mode mode, int width) const {
-  switch (mode) {
-    case Mode::NOTIFICATIONS:
-      return scroller_->GetHeightForWidth(width);
-    case Mode::SETTINGS:
-      return settings_view_->GetHeightForWidth(width);
-    case Mode::LOCKED:
-      return 0;
-    case Mode::NO_NOTIFICATIONS:
-      return kEmptyViewHeight;
-  }
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/message_center_view.h b/ash/system/message_center/message_center_view.h
deleted file mode 100644
index b812a22..0000000
--- a/ash/system/message_center/message_center_view.h
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_VIEW_H_
-#define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_VIEW_H_
-
-#include <stddef.h>
-
-#include "ash/ash_export.h"
-#include "ash/session/session_observer.h"
-#include "ash/system/message_center/message_list_view.h"
-#include "base/macros.h"
-#include "ui/gfx/animation/animation_delegate.h"
-#include "ui/message_center/message_center_observer.h"
-#include "ui/message_center/notification_list.h"
-#include "ui/views/focus/focus_manager.h"
-#include "ui/views/view.h"
-
-namespace gfx {
-class SlideAnimation;
-}  // namespace gfx
-
-namespace message_center {
-
-class MessageCenter;
-class MessageView;
-
-}  // namespace message_center
-
-namespace ash {
-
-class ArcNotificationContentViewTest;
-class MessageCenterButtonBar;
-class NotifierSettingsView;
-
-// Container for all the top-level views in the notification center, such as the
-// button bar, settings view, scrol view, and message list view.  Acts as a
-// controller/delegate for the message list view, passing data back and forth to
-// message center.
-class ASH_EXPORT MessageCenterView
-    : public views::View,
-      public message_center::MessageCenterObserver,
-      public SessionObserver,
-      public MessageListView::Observer,
-      public gfx::AnimationDelegate,
-      public views::ViewObserver {
- public:
-  MessageCenterView(message_center::MessageCenter* message_center,
-                    int max_height);
-  ~MessageCenterView() override;
-
-  void SetNotifications(
-      const message_center::NotificationList::Notifications& notifications);
-
-  void ClearAllClosableNotifications();
-
-  size_t NumMessageViewsForTest() const;
-
-  void SetSettingsVisible(bool visible);
-  void OnSettingsChanged();
-  bool settings_visible() const { return settings_visible_; }
-
-  void SetIsClosing(bool is_closing);
-
-  void SetMaxHeight(int max_height) { max_height_ = max_height; }
-
-  void UpdateScrollerShadowVisibility();
-
-  static const size_t kMaxVisibleNotifications;
-
- protected:
-  // Potentially sets the reposition target, and then returns whether or not it
-  // was set.
-  virtual bool SetRepositionTarget();
-
-  // Overridden from views::View:
-  void Layout() override;
-  gfx::Size CalculatePreferredSize() const override;
-  int GetHeightForWidth(int width) const override;
-  bool OnMouseWheel(const ui::MouseWheelEvent& event) override;
-  void OnMouseExited(const ui::MouseEvent& event) override;
-
-  // Overridden from MessageCenterObserver:
-  void OnNotificationAdded(const std::string& id) override;
-  void OnNotificationRemoved(const std::string& id, bool by_user) override;
-  void OnNotificationUpdated(const std::string& id) override;
-  void OnQuietModeChanged(bool is_quiet_mode) override;
-
-  // Overridden from SessionObserver:
-  void OnLockStateChanged(bool locked) override;
-
-  // Overridden from MessageListView::Observer:
-  void OnAllNotificationsCleared() override;
-
-  // Overridden from gfx::AnimationDelegate:
-  void AnimationEnded(const gfx::Animation* animation) override;
-  void AnimationProgressed(const gfx::Animation* animation) override;
-  void AnimationCanceled(const gfx::Animation* animation) override;
-
-  // Overridden from views::ViewObserver:
-  void OnViewPreferredSizeChanged(views::View* observed_view) override;
-
- private:
-  friend class ArcNotificationContentViewTest;
-  friend class MediaNotificationViewTest;
-  friend class MessageCenterViewTest;
-
-  // NOTIFICATIONS: Normal notification list (MessageListView) is shown.
-  //   There should be at least one notification.
-  // SETTINGS: Notifier settings (NotifierSettingsView) is shown.
-  // LOCKED: The computer is in the lock screen. No content view is shown.
-  // NO_NOTIFICATIONS: "All done" message (EmptyNotifcationView) is shown.
-  //   There should be no notification.
-  enum class Mode { NOTIFICATIONS, SETTINGS, LOCKED, NO_NOTIFICATIONS };
-
-  static bool disable_animation_for_testing;
-
-  void AddNotificationAt(const message_center::Notification& notification,
-                         int index);
-  void Update(bool animate);
-  void SetVisibilityMode(Mode mode, bool animate);
-  void UpdateButtonBarStatus();
-  void EnableCloseAllIfAppropriate();
-  void SetNotificationViewForTest(message_center::MessageView* view);
-  void UpdateNotification(const std::string& notification_id);
-  void NotifyAnimationState(bool animating);
-
-  // There are three patterns for animation.
-  // - Only MessageCenterView height changes.
-  // - Both MessageCenterview and NotifierSettingsView moves at same velocity.
-  // - Only NotifierSettingsView moves.
-  // Thus, these two methods are needed.
-  int GetSettingsHeightForWidth(int width) const;
-  int GetContentHeightDuringAnimation() const;
-
-  // Returns the height for the given |width| of the view correspond to |mode|
-  // e.g. |settings_view_|.
-  int GetContentHeightForMode(Mode mode, int width) const;
-
-  message_center::MessageCenter* message_center_;
-
-  // Child views.
-  views::ScrollView* scroller_ = nullptr;
-  std::unique_ptr<MessageListView> message_list_view_;
-  views::View* scroller_shadow_ = nullptr;
-  NotifierSettingsView* settings_view_ = nullptr;
-  views::View* no_notifications_view_ = nullptr;
-  MessageCenterButtonBar* button_bar_ = nullptr;
-
-  // Data for transition animation between settings view and message list.
-  bool settings_visible_;
-
-  // Animation managing transition between message center and settings (and vice
-  // versa).
-  std::unique_ptr<gfx::SlideAnimation> settings_transition_animation_;
-
-  // Helper data to keep track of the transition between settings and
-  // message center views.
-  views::View* source_view_ = nullptr;
-  int source_height_ = 0;
-  views::View* target_view_ = nullptr;
-  int target_height_ = 0;
-
-  // Maximum height set for the MessageCenterBubble by SetMaxHeight.
-  int max_height_ = 0;
-
-  // True when the widget is closing so that further operations should be
-  // ignored.
-  bool is_closing_ = false;
-
-  bool is_clearing_all_notifications_ = false;
-  bool is_locked_;
-
-  // Current view mode. During animation, it is the target mode.
-  Mode mode_ = Mode::NO_NOTIFICATIONS;
-
-  ScopedSessionObserver session_observer_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(MessageCenterView);
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_VIEW_H_
diff --git a/ash/system/message_center/message_center_view_unittest.cc b/ash/system/message_center/message_center_view_unittest.cc
deleted file mode 100644
index c7aa38f..0000000
--- a/ash/system/message_center/message_center_view_unittest.cc
+++ /dev/null
@@ -1,1114 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/message_center_view.h"
-
-#include <map>
-#include <memory>
-#include <utility>
-
-#include "ash/public/cpp/ash_features.h"
-#include "ash/public/cpp/ash_pref_names.h"
-#include "ash/session/session_controller.h"
-#include "ash/shell.h"
-#include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
-#include "ash/system/message_center/message_center_button_bar.h"
-#include "ash/system/message_center/message_center_style.h"
-#include "ash/system/message_center/message_list_view.h"
-#include "ash/test/ash_test_base.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "components/prefs/pref_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/message_center/fake_message_center.h"
-#include "ui/message_center/notification_list.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/public/cpp/notification.h"
-#include "ui/message_center/public/cpp/notification_types.h"
-#include "ui/message_center/views/notification_view.h"
-#include "ui/views/animation/bounds_animator_observer.h"
-#include "ui/views/widget/widget.h"
-
-namespace ash {
-
-using message_center::FakeMessageCenter;
-using message_center::MessageCenter;
-using message_center::MessageView;
-using message_center::Notification;
-using message_center::NotificationList;
-using message_center::NotificationView;
-using message_center::NotifierId;
-using message_center::NOTIFICATION_TYPE_SIMPLE;
-
-namespace {
-
-const char* kNotificationId1 = "notification id 1";
-const char* kNotificationId2 = "notification id 2";
-
-// Plain button bar height (56)
-const int kLockedMessageCenterViewHeight = 56;
-
-// Plain button bar height (56) + Empty view (96)
-const int kEmptyMessageCenterViewHeight = 152;
-
-/* Types **********************************************************************/
-
-enum CallType { GET_PREFERRED_SIZE, GET_HEIGHT_FOR_WIDTH, LAYOUT };
-
-class DummyEvent : public ui::Event {
- public:
-  DummyEvent() : Event(ui::ET_UNKNOWN, base::TimeTicks(), 0) {}
-  ~DummyEvent() override = default;
-};
-
-/* Instrumented/Mock NotificationView subclass ********************************/
-
-class MockNotificationView : public NotificationView {
- public:
-  class Test {
-   public:
-    virtual void RegisterCall(CallType type) = 0;
-  };
-
-  explicit MockNotificationView(const Notification& notification, Test* test);
-  ~MockNotificationView() override;
-
-  gfx::Size CalculatePreferredSize() const override;
-  int GetHeightForWidth(int w) const override;
-  void Layout() override;
-
- private:
-  Test* test_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockNotificationView);
-};
-
-MockNotificationView::MockNotificationView(const Notification& notification,
-                                           Test* test)
-    : NotificationView(notification), test_(test) {}
-
-MockNotificationView::~MockNotificationView() = default;
-
-gfx::Size MockNotificationView::CalculatePreferredSize() const {
-  test_->RegisterCall(GET_PREFERRED_SIZE);
-  DCHECK(child_count() > 0);
-  return NotificationView::CalculatePreferredSize();
-}
-
-int MockNotificationView::GetHeightForWidth(int width) const {
-  test_->RegisterCall(GET_HEIGHT_FOR_WIDTH);
-  DCHECK(child_count() > 0);
-  return NotificationView::GetHeightForWidth(width);
-}
-
-void MockNotificationView::Layout() {
-  test_->RegisterCall(LAYOUT);
-  DCHECK(child_count() > 0);
-  NotificationView::Layout();
-}
-
-class FakeMessageCenterImpl : public FakeMessageCenter {
- public:
-  const NotificationList::Notifications& GetVisibleNotifications() override {
-    return visible_notifications_;
-  }
-  void SetVisibleNotifications(NotificationList::Notifications notifications) {
-    visible_notifications_ = notifications;
-  }
-  void RemoveAllNotifications(bool by_user, RemoveType type) override {
-    if (type == RemoveType::NON_PINNED)
-      remove_all_closable_notification_called_ = true;
-  }
-  bool remove_all_closable_notification_called_ = false;
-  NotificationList::Notifications visible_notifications_;
-};
-
-// This is the class we are testing, but we need to override some functions
-// in it, hence MockMessageCenterView.
-class MockMessageCenterView : public MessageCenterView {
- public:
-  MockMessageCenterView(MessageCenter* message_center, int max_height);
-
-  bool SetRepositionTarget() override;
-
-  void PreferredSizeChanged() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockMessageCenterView);
-};
-
-MockMessageCenterView::MockMessageCenterView(MessageCenter* message_center,
-                                             int max_height)
-    : MessageCenterView(message_center, max_height) {}
-
-// Always say that the current reposition session is still active, by
-// returning true. Normally the reposition session is set based on where the
-// mouse is hovering.
-bool MockMessageCenterView::SetRepositionTarget() {
-  return true;
-}
-
-void MockMessageCenterView::PreferredSizeChanged() {
-  SetSize(GetPreferredSize());
-  MessageCenterView::PreferredSizeChanged();
-}
-
-}  // namespace
-
-/* Test fixture ***************************************************************/
-
-class MessageCenterViewTest : public AshTestBase,
-                              public testing::WithParamInterface<bool>,
-                              public MockNotificationView::Test,
-                              views::BoundsAnimatorObserver {
- public:
-  // Expose the private enum class MessageCenter::Mode for this test.
-  using Mode = MessageCenterView::Mode;
-
-  MessageCenterViewTest();
-  ~MessageCenterViewTest() override;
-
-  void SetUp() override;
-  void TearDown() override;
-
-  NotificationList::Notifications Notifications();
-  MessageCenterView* GetMessageCenterView();
-  MessageListView* GetMessageListView();
-  FakeMessageCenterImpl* GetMessageCenter() const;
-  MessageView* GetNotificationView(const std::string& id);
-  views::BoundsAnimator* GetAnimator();
-  int GetNotificationCount();
-  int GetCallCount(CallType type);
-  int GetCalculatedMessageListViewHeight();
-  void SetLockedState(bool locked);
-  Mode GetMessageCenterViewInternalMode();
-  void AddNotification(std::unique_ptr<Notification> notification);
-  void RemoveNotification(const std::string& notification_id, bool by_user);
-  void UpdateNotification(const std::string& notification_id,
-                          std::unique_ptr<Notification> notification);
-
-  // Overridden from MockNotificationView::Test
-  void RegisterCall(CallType type) override;
-
-  // Overridden from views::BoundsAnimatorObserver
-  void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override{};
-  void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override;
-
-  void FireOnMouseExitedEvent();
-
-  void LogBounds(int depth, views::View* view);
-
-  MessageCenterButtonBar* GetButtonBar() const;
-
-  void RemoveDefaultNotifications();
-
-  void WaitForAnimationToFinish();
-
-  void SetLockScreenNotificationsEnabled();
-
- private:
-  views::View* MakeParent(views::View* child1, views::View* child2);
-
-  // The ownership map of notifications; the key is the id.
-  std::map<std::string, std::unique_ptr<Notification>> notifications_;
-  std::unique_ptr<views::Widget> widget_;
-  std::unique_ptr<MockMessageCenterView> message_center_view_;
-  std::unique_ptr<FakeMessageCenterImpl> message_center_;
-  std::map<CallType, int> callCounts_;
-
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageCenterViewTest);
-};
-
-MessageCenterViewTest::MessageCenterViewTest() = default;
-
-MessageCenterViewTest::~MessageCenterViewTest() = default;
-
-void MessageCenterViewTest::SetUp() {
-  AshTestBase::SetUp();
-
-  MessageCenterView::disable_animation_for_testing = true;
-  message_center_.reset(new FakeMessageCenterImpl());
-
-  // Create a dummy notification.
-  std::unique_ptr<Notification> notification1 = std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"), gfx::Image(),
-      base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr);
-
-  std::unique_ptr<Notification> notification2 = std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-      base::UTF8ToUTF16("title2"), base::UTF8ToUTF16("message2"), gfx::Image(),
-      base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr);
-
-  // ...and a list for it.
-  notifications_[std::string(kNotificationId1)] = std::move(notification1);
-  notifications_[std::string(kNotificationId2)] = std::move(notification2);
-  NotificationList::Notifications notifications = Notifications();
-  message_center_->SetVisibleNotifications(notifications);
-
-  // Then create a new MockMessageCenterView with that single notification.
-  message_center_view_.reset(
-      new MockMessageCenterView(message_center_.get(), 600));
-  GetMessageCenterView()->SetBounds(0, 0, 380, 100);
-  message_center_view_->SetNotifications(notifications);
-  message_center_view_->set_owned_by_client();
-
-  widget_.reset(new views::Widget());
-  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-  params.bounds = gfx::Rect(50, 50, 650, 650);
-  params.context = CurrentContext();
-  widget_->Init(params);
-  views::View* root = widget_->GetRootView();
-  root->AddChildView(message_center_view_.get());
-  widget_->Show();
-  widget_->Activate();
-
-  GetAnimator()->AddObserver(this);
-
-  WaitForAnimationToFinish();
-}
-
-void MessageCenterViewTest::TearDown() {
-  GetAnimator()->RemoveObserver(this);
-  widget_->CloseNow();
-  widget_.reset();
-  message_center_view_.reset();
-  notifications_.clear();
-  AshTestBase::TearDown();
-}
-
-NotificationList::Notifications MessageCenterViewTest::Notifications() {
-  NotificationList::Notifications result;
-  for (const auto& notification_pair : notifications_)
-    result.insert(notification_pair.second.get());
-
-  return result;
-}
-
-MessageCenterView* MessageCenterViewTest::GetMessageCenterView() {
-  return message_center_view_.get();
-}
-
-MessageListView* MessageCenterViewTest::GetMessageListView() {
-  return message_center_view_->message_list_view_.get();
-}
-
-FakeMessageCenterImpl* MessageCenterViewTest::GetMessageCenter() const {
-  return message_center_.get();
-}
-
-MessageView* MessageCenterViewTest::GetNotificationView(const std::string& id) {
-  return GetMessageListView()->GetNotificationById(id).second;
-}
-
-int MessageCenterViewTest::GetCalculatedMessageListViewHeight() {
-  return GetMessageListView()->GetHeightForWidth(GetMessageListView()->width());
-}
-
-MessageCenterViewTest::Mode
-MessageCenterViewTest::GetMessageCenterViewInternalMode() {
-  return GetMessageCenterView()->mode_;
-}
-
-views::BoundsAnimator* MessageCenterViewTest::GetAnimator() {
-  return &GetMessageListView()->animator_;
-}
-
-int MessageCenterViewTest::GetNotificationCount() {
-  return 2;
-}
-
-int MessageCenterViewTest::GetCallCount(CallType type) {
-  return callCounts_[type];
-}
-
-void MessageCenterViewTest::SetLockedState(bool locked) {
-  GetMessageCenterView()->OnLockStateChanged(locked);
-}
-
-void MessageCenterViewTest::AddNotification(
-    std::unique_ptr<Notification> notification) {
-  std::string notification_id = notification->id();
-  notifications_[notification_id] = std::move(notification);
-  message_center_->SetVisibleNotifications(Notifications());
-  message_center_view_->OnNotificationAdded(notification_id);
-}
-
-void MessageCenterViewTest::UpdateNotification(
-    const std::string& notification_id,
-    std::unique_ptr<Notification> notification) {
-  DCHECK_EQ(notification_id, notification->id());
-  notifications_[notification_id] = std::move(notification);
-
-  message_center_->SetVisibleNotifications(Notifications());
-  message_center_view_->OnNotificationUpdated(notification_id);
-}
-
-void MessageCenterViewTest::RemoveNotification(
-    const std::string& notification_id,
-    bool by_user) {
-  notifications_.erase(notification_id);
-
-  message_center_->SetVisibleNotifications(Notifications());
-  message_center_view_->OnNotificationRemoved(notification_id, by_user);
-}
-
-void MessageCenterViewTest::RegisterCall(CallType type) {
-  callCounts_[type] += 1;
-}
-
-void MessageCenterViewTest::OnBoundsAnimatorDone(
-    views::BoundsAnimator* animator) {
-  if (run_loop_)
-    run_loop_->QuitWhenIdle();
-}
-
-void MessageCenterViewTest::FireOnMouseExitedEvent() {
-  ui::MouseEvent dummy_event(
-      ui::ET_MOUSE_EXITED /* type */, gfx::Point(0, 0) /* location */,
-      gfx::Point(0, 0) /* root location */, base::TimeTicks() /* time_stamp */,
-      0 /* flags */, 0 /*changed_button_flags */);
-  message_center_view_->OnMouseExited(dummy_event);
-}
-
-void MessageCenterViewTest::LogBounds(int depth, views::View* view) {
-  base::string16 inset;
-  for (int i = 0; i < depth; ++i)
-    inset.append(base::UTF8ToUTF16("  "));
-  gfx::Rect bounds = view->bounds();
-  DVLOG(0) << inset << bounds.width() << " x " << bounds.height() << " @ "
-           << bounds.x() << ", " << bounds.y();
-  for (int i = 0; i < view->child_count(); ++i)
-    LogBounds(depth + 1, view->child_at(i));
-}
-
-MessageCenterButtonBar* MessageCenterViewTest::GetButtonBar() const {
-  return message_center_view_->button_bar_;
-}
-
-void MessageCenterViewTest::RemoveDefaultNotifications() {
-  RemoveNotification(kNotificationId1, false);
-  RemoveNotification(kNotificationId2, false);
-}
-
-void MessageCenterViewTest::WaitForAnimationToFinish() {
-  while (GetAnimator()->IsAnimating()) {
-    run_loop_ = std::make_unique<base::RunLoop>();
-    run_loop_->Run();
-  }
-}
-
-void MessageCenterViewTest::SetLockScreenNotificationsEnabled() {
-  scoped_feature_list_.InitAndEnableFeature(features::kLockScreenNotifications);
-
-  PrefService* user_prefs =
-      Shell::Get()->session_controller()->GetActivePrefService();
-  user_prefs->SetString(prefs::kMessageCenterLockScreenMode,
-                        prefs::kMessageCenterLockScreenModeShow);
-
-  ASSERT_TRUE(AshMessageCenterLockScreenController::IsEnabled());
-}
-
-/* Unit tests *****************************************************************/
-
-TEST_F(MessageCenterViewTest, CallTest) {
-  // Verify that this didn't generate more than 2 Layout() call per descendant
-  // NotificationView or more than a total of 20 GetPreferredSize() and
-  // GetHeightForWidth() calls per descendant NotificationView. 20 is a very
-  // large number corresponding to the current reality. That number will be
-  // ratcheted down over time as the code improves.
-  EXPECT_LE(GetCallCount(LAYOUT), GetNotificationCount() * 2);
-  EXPECT_LE(
-      GetCallCount(GET_PREFERRED_SIZE) + GetCallCount(GET_HEIGHT_FOR_WIDTH),
-      GetNotificationCount() * 20);
-}
-
-TEST_F(MessageCenterViewTest, Size) {
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  EXPECT_EQ(GetMessageListView()->height(),
-            GetCalculatedMessageListViewHeight());
-
-  int width =
-      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
-  EXPECT_EQ(
-      GetMessageListView()->height(),
-      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
-          message_center::kMarginBetweenItemsInList +
-          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
-          GetMessageListView()->GetInsets().height());
-}
-
-// TODO(tetsui): The test is broken because there's no guarantee anymore that
-// height would change after setting longer message, as NotificationViewMD
-// implements collapse / expand functionality of long message.
-TEST_F(MessageCenterViewTest, DISABLED_SizeAfterUpdate) {
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  int width =
-      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
-
-  std::unique_ptr<Notification> notification = std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr);
-
-  EXPECT_EQ(
-      GetMessageListView()->height(),
-      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
-          message_center::kMarginBetweenItemsInList +
-          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
-          GetMessageListView()->GetInsets().height());
-
-  int previous_height = GetMessageListView()->height();
-
-  UpdateNotification(kNotificationId2, std::move(notification));
-
-  WaitForAnimationToFinish();
-
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  EXPECT_EQ(GetMessageListView()->height(),
-            GetCalculatedMessageListViewHeight());
-
-  // The size must be changed, since the new string is longer than the old one.
-  EXPECT_NE(previous_height, GetMessageListView()->height());
-
-  EXPECT_EQ(
-      GetMessageListView()->height(),
-      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
-          message_center::kMarginBetweenItemsInList +
-          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
-          GetMessageListView()->GetInsets().height());
-}
-
-TEST_F(MessageCenterViewTest, SizeAfterUpdateBelowWithRepositionTarget) {
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  // Make sure that notification 2 is placed above notification 1.
-  EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
-            GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
-
-  GetMessageListView()->SetRepositionTarget(
-      GetNotificationView(kNotificationId1)->GetBoundsInScreen());
-
-  std::unique_ptr<Notification> notification = std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr);
-  UpdateNotification(kNotificationId2, std::move(notification));
-
-  WaitForAnimationToFinish();
-
-  int width =
-      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
-  EXPECT_EQ(
-      GetMessageListView()->height(),
-      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
-          message_center::kMarginBetweenItemsInList +
-          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
-          GetMessageListView()->GetInsets().height());
-}
-
-TEST_F(MessageCenterViewTest, SizeAfterUpdateOfRepositionTarget) {
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  // Make sure that notification 2 is placed above notification 1.
-  EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
-            GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
-
-  GetMessageListView()->SetRepositionTarget(
-      GetNotificationView(kNotificationId1)->GetBoundsInScreen());
-
-  std::unique_ptr<Notification> notification = std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr);
-  UpdateNotification(kNotificationId1, std::move(notification));
-
-  WaitForAnimationToFinish();
-
-  int width =
-      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
-  EXPECT_EQ(
-      GetMessageListView()->height(),
-      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
-          message_center::kMarginBetweenItemsInList +
-          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
-          GetMessageListView()->GetInsets().height());
-}
-
-TEST_F(MessageCenterViewTest, SizeAfterRemove) {
-  int original_height = GetMessageListView()->height();
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  RemoveNotification(kNotificationId1, false);
-
-  WaitForAnimationToFinish();
-
-  EXPECT_EQ(1, GetMessageListView()->child_count());
-
-  EXPECT_FALSE(GetNotificationView(kNotificationId1));
-  EXPECT_TRUE(GetNotificationView(kNotificationId2));
-  EXPECT_EQ(original_height, GetMessageListView()->height());
-}
-
-TEST_F(MessageCenterViewTest, PositionAfterUpdate) {
-  // Make sure that the notification 2 is placed above the notification 1.
-  EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
-            GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
-
-  int previous_vertical_pos_from_bottom =
-      GetMessageListView()->height() -
-      GetNotificationView(kNotificationId1)->GetBoundsInScreen().y();
-  GetMessageListView()->SetRepositionTarget(
-      GetNotificationView(kNotificationId1)->parent()->bounds());
-
-  std::unique_ptr<Notification> notification = std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr);
-  UpdateNotification(kNotificationId2, std::move(notification));
-
-  WaitForAnimationToFinish();
-
-  // The vertical position of the target from bottom should be kept over change.
-  int current_vertical_pos_from_bottom =
-      GetMessageListView()->height() -
-      GetNotificationView(kNotificationId1)->GetBoundsInScreen().y();
-  EXPECT_EQ(previous_vertical_pos_from_bottom,
-            current_vertical_pos_from_bottom);
-}
-
-TEST_F(MessageCenterViewTest, PositionAfterRemove) {
-  // Make sure that the notification 2 is placed above the notification 1.
-  EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
-            GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
-
-  GetMessageListView()->SetRepositionTarget(
-      GetNotificationView(kNotificationId2)->parent()->bounds());
-  int previous_height = GetMessageListView()->height();
-  int previous_notification2_y =
-      GetNotificationView(kNotificationId2)->GetBoundsInScreen().y();
-
-  EXPECT_EQ(2, GetMessageListView()->child_count());
-  RemoveNotification(kNotificationId2, false);
-
-  WaitForAnimationToFinish();
-
-  EXPECT_EQ(1, GetMessageListView()->child_count());
-
-  // Confirm that notification 1 is moved up to the place on which the
-  // notification 2 was.
-  EXPECT_EQ(previous_notification2_y,
-            GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
-  // The size should be kept.
-  EXPECT_EQ(previous_height, GetMessageListView()->height());
-
-  // Notification 2 is successfully removed.
-  EXPECT_FALSE(GetNotificationView(kNotificationId2));
-  EXPECT_TRUE(GetNotificationView(kNotificationId1));
-
-  // Mouse cursor moves out of the message center. This resets the reposition
-  // target in the message list.
-  FireOnMouseExitedEvent();
-
-  // The height should be kept even after the cursor moved out.
-  EXPECT_EQ(previous_height, GetMessageListView()->height());
-}
-
-TEST_F(MessageCenterViewTest, CloseButton) {
-  views::Button* close_button = GetButtonBar()->GetCloseAllButtonForTest();
-  EXPECT_NE(nullptr, close_button);
-
-  GetButtonBar()->ButtonPressed(close_button, DummyEvent());
-  WaitForAnimationToFinish();
-  EXPECT_TRUE(GetMessageCenter()->remove_all_closable_notification_called_);
-}
-
-TEST_F(MessageCenterViewTest, CloseButtonEnablity) {
-  views::Button* close_button = GetButtonBar()->GetCloseAllButtonForTest();
-  EXPECT_NE(nullptr, close_button);
-
-  // There should be 2 non-pinned notifications.
-  EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_TRUE(close_button->enabled());
-
-  RemoveNotification(kNotificationId1, false);
-  WaitForAnimationToFinish();
-
-  // There should be 1 non-pinned notification.
-  EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_TRUE(close_button->enabled());
-
-  RemoveNotification(kNotificationId2, false);
-  WaitForAnimationToFinish();
-
-  // There should be no notification.
-  EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_FALSE(close_button->enabled());
-
-  // Non-pinned version of notification #1
-  Notification normal_notification1(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), NULL);
-
-  // Pinned version of notification #1
-  Notification pinned_notification1(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), NULL);
-  pinned_notification1.set_pinned(true);
-
-  // Pinned notification #2
-  Notification pinned_notification2(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), NULL);
-  pinned_notification2.set_pinned(true);
-
-  AddNotification(std::make_unique<Notification>(normal_notification1));
-
-  // There should be 1 non-pinned notification.
-  EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_TRUE(close_button->enabled());
-
-  UpdateNotification(kNotificationId1,
-                     std::make_unique<Notification>(pinned_notification1));
-
-  // There should be 1 pinned notification.
-  EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_FALSE(close_button->enabled());
-
-  // Adds 1 pinned notification.
-  AddNotification(std::make_unique<Notification>(pinned_notification2));
-
-  // There should be 1 pinned notification.
-  EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_FALSE(close_button->enabled());
-
-  UpdateNotification(kNotificationId1,
-                     std::make_unique<Notification>(normal_notification1));
-
-  // There should be 1 normal notification and 1 pinned notification.
-  EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_TRUE(close_button->enabled());
-
-  RemoveNotification(kNotificationId1, false);
-
-  // There should be 1 pinned notification.
-  EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_FALSE(close_button->enabled());
-
-  RemoveNotification(kNotificationId2, false);
-
-  // There should be no notification.
-  EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_FALSE(close_button->enabled());
-
-  AddNotification(std::make_unique<Notification>(pinned_notification2));
-
-  // There should be 1 pinned notification.
-  EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
-  EXPECT_FALSE(close_button->enabled());
-}
-
-TEST_F(MessageCenterViewTest, CheckModeWithSettingsVisibleAndHidden) {
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-  // Show the settings.
-  GetMessageCenterView()->SetSettingsVisible(true);
-  EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
-  // Hide the settings.
-  GetMessageCenterView()->SetSettingsVisible(false);
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest, CheckModeWithRemovingAndAddingNotifications) {
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Remove notifications.
-  RemoveDefaultNotifications();
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Add a notification.
-  AddNotification(std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr));
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest, CheckModeWithSettingsVisibleAndHiddenOnEmpty) {
-  // Set up by removing all existing notifications.
-  RemoveDefaultNotifications();
-
-  // Check the initial state.
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-  // Show the settings.
-  GetMessageCenterView()->SetSettingsVisible(true);
-  EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
-  // Hide the settings.
-  GetMessageCenterView()->SetSettingsVisible(false);
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest,
-       CheckModeWithRemovingNotificationDuringSettingsVisible) {
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Show the settings.
-  GetMessageCenterView()->SetSettingsVisible(true);
-  EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
-
-  // Remove a notification during settings is visible.
-  RemoveDefaultNotifications();
-  EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
-
-  // Hide the settings.
-  GetMessageCenterView()->SetSettingsVisible(false);
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest,
-       CheckModeWithAddingNotificationDuringSettingsVisible) {
-  // Set up by removing all existing notifications.
-  RemoveDefaultNotifications();
-
-  // Check the initial state.
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Show the settings.
-  GetMessageCenterView()->SetSettingsVisible(true);
-  EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
-
-  // Add a notification during settings is visible.
-  AddNotification(std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title2"),
-      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
-      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr));
-  EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
-
-  // Hide the settings.
-  GetMessageCenterView()->SetSettingsVisible(false);
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest, CheckModeWithLockingAndUnlocking) {
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Lock!
-  SetLockedState(true);
-  EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());
-
-  // Unlock!
-  SetLockedState(false);
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Remove all existing notifications.
-  RemoveDefaultNotifications();
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Lock!
-  SetLockedState(true);
-  EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());
-
-  // Unlock!
-  SetLockedState(false);
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest,
-       CheckModeWithLockingAndUnlockingWithLockScreenNotificationEnabled) {
-  SetLockScreenNotificationsEnabled();
-
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Lock!
-  SetLockedState(true);
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Unlock!
-  SetLockedState(false);
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Remove all existing notifications.
-  RemoveDefaultNotifications();
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Lock!
-  SetLockedState(true);
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Unlock!
-  SetLockedState(false);
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest, CheckModeWithRemovingNotificationDuringLock) {
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Lock!
-  SetLockedState(true);
-  EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());
-
-  // Remove all existing notifications.
-  RemoveDefaultNotifications();
-  EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());
-
-  // Unlock!
-  SetLockedState(false);
-
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(
-    MessageCenterViewTest,
-    CheckModeWithRemovingNotificationDuringLockWithLockScreenNotificationEnabled) {
-  SetLockScreenNotificationsEnabled();
-
-  // Check the initial state.
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Lock!
-  SetLockedState(true);
-  EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Remove all existing notifications.
-  RemoveDefaultNotifications();
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-
-  // Unlock!
-  SetLockedState(false);
-
-  EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
-}
-
-TEST_F(MessageCenterViewTest, LockScreen) {
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-  EXPECT_TRUE(GetNotificationView(kNotificationId2)->IsDrawn());
-
-  views::Button* close_button = GetButtonBar()->GetCloseAllButtonForTest();
-  ASSERT_TRUE(close_button);
-  views::Button* quiet_mode_button =
-      GetButtonBar()->GetQuietModeButtonForTest();
-  ASSERT_TRUE(quiet_mode_button);
-  views::Button* settings_button = GetButtonBar()->GetSettingsButtonForTest();
-  ASSERT_TRUE(settings_button);
-  views::Button* collapse_button = GetButtonBar()->GetCollapseButtonForTest();
-  ASSERT_TRUE(collapse_button);
-
-  EXPECT_TRUE(close_button->visible());
-  EXPECT_TRUE(quiet_mode_button->visible());
-  EXPECT_TRUE(settings_button->visible());
-
-  // Lock!
-  SetLockedState(true);
-
-  EXPECT_FALSE(GetNotificationView(kNotificationId1)->IsDrawn());
-  EXPECT_FALSE(GetNotificationView(kNotificationId2)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  RemoveNotification(kNotificationId1, false);
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  RemoveNotification(kNotificationId2, false);
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  AddNotification(std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title1"), base::UTF8ToUTF16("message"), gfx::Image(),
-      base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr));
-  EXPECT_FALSE(GetNotificationView(kNotificationId1)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  EXPECT_FALSE(close_button->visible());
-  EXPECT_FALSE(quiet_mode_button->visible());
-  EXPECT_FALSE(settings_button->visible());
-  EXPECT_FALSE(collapse_button->visible());
-
-  // Unlock!
-  SetLockedState(false);
-
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  EXPECT_TRUE(close_button->visible());
-  EXPECT_TRUE(quiet_mode_button->visible());
-  EXPECT_TRUE(settings_button->visible());
-
-  // Lock!
-  SetLockedState(true);
-
-  EXPECT_FALSE(GetNotificationView(kNotificationId1)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  EXPECT_FALSE(close_button->visible());
-  EXPECT_FALSE(quiet_mode_button->visible());
-  EXPECT_FALSE(settings_button->visible());
-  EXPECT_FALSE(collapse_button->visible());
-}
-
-TEST_F(MessageCenterViewTest, LockScreenWithLockScreenNotificationEnabled) {
-  SetLockScreenNotificationsEnabled();
-
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-  EXPECT_TRUE(GetNotificationView(kNotificationId2)->IsDrawn());
-
-  views::Button* close_button = GetButtonBar()->GetCloseAllButtonForTest();
-  ASSERT_TRUE(close_button);
-  views::Button* quiet_mode_button =
-      GetButtonBar()->GetQuietModeButtonForTest();
-  ASSERT_TRUE(quiet_mode_button);
-  views::Button* settings_button = GetButtonBar()->GetSettingsButtonForTest();
-  ASSERT_TRUE(settings_button);
-  views::Button* collapse_button = GetButtonBar()->GetCollapseButtonForTest();
-  ASSERT_TRUE(collapse_button);
-
-  EXPECT_TRUE(close_button->visible());
-  EXPECT_TRUE(quiet_mode_button->visible());
-  EXPECT_TRUE(settings_button->visible());
-
-  // Lock!
-  SetLockedState(true);
-
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-  EXPECT_TRUE(GetNotificationView(kNotificationId2)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  RemoveNotification(kNotificationId1, false);
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  RemoveNotification(kNotificationId2, false);
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  AddNotification(std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title1"), base::UTF8ToUTF16("message"), gfx::Image(),
-      base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr));
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  EXPECT_TRUE(close_button->visible());
-  EXPECT_TRUE(quiet_mode_button->visible());
-  EXPECT_FALSE(settings_button->visible());
-  EXPECT_FALSE(collapse_button->visible());
-
-  // Unlock!
-  SetLockedState(false);
-
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  EXPECT_TRUE(close_button->visible());
-  EXPECT_TRUE(quiet_mode_button->visible());
-  EXPECT_TRUE(settings_button->visible());
-
-  // Lock!
-  SetLockedState(true);
-
-  EXPECT_TRUE(GetNotificationView(kNotificationId1)->IsDrawn());
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kLockedMessageCenterViewHeight, GetMessageCenterView()->height());
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  EXPECT_TRUE(close_button->visible());
-  EXPECT_TRUE(quiet_mode_button->visible());
-  EXPECT_FALSE(settings_button->visible());
-  EXPECT_FALSE(collapse_button->visible());
-}
-
-TEST_F(MessageCenterViewTest, NoNotification) {
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-  RemoveNotification(kNotificationId1, false);
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-  RemoveNotification(kNotificationId2, false);
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_EQ(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-
-  AddNotification(std::make_unique<Notification>(
-      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-      base::UTF8ToUTF16("title1"), base::UTF8ToUTF16("message"), gfx::Image(),
-      base::UTF8ToUTF16("display source"), GURL(),
-      NotifierId(NotifierId::APPLICATION, "extension_id"),
-      message_center::RichNotificationData(), nullptr));
-
-  GetMessageCenterView()->SizeToPreferredSize();
-  EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/message_list_view.cc b/ash/system/message_center/message_list_view.cc
deleted file mode 100644
index 3d7a4487..0000000
--- a/ash/system/message_center/message_list_view.cc
+++ /dev/null
@@ -1,719 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/message_list_view.h"
-
-#include "ash/system/message_center/message_center_style.h"
-#include "ash/system/message_center/message_center_view.h"
-#include "ash/system/message_center/slidable_message_view.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "ui/gfx/animation/slide_animation.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/public/cpp/notification.h"
-#include "ui/message_center/views/message_view.h"
-#include "ui/views/background.h"
-#include "ui/views/border.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/widget/widget.h"
-
-using message_center::MessageView;
-using message_center::SlidableMessageView;
-using message_center::Notification;
-
-namespace ash {
-
-namespace {
-const int kAnimateClearingNextNotificationDelayMS = 40;
-}  // namespace
-
-MessageListView::MessageListView()
-    : reposition_top_(-1),
-      fixed_height_(0),
-      has_deferred_task_(false),
-      clear_all_started_(false),
-      use_fixed_height_(true),
-      has_border_padding_(false),
-      animator_(this),
-      weak_ptr_factory_(this) {
-  auto layout = std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical,
-                                                   gfx::Insets(), 1);
-  layout->SetDefaultFlex(1);
-  SetLayoutManager(std::move(layout));
-
-  animator_.AddObserver(this);
-}
-
-MessageListView::~MessageListView() {
-  animator_.RemoveObserver(this);
-}
-
-void MessageListView::Layout() {
-  if (animator_.IsAnimating())
-    return;
-
-  gfx::Rect child_area = GetContentsBounds();
-  int top = child_area.y();
-
-  for (int i = 0; i < child_count(); ++i) {
-    views::View* child = child_at(i);
-    if (!child->visible())
-      continue;
-    int height = child->GetHeightForWidth(child_area.width());
-    child->SetBounds(child_area.x(), top, child_area.width(), height);
-    top += height + GetMarginBetweenItems();
-  }
-}
-
-void MessageListView::AddNotificationAt(MessageView* message_view, int index) {
-  // |index| refers to a position in a subset of valid children. |real_index|
-  // in a list includes the invalid children, so we compute the real index by
-  // walking the list until |index| number of valid children are encountered,
-  // or to the end of the list.
-  int real_index = 0;
-  while (real_index < child_count()) {
-    if (IsValidChild(child_at(real_index))) {
-      --index;
-      if (index < 0)
-        break;
-    }
-    ++real_index;
-  }
-
-  if (real_index == 0)
-    ExpandSpecifiedNotificationAndCollapseOthers(message_view);
-
-  SlidableMessageView* container = new SlidableMessageView(message_view);
-  AddChildViewAt(container, real_index);
-  if (GetContentsBounds().IsEmpty())
-    return;
-
-  adding_views_.insert(container);
-  DoUpdateIfPossible();
-}
-
-void MessageListView::RemoveNotification(MessageView* message_view) {
-  views::View* container = message_view->parent();
-  DCHECK_EQ(container->parent(), this);
-
-  // TODO(yhananda): We should consider consolidating clearing_all_views_,
-  // deleting_views_ and deleted_when_done_.
-  if (base::ContainsValue(clearing_all_views_, container) ||
-      deleting_views_.find(container) != deleting_views_.end() ||
-      deleted_when_done_.find(container) != deleted_when_done_.end()) {
-    // Let's skip deleting the view if it's already scheduled for deleting.
-    // Even if we check clearing_all_views_ here, we actualy have no idea
-    // whether the view is due to be removed or not because it could be in its
-    // animation before removal.
-    // In short, we could delete the view twice even if we check these three
-    // lists.
-    return;
-  }
-
-  if (GetContentsBounds().IsEmpty()) {
-    delete container;
-  } else {
-    if (adding_views_.find(container) != adding_views_.end())
-      adding_views_.erase(container);
-    if (animator_.IsAnimating(container))
-      animator_.StopAnimatingView(container);
-
-    if (container->layer()) {
-      deleting_views_.insert(container);
-    } else {
-      delete container;
-    }
-    DoUpdateIfPossible();
-  }
-
-  int index = GetIndexOf(container);
-  if (index == 0)
-    ExpandTopNotificationAndCollapseOthers();
-}
-
-void MessageListView::UpdateNotification(MessageView* message_view,
-                                         const Notification& notification) {
-  auto* container = SlidableMessageView::GetFromMessageView(message_view);
-
-  // Skip updating the notification being cleared.
-  if (base::ContainsValue(clearing_all_views_, container))
-    return;
-
-  int index = GetIndexOf(container);
-  DCHECK_LE(0, index);  // GetIndexOf is negative if not a child.
-
-  if (index == 0)
-    ExpandSpecifiedNotificationAndCollapseOthers(message_view);
-
-  animator_.StopAnimatingView(container);
-  if (deleting_views_.find(container) != deleting_views_.end())
-    deleting_views_.erase(container);
-  if (deleted_when_done_.find(container) != deleted_when_done_.end())
-    deleted_when_done_.erase(container);
-  container->UpdateWithNotification(notification);
-  DoUpdateIfPossible();
-}
-
-std::pair<int, MessageView*> MessageListView::GetNotificationById(
-    const std::string& id) {
-  for (int i = child_count() - 1; i >= 0; --i) {
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              child_at(i)->GetClassName());
-    SlidableMessageView* container =
-        static_cast<SlidableMessageView*>(child_at(i));
-    if (container->notification_id() == id && IsValidChild(container))
-      return std::make_pair(i, container->GetMessageView());
-  }
-  return std::make_pair(-1, nullptr);
-}
-
-MessageView* MessageListView::GetNotificationAt(int index) {
-  for (int i = child_count() - 1; i >= 0; --i) {
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              child_at(i)->GetClassName());
-    SlidableMessageView* container =
-        static_cast<SlidableMessageView*>(child_at(i));
-    if (IsValidChild(container)) {
-      if (index == 0)
-        return container->GetMessageView();
-      index--;
-    }
-  }
-  return nullptr;
-}
-
-size_t MessageListView::GetNotificationCount() const {
-  int count = 0;
-  for (int i = child_count() - 1; i >= 0; --i) {
-    const SlidableMessageView* container =
-        static_cast<const SlidableMessageView*>(child_at(i));
-    if (IsValidChild(container))
-      count++;
-  }
-  return count;
-}
-
-gfx::Size MessageListView::CalculatePreferredSize() const {
-  // Just returns the current size. All size change must be done in
-  // |DoUpdateIfPossible()| with animation , because we don't want to change
-  // the size in unexpected timing.
-  return size();
-}
-
-int MessageListView::GetHeightForWidth(int width) const {
-  if (use_fixed_height_ && fixed_height_ > 0)
-    return fixed_height_;
-
-  width -= GetInsets().width();
-  int height = 0;
-  int padding = 0;
-  for (int i = 0; i < child_count(); ++i) {
-    const views::View* child = child_at(i);
-    if (!IsValidChild(child))
-      continue;
-    height += child->GetHeightForWidth(width) + padding;
-    padding = GetMarginBetweenItems();
-  }
-
-  return height + GetInsets().height();
-}
-
-void MessageListView::PaintChildren(const views::PaintInfo& paint_info) {
-  // Paint in the inversed order. Otherwise upper notification may be
-  // hidden by the lower one.
-  for (int i = child_count() - 1; i >= 0; --i) {
-    if (!child_at(i)->layer())
-      child_at(i)->Paint(paint_info);
-  }
-}
-
-void MessageListView::ReorderChildLayers(ui::Layer* parent_layer) {
-  // Reorder children to stack the last child layer at the top. Otherwise
-  // upper notification may be hidden by the lower one.
-  for (int i = 0; i < child_count(); ++i) {
-    if (child_at(i)->layer())
-      parent_layer->StackAtBottom(child_at(i)->layer());
-  }
-}
-
-void MessageListView::UpdateFixedHeight(int requested_height,
-                                        bool prevent_scroll) {
-  int previous_fixed_height = fixed_height_;
-  int min_height;
-
-  // When the |prevent_scroll| flag is set, we use |fixed_height_|, which is the
-  // bottom position of the visible rect. It's to keep the current visible
-  // window, in other words, not to be scrolled, when the visible rect has a
-  // blank area at the bottom.
-  // Otherwise (in else block), we use the height of the visible rect to make
-  // the height of the message list as small as possible.
-  if (prevent_scroll) {
-    // TODO(yoshiki): Consider the case with scrolling. If the message center
-    // has scrollbar and its height is maximum, we may not need to keep the
-    // height of the list in the scroll view.
-    min_height = fixed_height_;
-  } else {
-    if (scroller_) {
-      gfx::Rect visible_rect = scroller_->GetVisibleRect();
-      min_height = visible_rect.height();
-    } else {
-      // Fallback for testing.
-      min_height = fixed_height_;
-    }
-  }
-  fixed_height_ = std::max(min_height, requested_height);
-
-  if (previous_fixed_height != fixed_height_) {
-    PreferredSizeChanged();
-  }
-}
-
-void MessageListView::SetRepositionTarget(const gfx::Rect& target) {
-  reposition_top_ = std::max(target.y(), 0);
-  UpdateFixedHeight(GetHeightForWidth(width()), false);
-}
-
-void MessageListView::ResetRepositionSession() {
-  // Don't call DoUpdateIfPossible(), but let Layout() do the task without
-  // animation. Reset will cause the change of the bubble size itself, and
-  // animation from the old location will look weird.
-  if (reposition_top_ >= 0) {
-    has_deferred_task_ = false;
-    // cancel cause OnBoundsAnimatorDone which deletes |deleted_when_done_|.
-    animator_.Cancel();
-    for (auto* view : deleting_views_)
-      delete view;
-    deleting_views_.clear();
-    adding_views_.clear();
-  }
-
-  reposition_top_ = -1;
-
-  UpdateFixedHeight(fixed_height_, false);
-}
-
-void MessageListView::ClearAllClosableNotifications(
-    const gfx::Rect& visible_scroll_rect) {
-  for (int i = 0; i < child_count(); ++i) {
-    // Safe cast since all views in MessageListView are SlidableMessageViews.
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              child_at(i)->GetClassName());
-    SlidableMessageView* child = static_cast<SlidableMessageView*>(child_at(i));
-    if (!child->visible())
-      continue;
-    if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty())
-      continue;
-    if (child->GetMode() != MessageView::Mode::NORMAL)
-      continue;
-    if (deleting_views_.find(child) != deleting_views_.end() ||
-        deleted_when_done_.find(child) != deleted_when_done_.end()) {
-      // We don't check clearing_all_views_ here, so this can lead to a
-      // notification being deleted twice. Even if we do check it, there is a
-      // problem similar to the problem in RemoveNotification(), it could be
-      // currently in its animation before removal, and we could similarly
-      // delete it twice. This is a bug.
-      continue;
-    }
-    clearing_all_views_.push_back(child);
-  }
-  if (clearing_all_views_.empty()) {
-    for (auto& observer : observers_)
-      observer.OnAllNotificationsCleared();
-  } else {
-    DoUpdateIfPossible();
-  }
-}
-
-void MessageListView::AddObserver(MessageListView::Observer* observer) {
-  observers_.AddObserver(observer);
-}
-
-void MessageListView::RemoveObserver(MessageListView::Observer* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-void MessageListView::SetBorderPadding() {
-  has_border_padding_ = true;
-  SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(message_center::kMarginBetweenItemsInList)));
-}
-
-int MessageListView::GetCountAboveVisibleRect(int y_offset) const {
-  DCHECK(scroller_);
-
-  int height = 0;
-  int padding = 0;
-  for (int i = 0; i < child_count(); ++i) {
-    const views::View* child = child_at(i);
-    if (!child->visible())
-      continue;
-    if (!IsValidChild(child))
-      continue;
-
-    height += child->bounds().height() + padding;
-    padding = GetMarginBetweenItems();
-
-    if (height >= scroller_->GetVisibleRect().y() + y_offset)
-      return i;
-  }
-  return child_count();
-}
-
-int MessageListView::GetHeightBelowVisibleRect() const {
-  DCHECK(scroller_);
-
-  int height = 0;
-  int padding = 0;
-  for (int i = 0; i < child_count(); ++i) {
-    const views::View* child = child_at(i);
-    if (!child->visible())
-      continue;
-    if (!IsValidChild(child))
-      continue;
-
-    height += child->bounds().height() + padding;
-    padding = GetMarginBetweenItems();
-  }
-  return std::max(0, height - scroller_->GetVisibleRect().bottom());
-}
-
-void MessageListView::OnBoundsAnimatorProgressed(
-    views::BoundsAnimator* animator) {
-  DCHECK_EQ(&animator_, animator);
-  for (auto* view : deleted_when_done_) {
-    const gfx::SlideAnimation* animation = animator->GetAnimationForView(view);
-    if (animation)
-      view->layer()->SetOpacity(animation->CurrentValueBetween(1.0, 0.0));
-  }
-}
-
-void MessageListView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
-  // It's possible for the delayed task that queues the next animation for
-  // clearing all notifications to be delayed more than we want. In this case,
-  // the BoundsAnimator can finish while a clear all is still happening. So,
-  // explicitly check if |clearing_all_views_| is empty.
-  if (clear_all_started_ && !clearing_all_views_.empty()) {
-    return;
-  }
-
-  bool need_update = false;
-
-  if (clear_all_started_) {
-    clear_all_started_ = false;
-    for (auto& observer : observers_)
-      observer.OnAllNotificationsCleared();
-
-    // Just return here if new animation is initiated in the above observers,
-    // since the code below assumes no animation is running. In the current
-    // impelementation, the observer tries removing the notification and their
-    // views and starts animation if the message center keeps opening.
-    // The code below will be executed when the new animation is finished.
-    if (animator_.IsAnimating())
-      return;
-  }
-
-  // None of these views should be deleted.
-  DCHECK(std::all_of(deleted_when_done_.begin(), deleted_when_done_.end(),
-                     [this](views::View* view) { return Contains(view); }));
-
-  for (auto* view : deleted_when_done_)
-    delete view;
-  deleted_when_done_.clear();
-
-  if (has_deferred_task_) {
-    has_deferred_task_ = false;
-    need_update = true;
-  }
-
-  if (need_update)
-    DoUpdateIfPossible();
-
-  if (GetWidget() && !GetWidget()->IsClosed())
-    GetWidget()->SynthesizeMouseMoveEvent();
-}
-
-int MessageListView::GetMarginBetweenItems() const {
-  return has_border_padding_ ? message_center::kMarginBetweenItemsInList : 0;
-}
-
-bool MessageListView::IsValidChild(const views::View* child) const {
-  return deleting_views_.find(const_cast<views::View*>(child)) ==
-             deleting_views_.end() &&
-         deleted_when_done_.find(const_cast<views::View*>(child)) ==
-             deleted_when_done_.end() &&
-         !base::ContainsValue(clearing_all_views_, child) && child->visible();
-}
-
-void MessageListView::DoUpdateIfPossible() {
-  gfx::Rect child_area = GetContentsBounds();
-  if (child_area.IsEmpty())
-    return;
-
-  if (animator_.IsAnimating()) {
-    has_deferred_task_ = true;
-    return;
-  }
-
-  // Start the clearing all animation if necessary.
-  if (!clearing_all_views_.empty() && !clear_all_started_) {
-    AnimateClearingOneNotification();
-    return;
-  }
-
-  // Skip during the clering all animation.
-  // This checks |clear_all_started_! rather than |clearing_all_views_|, since
-  // the latter is empty during the animation of the last element.
-  if (clear_all_started_) {
-    DCHECK(!clearing_all_views_.empty());
-    return;
-  }
-
-  AnimateNotifications();
-
-  // Should calculate and set new size after calling AnimateNotifications()
-  // because fixed_height_ may be updated in it.
-  int new_height = GetHeightForWidth(child_area.width() + GetInsets().width());
-  SetSize(gfx::Size(child_area.width() + GetInsets().width(), new_height));
-
-  adding_views_.clear();
-  deleting_views_.clear();
-
-  if (!animator_.IsAnimating() && GetWidget() && !GetWidget()->IsClosed())
-    GetWidget()->SynthesizeMouseMoveEvent();
-}
-
-void MessageListView::ExpandSpecifiedNotificationAndCollapseOthers(
-    message_center::MessageView* target_view) {
-  if (!target_view->IsManuallyExpandedOrCollapsed() &&
-      target_view->IsAutoExpandingAllowed()) {
-    target_view->SetExpanded(true);
-  }
-
-  for (int i = 0; i < child_count(); ++i) {
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              child_at(i)->GetClassName());
-    SlidableMessageView* container =
-        static_cast<SlidableMessageView*>(child_at(i));
-    // Target view is already processed above.
-    if (target_view == container->GetMessageView())
-      continue;
-    // Skip if the view is invalid.
-    if (!IsValidChild(container))
-      continue;
-    // We don't touch if the view has been manually expanded or collapsed.
-    if (container->IsManuallyExpandedOrCollapsed())
-      continue;
-
-    // Otherwise, collapse the notification.
-    container->SetExpanded(false);
-  }
-}
-
-void MessageListView::ExpandTopNotificationAndCollapseOthers() {
-  SlidableMessageView* top_notification = nullptr;
-  for (int i = 0; i < child_count(); ++i) {
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              child_at(i)->GetClassName());
-    SlidableMessageView* container =
-        static_cast<SlidableMessageView*>(child_at(i));
-    if (!IsValidChild(container))
-      continue;
-    top_notification = container;
-    break;
-  }
-
-  if (top_notification != nullptr)
-    ExpandSpecifiedNotificationAndCollapseOthers(
-        top_notification->GetMessageView());
-}
-
-std::vector<int> MessageListView::ComputeRepositionOffsets(
-    const std::vector<int>& heights,
-    const std::vector<bool>& deleting,
-    int target_index,
-    int padding) {
-  DCHECK_EQ(heights.size(), deleting.size());
-  // Calculate the vertical length between the top of message list and the top
-  // of target. This is to shrink or expand the height of the message list
-  // when the notifications above the target is changed.
-  int vertical_gap_to_target_from_top = GetInsets().top();
-  for (int i = 0; i < target_index; i++) {
-    if (!deleting[i])
-      vertical_gap_to_target_from_top += heights[i] + padding;
-  }
-
-  // If the calculated length is expanded from |repositon_top_|, it means that
-  // some of items above the target are updated and their height increased.
-  // Adjust the vertical length above the target.
-  if (vertical_gap_to_target_from_top > reposition_top_) {
-    fixed_height_ += vertical_gap_to_target_from_top - reposition_top_;
-    reposition_top_ = vertical_gap_to_target_from_top;
-  }
-
-  // TODO(yoshiki): Scroll the parent container to keep the physical position
-  // of the target notification when the scrolling is caused by a size change
-  // of notification above.
-
-  std::vector<int> positions;
-  positions.reserve(heights.size());
-  // Layout the items above the target.
-  int y = GetInsets().top();
-  for (int i = 0; i < target_index; i++) {
-    positions.push_back(y);
-    if (!deleting[i])
-      y += heights[i] + padding;
-  }
-  DCHECK_EQ(y, vertical_gap_to_target_from_top);
-  DCHECK_LE(y, reposition_top_);
-
-  // Match the top with |reposition_top_|.
-  y = reposition_top_;
-  // Layout the target and the items below the target.
-  for (int i = target_index; i < int(heights.size()); i++) {
-    positions.push_back(y);
-    if (!deleting[i])
-      y += heights[i] + padding;
-  }
-
-  // Update the fixed height. |requested_height| is the height to have all
-  // notifications in the list and to keep the vertical position of the target
-  // notification. It may not just a total of all the notification heights if
-  // the target exists.
-  int requested_height = y - padding + GetInsets().bottom();
-  UpdateFixedHeight(requested_height, true);
-
-  return positions;
-}
-
-void MessageListView::AnimateNotifications() {
-  int target_index = -1;
-  int padding = GetMarginBetweenItems();
-  gfx::Rect child_area = GetContentsBounds();
-  if (reposition_top_ >= 0) {
-    // Find the target item.
-    for (int i = 0; i < child_count(); ++i) {
-      views::View* child = child_at(i);
-      if (child->y() >= reposition_top_ &&
-          deleting_views_.find(child) == deleting_views_.end()) {
-        // Find the target.
-        target_index = i;
-        break;
-      }
-    }
-  }
-
-  if (target_index != -1) {
-    std::vector<int> heights;
-    std::vector<bool> deleting;
-    heights.reserve(child_count());
-    deleting.reserve(child_count());
-    for (int i = 0; i < child_count(); i++) {
-      views::View* child = child_at(i);
-      heights.push_back(child->GetHeightForWidth(child_area.width()));
-      deleting.push_back(deleting_views_.find(child) != deleting_views_.end());
-    }
-    std::vector<int> ys =
-        ComputeRepositionOffsets(heights, deleting, target_index, padding);
-    for (int i = 0; i < child_count(); ++i) {
-      bool above_target = (i < target_index);
-      AnimateChild(child_at(i), ys[i], heights[i],
-                   !above_target /* animate_on_move */);
-    }
-  } else {
-    // Layout all the items.
-    int y = GetInsets().top();
-    for (int i = 0; i < child_count(); ++i) {
-      views::View* child = child_at(i);
-      int height = child->GetHeightForWidth(child_area.width());
-      if (AnimateChild(child, y, height, true))
-        y += height + padding;
-    }
-    int new_height = y - padding + GetInsets().bottom();
-    UpdateFixedHeight(new_height, false);
-  }
-}
-
-bool MessageListView::AnimateChild(views::View* child,
-                                   int top,
-                                   int height,
-                                   bool animate_on_move) {
-  // Do not call this during clearing all animation.
-  DCHECK(clearing_all_views_.empty());
-  DCHECK(!clear_all_started_);
-
-  gfx::Rect child_area = GetContentsBounds();
-  if (adding_views_.find(child) != adding_views_.end()) {
-    child->SetBounds(child_area.right(), top, child_area.width(), height);
-    animator_.AnimateViewTo(
-        child, gfx::Rect(child_area.x(), top, child_area.width(), height));
-  } else if (deleting_views_.find(child) != deleting_views_.end()) {
-    DCHECK(child->layer());
-    // No moves, but animate to fade-out.
-    animator_.AnimateViewTo(child, child->bounds());
-    deleted_when_done_.insert(child);
-    return false;
-  } else {
-    gfx::Rect target(child_area.x(), top, child_area.width(), height);
-    if (child->origin() != target.origin() && animate_on_move)
-      animator_.AnimateViewTo(child, target);
-    else
-      child->SetBoundsRect(target);
-  }
-  return true;
-}
-
-void MessageListView::AnimateClearingOneNotification() {
-  DCHECK(!clearing_all_views_.empty());
-
-  clear_all_started_ = true;
-
-  views::View* child = clearing_all_views_.front();
-  clearing_all_views_.pop_front();
-
-  // Slide from left to right.
-  gfx::Rect new_bounds = child->bounds();
-  new_bounds.set_x(new_bounds.right() + GetMarginBetweenItems());
-  animator_.AnimateViewTo(child, new_bounds);
-
-  // Schedule to start sliding out next notification after a short delay.
-  if (!clearing_all_views_.empty()) {
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&MessageListView::AnimateClearingOneNotification,
-                   weak_ptr_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMilliseconds(
-            kAnimateClearingNextNotificationDelayMS));
-  }
-}
-
-void MessageListView::OnSlideChanged(const std::string& notification_id) {
-  for (int i = 0; i < child_count(); ++i) {
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              child_at(i)->GetClassName());
-    SlidableMessageView* container =
-        static_cast<SlidableMessageView*>(child_at(i));
-    MessageView* message = container->GetMessageView();
-    if (message->notification_id() == notification_id)
-      continue;
-    if (!IsValidChild(container))
-      continue;
-    container->CloseSwipeControl();
-  }
-}
-
-void MessageListView::UpdateCornerRadius(int index,
-                                         int top_radius,
-                                         int bottom_radius) {
-  auto* message_view = GetNotificationAt(index);
-  auto* container = SlidableMessageView::GetFromMessageView(message_view);
-
-  message_view->UpdateCornerRadius(top_radius, bottom_radius);
-  container->UpdateCornerRadius(top_radius, bottom_radius);
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/message_list_view.h b/ash/system/message_center/message_list_view.h
deleted file mode 100644
index 1965e2e..0000000
--- a/ash/system/message_center/message_list_view.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_LIST_VIEW_H_
-#define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_LIST_VIEW_H_
-
-#include <list>
-#include <set>
-#include <vector>
-
-#include "ash/ash_export.h"
-#include "ash/system/message_center/slidable_message_view.h"
-#include "base/macros.h"
-#include "ui/compositor/paint_context.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/views/animation/bounds_animator.h"
-#include "ui/views/animation/bounds_animator_observer.h"
-#include "ui/views/controls/scroll_view.h"
-#include "ui/views/view.h"
-
-namespace ui {
-class Layer;
-}
-
-namespace message_center {
-class SlidableMessageView;
-class MessageView;
-class Notification;
-}  // namespace message_center
-
-namespace ash {
-
-// Displays a list of messages for rich notifications. Functions as an array of
-// MessageViews and animates them on transitions. It also supports
-// repositioning.
-class ASH_EXPORT MessageListView
-    : public views::View,
-      public views::BoundsAnimatorObserver,
-      public message_center::MessageView::SlideObserver {
- public:
-  class Observer {
-   public:
-    virtual void OnAllNotificationsCleared() = 0;
-  };
-
-  MessageListView();
-  ~MessageListView() override;
-
-  void AddNotificationAt(message_center::MessageView* message_view, int i);
-  void RemoveNotification(message_center::MessageView* message_view);
-  void UpdateNotification(message_center::MessageView* message_view,
-                          const message_center::Notification& notification);
-  std::pair<int, message_center::MessageView*> GetNotificationById(
-      const std::string& id);
-  message_center::MessageView* GetNotificationAt(int index);
-  // Return the number of the valid notification. This traverse the items so it
-  // costs O(n) time, where n is the number of total notifications.
-  size_t GetNotificationCount() const;
-
-  // SetRepositionTarget sets the target that the physical location of
-  // the notification at |target_rect| does not change after the repositining.
-  // Repositioning is a process to change the positions of the notifications,
-  // which is caused by addition/modification/removal of notifications.
-  // The term is almost interchangeable with animation.
-  void SetRepositionTarget(const gfx::Rect& target_rect);
-
-  void ResetRepositionSession();
-  void ClearAllClosableNotifications(const gfx::Rect& visible_scroll_rect);
-
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-
-  void SetBorderPadding();
-
-  // Get the number of notifications above ScrollView's visible rect.
-  int GetCountAboveVisibleRect(int y_offset) const;
-
-  // Get the distance from the bottom of ScrollView's visible rect to the bottom
-  // of the notification list.
-  int GetHeightBelowVisibleRect() const;
-
-  void set_use_fixed_height(bool use_fixed_height) {
-    use_fixed_height_ = use_fixed_height;
-  }
-  void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
-
-  // Overridden from MessageView::SlideObserver
-  void OnSlideChanged(const std::string& notification_id) override;
-
-  void UpdateCornerRadius(int index, int top_radius, int bottom_radius);
-
- protected:
-  // Overridden from views::View.
-  void Layout() override;
-  gfx::Size CalculatePreferredSize() const override;
-  int GetHeightForWidth(int width) const override;
-  void PaintChildren(const views::PaintInfo& paint_info) override;
-  void ReorderChildLayers(ui::Layer* parent_layer) override;
-
-  // Overridden from views::BoundsAnimatorObserver.
-  void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override;
-  void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override;
-
- private:
-  friend class MessageCenterViewTest;
-  friend class MessageListViewTest;
-
-  int GetMarginBetweenItems() const;
-  bool IsValidChild(const views::View* child) const;
-  void DoUpdateIfPossible();
-
-  // For given notification, expand it if it is allowed to be expanded and is
-  // never manually expanded:
-  // For other notifications, collapse if it's never manually expanded.
-  void ExpandSpecifiedNotificationAndCollapseOthers(
-      message_center::MessageView* target_view);
-
-  void ExpandTopNotificationAndCollapseOthers();
-
-  // Animates all notifications to align with the top of the last closed
-  // notification.
-  void AnimateNotifications();
-  // Computes reposition offsets for |AnimateNotificationsAboveTarget|.
-  std::vector<int> ComputeRepositionOffsets(const std::vector<int>& heights,
-                                            const std::vector<bool>& deleting,
-                                            int target_index,
-                                            int padding);
-
-  // Schedules animation for a child to the specified position. Returns false
-  // if |child| will disappear after the animation.
-  bool AnimateChild(views::View* child,  // message_center::SlidableMessageView
-                    int top,
-                    int height,
-                    bool animate_even_on_move);
-
-  // Calculate the new fixed height and update with it. |requested_height|
-  // is the minimum height, and actual fixed height should be more than it.
-  void UpdateFixedHeight(int requested_height, bool prevent_scroll);
-
-  // Animate clearing one notification.
-  void AnimateClearingOneNotification();
-
-  // List of MessageListView::Observer
-  base::ObserverList<Observer>::Unchecked observers_;
-
-  // The top position of the reposition target rectangle.
-  int reposition_top_;
-  int fixed_height_;
-  bool has_deferred_task_;
-  bool clear_all_started_;
-  bool use_fixed_height_;
-  bool has_border_padding_;
-  std::set<views::View*> adding_views_;
-  std::set<views::View*> deleting_views_;
-  std::set<views::View*> deleted_when_done_;
-  std::list<views::View*> clearing_all_views_;
-  views::BoundsAnimator animator_;
-
-  views::ScrollView* scroller_ = nullptr;
-
-  base::WeakPtrFactory<MessageListView> weak_ptr_factory_;
-  DISALLOW_COPY_AND_ASSIGN(MessageListView);
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_LIST_VIEW_H_
diff --git a/ash/system/message_center/message_list_view_unittest.cc b/ash/system/message_center/message_list_view_unittest.cc
deleted file mode 100644
index 99100a5..0000000
--- a/ash/system/message_center/message_list_view_unittest.cc
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <memory>
-#include <utility>
-
-#include "ash/system/message_center/message_list_view.h"
-#include "ash/system/message_center/slidable_message_view.h"
-#include "ash/test/ash_test_base.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/message_center/fake_message_center.h"
-#include "ui/message_center/notification_list.h"
-#include "ui/message_center/public/cpp/notification.h"
-#include "ui/message_center/views/notification_view_md.h"
-#include "ui/views/test/views_test_base.h"
-
-using ::testing::ElementsAre;
-using message_center::Notification;
-using message_center::NotificationViewMD;
-using message_center::SlidableMessageView;
-using message_center::NotifierId;
-using message_center::NOTIFICATION_TYPE_SIMPLE;
-
-namespace ash {
-
-namespace {
-
-const char* kNotificationId1 = "notification id 1";
-const char* kNotificationId2 = "notification id 2";
-
-/* Types **********************************************************************/
-
-enum CallType { GET_PREFERRED_SIZE, GET_HEIGHT_FOR_WIDTH, LAYOUT };
-
-/* Instrumented/Mock NotificationView subclass ********************************/
-
-class MockNotificationView : public NotificationViewMD {
- public:
-  class Test {
-   public:
-    virtual void RegisterCall(CallType type) = 0;
-  };
-
-  MockNotificationView(const Notification& notification, Test* test);
-  ~MockNotificationView() override;
-
-  gfx::Size CalculatePreferredSize() const override;
-  int GetHeightForWidth(int w) const override;
-  void Layout() override;
-
- private:
-  Test* test_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockNotificationView);
-};
-
-MockNotificationView::MockNotificationView(const Notification& notification,
-                                           Test* test)
-    : NotificationViewMD(notification), test_(test) {
-  // Calling SetPaintToLayer() to ensure that this view has its own layer.
-  // This layer is needed to enable adding/removal animations.
-  SetPaintToLayer();
-}
-
-MockNotificationView::~MockNotificationView() = default;
-
-gfx::Size MockNotificationView::CalculatePreferredSize() const {
-  test_->RegisterCall(GET_PREFERRED_SIZE);
-  DCHECK(child_count() > 0);
-  return NotificationViewMD::CalculatePreferredSize();
-}
-
-int MockNotificationView::GetHeightForWidth(int width) const {
-  test_->RegisterCall(GET_HEIGHT_FOR_WIDTH);
-  DCHECK(child_count() > 0);
-  return NotificationViewMD::GetHeightForWidth(width);
-}
-
-void MockNotificationView::Layout() {
-  test_->RegisterCall(LAYOUT);
-  DCHECK(child_count() > 0);
-  NotificationViewMD::Layout();
-}
-
-}  // namespace
-
-/* Test fixture ***************************************************************/
-
-class MessageListViewTest : public AshTestBase,
-                            public MockNotificationView::Test,
-                            public MessageListView::Observer {
- public:
-  MessageListViewTest() = default;
-
-  ~MessageListViewTest() override = default;
-
-  void SetUp() override {
-    AshTestBase::SetUp();
-
-    message_list_view_.reset(new MessageListView());
-    message_list_view_->SetBorderPadding();
-    message_list_view_->AddObserver(this);
-    message_list_view_->set_owned_by_client();
-
-    widget_.reset(new views::Widget());
-    views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-    params.bounds = gfx::Rect(50, 50, 650, 650);
-    params.context = CurrentContext();
-    widget_->Init(params);
-    views::View* root = widget_->GetRootView();
-    root->AddChildView(message_list_view_.get());
-    widget_->Show();
-    widget_->Activate();
-  }
-
-  void TearDown() override {
-    widget_->CloseNow();
-    widget_.reset();
-
-    message_list_view_->RemoveObserver(this);
-    message_list_view_.reset();
-
-    AshTestBase::TearDown();
-  }
-
- protected:
-  MessageListView* message_list_view() const {
-    return message_list_view_.get();
-  }
-
-  int& reposition_top() { return message_list_view_->reposition_top_; }
-
-  int& fixed_height() { return message_list_view_->fixed_height_; }
-
-  views::BoundsAnimator& animator() { return message_list_view_->animator_; }
-
-  std::vector<int> ComputeRepositionOffsets(const std::vector<int>& heights,
-                                            const std::vector<bool>& deleting,
-                                            int target_index,
-                                            int padding) {
-    return message_list_view_->ComputeRepositionOffsets(heights, deleting,
-                                                        target_index, padding);
-  }
-
-  MockNotificationView* CreateNotificationView(
-      const Notification& notification) {
-    return new MockNotificationView(notification, this);
-  }
-
-  void RunPendingAnimations() {
-    while (animator().IsAnimating()) {
-      base::RunLoop run_loop;
-      run_loop.RunUntilIdle();
-    }
-  }
-
-  bool is_on_all_notifications_cleared_called() const {
-    return is_on_all_notifications_cleared_called_;
-  }
-
- private:
-  // MockNotificationView::Test override
-  void RegisterCall(CallType type) override {}
-
-  // MessageListView::Observer override
-  void OnAllNotificationsCleared() override {
-    is_on_all_notifications_cleared_called_ = true;
-  }
-
-  // Widget to host a MessageListView.
-  std::unique_ptr<views::Widget> widget_;
-  // MessageListView to be tested.
-  std::unique_ptr<MessageListView> message_list_view_;
-
-  bool is_on_all_notifications_cleared_called_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageListViewTest);
-};
-
-/* Unit tests *****************************************************************/
-
-TEST_F(MessageListViewTest, AddNotification) {
-  // Create a dummy notification.
-  auto* notification_view = CreateNotificationView(
-      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-                   base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"),
-                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-                   NotifierId(NotifierId::APPLICATION, "extension_id"),
-                   message_center::RichNotificationData(), nullptr));
-
-  EXPECT_EQ(0, message_list_view()->child_count());
-  EXPECT_FALSE(message_list_view()->Contains(notification_view));
-
-  // Add a notification.
-  message_list_view()->AddNotificationAt(notification_view, 0);
-
-  EXPECT_EQ(1, message_list_view()->child_count());
-  EXPECT_TRUE(message_list_view()->Contains(notification_view));
-}
-
-TEST_F(MessageListViewTest, RepositionOffsets) {
-  const auto insets = message_list_view()->GetInsets();
-  const int top = insets.top();
-  std::vector<int> positions;
-
-  // Notification above grows. |reposition_top| should remain at the same
-  // offset from the bottom.
-  fixed_height() = 4 + insets.height();
-  reposition_top() = 1 + top;
-  positions =
-      ComputeRepositionOffsets({2, 1, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(4 + insets.height() + 1, fixed_height());
-  EXPECT_EQ(1 + top + 1, reposition_top());
-
-  // Notification above shrinks. The message center keeps its height.
-  // All notifications should remain at the same position from the top.
-  fixed_height() = 5 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(5 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification above is being deleted. |reposition_top| should remain at the
-  // same place.
-  fixed_height() = 5 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {true, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(5 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification above is inserted. |reposition_top| should remain at the
-  // same offset from the bottom.
-  fixed_height() = 5 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(5 + insets.height(), fixed_height());
-  EXPECT_EQ(top + 2, reposition_top());
-
-  // Target notification grows with no free space. |reposition_top| is forced to
-  // change its offset from the bottom.
-  fixed_height() = 5 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 2, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 4, top + 5));
-  EXPECT_EQ(5 + insets.height() + 1, fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Target notification grows with free space. |reposition_top| should remain
-  // at the same offset from the bottom.
-  fixed_height() = 6 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 2, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 4, top + 5));
-  EXPECT_EQ(6 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Target notification grows with not enough free space. |reposition_top|
-  // should change its offset as little as possible, and consume the free space.
-  fixed_height() = 6 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 3, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 5, top + 6));
-  EXPECT_EQ(6 + insets.height() + 1, fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Target notification shrinks. |reposition_top| should remain at the
-  // same offset from the bottom.
-  fixed_height() = 7 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(7 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification below grows with no free space. |reposition_top| is forced to
-  // change its offset from the bottom.
-  fixed_height() = 7 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 4, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 7));
-  EXPECT_EQ(7 + insets.height() + 1, fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification below grows with free space. |reposition_top| should remain
-  // at the same offset from the bottom.
-  fixed_height() = 8 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 2, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 5));
-  EXPECT_EQ(8 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification below shrinks. |reposition_top| should remain at the same
-  // offset from the bottom.
-  fixed_height() = 8 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(8 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification below is being deleted. |reposition_top| should remain at the
-  // same offset from the bottom.
-  fixed_height() = 8 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {false, false, true, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 3));
-  EXPECT_EQ(8 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification below is inserted with free space. |reposition_top| should
-  // remain at the same offset from the bottom.
-  fixed_height() = 8 + insets.height();
-  reposition_top() = 2 + top;
-  positions =
-      ComputeRepositionOffsets({1, 1, 1, 1}, {false, false, false, false},
-                               1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4));
-  EXPECT_EQ(8 + insets.height(), fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Notification below is inserted with no free space. |reposition_top| is
-  // forced to change its offset from the bottom.
-  fixed_height() = 8 + insets.height();
-  reposition_top() = 2 + top;
-  positions = ComputeRepositionOffsets({1, 1, 1, 4, 1},
-                                       {false, false, false, false, false},
-                                       1 /* target_index */, 0 /* padding */);
-  EXPECT_THAT(positions, ElementsAre(top, top + 2, top + 3, top + 4, top + 8));
-  EXPECT_EQ(8 + insets.height() + 1, fixed_height());
-  EXPECT_EQ(2 + top, reposition_top());
-
-  // Test padding.
-  fixed_height() = 20 + insets.height();
-  reposition_top() = 5 + top;
-  positions =
-      ComputeRepositionOffsets({5, 3, 3, 3}, {false, false, false, false},
-                               1 /* target_index */, 2 /* padding */);
-  EXPECT_THAT(positions,
-              ElementsAre(top, top + 7, top + 7 + 5, top + 7 + 5 + 5));
-  EXPECT_EQ(20 + insets.height() + 2, fixed_height());
-  EXPECT_EQ(5 + top + 2, reposition_top());
-}
-
-TEST_F(MessageListViewTest, RemoveNotification) {
-  message_list_view()->SetBounds(0, 0, 800, 600);
-
-  // Create dummy notifications.
-  auto* notification_view = CreateNotificationView(
-      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-                   base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"),
-                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-                   NotifierId(NotifierId::APPLICATION, "extension_id"),
-                   message_center::RichNotificationData(), nullptr));
-
-  message_list_view()->AddNotificationAt(notification_view, 0);
-  EXPECT_EQ(1, message_list_view()->child_count());
-  EXPECT_TRUE(message_list_view()->Contains(notification_view));
-
-  RunPendingAnimations();
-
-  message_list_view()->RemoveNotification(notification_view);
-
-  RunPendingAnimations();
-
-  EXPECT_EQ(0, message_list_view()->child_count());
-}
-
-TEST_F(MessageListViewTest, ClearAllClosableNotifications) {
-  message_list_view()->SetBounds(0, 0, 800, 600);
-
-  // Create dummy notifications.
-  auto* notification_view1 = CreateNotificationView(
-      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-                   base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"),
-                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-                   NotifierId(NotifierId::APPLICATION, "extension_id"),
-                   message_center::RichNotificationData(), nullptr));
-  auto* notification_view2 = CreateNotificationView(
-      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-                   base::UTF8ToUTF16("title 2"), base::UTF8ToUTF16("message2"),
-                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-                   NotifierId(NotifierId::APPLICATION, "extension_id"),
-                   message_center::RichNotificationData(), nullptr));
-
-  message_list_view()->AddNotificationAt(notification_view1, 0);
-  EXPECT_EQ(1, message_list_view()->child_count());
-  EXPECT_TRUE(notification_view1->visible());
-
-  RunPendingAnimations();
-
-  message_list_view()->AddNotificationAt(notification_view2, 1);
-  EXPECT_EQ(2, message_list_view()->child_count());
-  EXPECT_TRUE(notification_view2->visible());
-
-  RunPendingAnimations();
-
-  message_list_view()->ClearAllClosableNotifications(
-      message_list_view()->bounds());
-
-  RunPendingAnimations();
-
-  EXPECT_TRUE(is_on_all_notifications_cleared_called());
-}
-
-bool ContainsMessageView(MessageListView* message_list_view,
-                         NotificationViewMD* notification_view) {
-  for (int i = 0; i < message_list_view->child_count(); i++) {
-    DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-              message_list_view->child_at(i)->GetClassName());
-    if (static_cast<SlidableMessageView*>(message_list_view->child_at(i))
-            ->GetMessageView() == notification_view) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Regression test for crbug.com/713983
-TEST_F(MessageListViewTest, RemoveWhileClearAll) {
-  message_list_view()->SetBounds(0, 0, 800, 600);
-
-  // Create dummy notifications.
-  auto* notification_view1 = CreateNotificationView(
-      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
-                   base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"),
-                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-                   NotifierId(NotifierId::APPLICATION, "extension_id"),
-                   message_center::RichNotificationData(), nullptr));
-  auto* notification_view2 = CreateNotificationView(
-      Notification(NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
-                   base::UTF8ToUTF16("title 2"), base::UTF8ToUTF16("message2"),
-                   gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
-                   NotifierId(NotifierId::APPLICATION, "extension_id"),
-                   message_center::RichNotificationData(), nullptr));
-
-  message_list_view()->AddNotificationAt(notification_view1, 0);
-  RunPendingAnimations();
-
-  message_list_view()->AddNotificationAt(notification_view2, 1);
-  RunPendingAnimations();
-
-  // Call RemoveNotification()
-  EXPECT_TRUE(ContainsMessageView(message_list_view(), notification_view2));
-  message_list_view()->RemoveNotification(notification_view2);
-
-  // Call "Clear All" while notification_view2 is still in message_list_view.
-  EXPECT_TRUE(ContainsMessageView(message_list_view(), notification_view2));
-  message_list_view()->ClearAllClosableNotifications(
-      message_list_view()->bounds());
-
-  RunPendingAnimations();
-  EXPECT_TRUE(is_on_all_notifications_cleared_called());
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/notification_tray.cc b/ash/system/message_center/notification_tray.cc
deleted file mode 100644
index 8edae620..0000000
--- a/ash/system/message_center/notification_tray.cc
+++ /dev/null
@@ -1,623 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/notification_tray.h"
-
-#include <memory>
-
-#include "ash/accessibility/accessibility_controller.h"
-#include "ash/public/cpp/app_list/app_list_features.h"
-#include "ash/public/cpp/ash_switches.h"
-#include "ash/resources/vector_icons/vector_icons.h"
-#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/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/system/message_center/ash_popup_alignment_delegate.h"
-#include "ash/system/message_center/message_center_bubble.h"
-#include "ash/system/message_center/message_center_ui_controller.h"
-#include "ash/system/status_area_widget.h"
-#include "ash/system/tray/tray_bubble_view.h"
-#include "ash/system/tray/tray_bubble_wrapper.h"
-#include "ash/system/tray/tray_constants.h"
-#include "ash/system/tray/tray_container.h"
-#include "ash/system/tray/tray_utils.h"
-#include "base/auto_reset.h"
-#include "base/i18n/number_formatting.h"
-#include "base/i18n/rtl.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/display/display.h"
-#include "ui/display/screen.h"
-#include "ui/gfx/paint_vector_icon.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/views/message_popup_collection.h"
-#include "ui/strings/grit/ui_strings.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/layout/fill_layout.h"
-
-namespace ash {
-namespace {
-
-constexpr int kMaximumSmallIconCount = 3;
-
-constexpr int kTrayItemInnerIconSize = 16;
-
-constexpr gfx::Size kTrayItemOuterSize(26, 26);
-constexpr int kTrayMainAxisInset = 3;
-constexpr int kTrayCrossAxisInset = 0;
-
-constexpr int kTrayItemAnimationDurationMS = 200;
-
-constexpr size_t kMaximumNotificationNumber = 99;
-
-// in px. See https://crbug.com/754307.
-constexpr size_t kPaddingFromScreenTop = 8;
-
-constexpr float kBackgroundBlurRadius = 30.f;
-
-// Flag to disable animation. Only for testing.
-bool disable_animations_for_test = false;
-
-}  // namespace
-
-// Class to initialize and manage the NotificationBubble and TrayBubbleWrapper
-// instances for a bubble.
-class NotificationBubbleWrapper {
- public:
-  // Takes ownership of |bubble| and creates |bubble_wrapper_|.
-  NotificationBubbleWrapper(NotificationTray* tray,
-                            TrayBackgroundView* anchor_tray,
-                            MessageCenterBubble* bubble,
-                            bool show_by_click) {
-    bubble_.reset(bubble);
-    TrayBubbleView::InitParams init_params;
-    init_params.delegate = tray;
-    init_params.parent_window = anchor_tray->GetBubbleWindowContainer();
-    init_params.anchor_view = anchor_tray->GetBubbleAnchor();
-    init_params.anchor_alignment = tray->GetAnchorAlignment();
-    const int width = message_center::kNotificationWidth +
-                      message_center::kNotificationBorderThickness * 2 +
-                      message_center::kMarginBetweenItemsInList * 2;
-    init_params.min_width = width;
-    init_params.max_width = width;
-    init_params.max_height = bubble->max_height();
-    init_params.show_by_click = show_by_click;
-
-    TrayBubbleView* bubble_view = new TrayBubbleView(init_params);
-    bubble_view->set_color(SK_ColorTRANSPARENT);
-    bubble_view->layer()->SetFillsBoundsOpaquely(false);
-    bubble_view->set_anchor_view_insets(anchor_tray->GetBubbleAnchorInsets());
-    bubble_wrapper_ = std::make_unique<TrayBubbleWrapper>(
-        tray, bubble_view, false /* is_persistent */);
-    bubble->InitializeContents(bubble_view);
-
-    if (app_list_features::IsBackgroundBlurEnabled()) {
-      // ClientView's layer (See TrayBubbleView::InitializeAndShowBubble())
-      bubble_view->layer()->parent()->SetBackgroundBlur(kBackgroundBlurRadius);
-    }
-  }
-
-  MessageCenterBubble* bubble() const { return bubble_.get(); }
-
-  // Convenience accessors.
-  TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); }
-
- private:
-  std::unique_ptr<MessageCenterBubble> bubble_;
-  std::unique_ptr<TrayBubbleWrapper> bubble_wrapper_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationBubbleWrapper);
-};
-
-class NotificationTraySubview : public views::View,
-                                public gfx::AnimationDelegate {
- public:
-  NotificationTraySubview(gfx::AnimationContainer* container,
-                          NotificationTray* tray)
-      : tray_(tray) {
-    SetPaintToLayer();
-    layer()->SetFillsBoundsOpaquely(false);
-    views::View::SetVisible(false);
-    set_owned_by_client();
-
-    SetLayoutManager(std::make_unique<views::FillLayout>());
-
-    animation_ = std::make_unique<gfx::SlideAnimation>(this);
-    animation_->SetContainer(container);
-    animation_->SetSlideDuration(kTrayItemAnimationDurationMS);
-    animation_->SetTweenType(gfx::Tween::LINEAR);
-  }
-
-  void SetVisible(bool set_visible) override {
-    if (!GetWidget() || disable_animations_for_test) {
-      views::View::SetVisible(set_visible);
-      return;
-    }
-
-    if (!set_visible) {
-      animation_->Hide();
-      AnimationProgressed(animation_.get());
-    } else {
-      animation_->Show();
-      AnimationProgressed(animation_.get());
-      views::View::SetVisible(true);
-    }
-  }
-
-  void HideAndDelete() {
-    SetVisible(false);
-
-    if (!visible() && !animation_->is_animating()) {
-      if (parent())
-        parent()->RemoveChildView(this);
-      base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
-    } else {
-      delete_after_animation_ = true;
-    }
-  }
-
- protected:
-  // Overridden from views::View:
-  gfx::Size CalculatePreferredSize() const override {
-    if (!animation_.get() || !animation_->is_animating())
-      return kTrayItemOuterSize;
-
-    // Animate the width (or height) when this item shows (or hides) so that
-    // the icons on the left are shifted with the animation.
-    // Note that TrayItemView does the same thing.
-    gfx::Size size = kTrayItemOuterSize;
-    if (tray_->shelf()->IsHorizontalAlignment()) {
-      size.set_width(std::max(
-          1, gfx::ToRoundedInt(size.width() * animation_->GetCurrentValue())));
-    } else {
-      size.set_height(std::max(
-          1, gfx::ToRoundedInt(size.height() * animation_->GetCurrentValue())));
-    }
-    return size;
-  }
-
-  int GetHeightForWidth(int width) const override {
-    return GetPreferredSize().height();
-  }
-
- private:
-  // gfx::AnimationDelegate:
-  void AnimationProgressed(const gfx::Animation* animation) override {
-    // After HideAndDelete() has been called and |this| is responsible for
-    // deleting itself, but |tray_| has been deleted before the animation
-    // reached its end, |this| will be parentless. It's ok to stop the animation
-    // (deleting |this|). See https://crbug.com/841768
-    if (!parent()) {
-      DCHECK(delete_after_animation_);
-      animation_->Stop();
-      return;
-    }
-
-    gfx::Transform transform;
-    if (tray_->shelf()->IsHorizontalAlignment()) {
-      transform.Translate(0, animation->CurrentValueBetween(
-                                 static_cast<double>(height()) / 2., 0.));
-    } else {
-      transform.Translate(
-          animation->CurrentValueBetween(static_cast<double>(width() / 2.), 0.),
-          0);
-    }
-    transform.Scale(animation->GetCurrentValue(), animation->GetCurrentValue());
-    layer()->SetTransform(transform);
-    PreferredSizeChanged();
-  }
-
-  void AnimationEnded(const gfx::Animation* animation) override {
-    if (animation->GetCurrentValue() < 0.1)
-      views::View::SetVisible(false);
-
-    if (delete_after_animation_) {
-      if (parent())
-        parent()->RemoveChildView(this);
-      base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
-    }
-  }
-  void AnimationCanceled(const gfx::Animation* animation) override {
-    AnimationEnded(animation);
-  }
-
-  std::unique_ptr<gfx::SlideAnimation> animation_;
-  bool delete_after_animation_ = false;
-  NotificationTray* tray_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationTraySubview);
-};
-
-class NotificationTrayImageSubview : public NotificationTraySubview {
- public:
-  NotificationTrayImageSubview(const gfx::ImageSkia& image,
-                               gfx::AnimationContainer* container,
-                               NotificationTray* tray)
-      : NotificationTraySubview(container, tray) {
-    DCHECK(image.size() ==
-           gfx::Size(kTrayItemInnerIconSize, kTrayItemInnerIconSize));
-    view_ = new views::ImageView();
-    view_->SetImage(image);
-    view_->set_tooltip_text(
-        l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_FOOTER_TITLE));
-    AddChildView(view_);
-  }
-
- private:
-  views::ImageView* view_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationTrayImageSubview);
-};
-
-class NotificationTrayLabelSubview : public NotificationTraySubview {
- public:
-  NotificationTrayLabelSubview(gfx::AnimationContainer* container,
-                               NotificationTray* tray)
-      : NotificationTraySubview(container, tray) {
-    view_ = new views::Label();
-    SetupLabelForTray(view_);
-    AddChildView(view_);
-  }
-
-  void SetNotificationCount(bool small_icons_exist, size_t notification_count) {
-    notification_count = std::min(notification_count,
-                                  kMaximumNotificationNumber);  // cap with 99
-
-    // TODO(yoshiki): Use a string for "99" and "+99".
-
-    base::string16 str = base::FormatNumber(notification_count);
-    if (small_icons_exist) {
-      str = base::ASCIIToUTF16("+") + str;
-      if (base::i18n::IsRTL())
-        base::i18n::WrapStringWithRTLFormatting(&str);
-    }
-
-    view_->SetText(str);
-    SchedulePaint();
-  }
-
- private:
-  views::Label* view_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationTrayLabelSubview);
-};
-
-NotificationTray::NotificationTray(Shelf* shelf,
-                                   aura::Window* status_area_window)
-    : TrayBackgroundView(shelf),
-      status_area_window_(status_area_window),
-      show_message_center_on_unlock_(false),
-      should_update_tray_content_(false) {
-  DCHECK(shelf);
-  DCHECK(status_area_window_);
-
-  SetInkDropMode(InkDropMode::ON);
-  gfx::ImageSkia bell_image =
-      CreateVectorIcon(kShelfNotificationsIcon, kShelfIconColor);
-  bell_icon_ = std::make_unique<NotificationTrayImageSubview>(
-      bell_image, animation_container_.get(), this);
-  tray_container()->AddChildView(bell_icon_.get());
-
-  gfx::ImageSkia quiet_mode_image =
-      CreateVectorIcon(kNotificationCenterDoNotDisturbOnIcon,
-                       kTrayItemInnerIconSize, kShelfIconColor);
-  quiet_mode_icon_ = std::make_unique<NotificationTrayImageSubview>(
-      quiet_mode_image, animation_container_.get(), this);
-  tray_container()->AddChildView(quiet_mode_icon_.get());
-
-  counter_ = std::make_unique<NotificationTrayLabelSubview>(
-      animation_container_.get(), this);
-  tray_container()->AddChildView(counter_.get());
-
-  message_center_ui_controller_ =
-      std::make_unique<MessageCenterUiController>(this);
-  popup_alignment_delegate_ =
-      std::make_unique<AshPopupAlignmentDelegate>(shelf);
-  popup_collection_ = std::make_unique<message_center::MessagePopupCollection>(
-      popup_alignment_delegate_.get());
-  display::Screen* screen = display::Screen::GetScreen();
-  popup_alignment_delegate_->StartObserving(
-      screen, screen->GetDisplayNearestWindow(status_area_window_));
-  OnMessageCenterContentsChanged();
-
-  tray_container()->SetMargin(kTrayMainAxisInset, kTrayCrossAxisInset);
-}
-
-NotificationTray::~NotificationTray() {
-  // Release any child views that might have back pointers before ~View().
-  message_center_bubble_.reset();
-  popup_alignment_delegate_.reset();
-  popup_collection_.reset();
-}
-
-// static
-void NotificationTray::DisableAnimationsForTest(bool disable) {
-  disable_animations_for_test = disable;
-}
-
-// Public methods.
-
-bool NotificationTray::ShowMessageCenter(bool show_by_click) {
-  if (!ShouldShowMessageCenter())
-    return false;
-
-  if (IsMessageCenterVisible())
-    return true;
-
-  MessageCenterBubble* message_center_bubble =
-      new MessageCenterBubble(message_center());
-
-  // In the horizontal case, message center starts from the top of the shelf.
-  // In the vertical case, it starts from the bottom of NotificationTray.
-  const int max_height = (shelf()->IsHorizontalAlignment()
-                              ? shelf()->GetUserWorkAreaBounds().height()
-                              : GetBoundsInScreen().bottom() -
-                                    shelf()->GetUserWorkAreaBounds().y());
-  // Sets the maximum height, considering the padding from the top edge of
-  // screen. This padding should be applied in all types of shelf alignment.
-  message_center_bubble->SetMaxHeight(max_height - kPaddingFromScreenTop);
-
-  // For vertical shelf alignments, anchor to the NotificationTray, but for
-  // horizontal (i.e. bottom) shelves, anchor to the system tray.
-  TrayBackgroundView* anchor_tray = this;
-  if (shelf()->IsHorizontalAlignment())
-    anchor_tray = shelf()->GetSystemTrayAnchorView();
-
-  message_center_bubble_ = std::make_unique<NotificationBubbleWrapper>(
-      this, anchor_tray, message_center_bubble, show_by_click);
-
-  shelf()->UpdateAutoHideState();
-  SetIsActive(true);
-  return true;
-}
-
-void NotificationTray::HideMessageCenter() {
-  if (!message_center_bubble())
-    return;
-
-  SetIsActive(false);
-  message_center_bubble_.reset();
-  show_message_center_on_unlock_ = false;
-  shelf()->UpdateAutoHideState();
-}
-
-void NotificationTray::SetTrayBubbleHeight(int height) {
-  popup_alignment_delegate_->SetTrayBubbleHeight(height);
-}
-
-int NotificationTray::tray_bubble_height_for_test() const {
-  return popup_alignment_delegate_->tray_bubble_height_for_test();
-}
-
-bool NotificationTray::ShowPopups() {
-  if (IsMessageCenterVisible())
-    return false;
-  return true;
-}
-
-void NotificationTray::HidePopups() {
-  DCHECK(popup_collection_.get());
-}
-
-// Private methods.
-
-bool NotificationTray::ShouldShowMessageCenter() const {
-  // Hidden at login screen, during supervised user creation, etc.
-  return Shell::Get()->session_controller()->ShouldShowNotificationTray();
-}
-
-bool NotificationTray::IsMessageCenterVisible() const {
-  return message_center_bubble() &&
-         message_center_bubble()->bubble()->IsVisible();
-}
-
-void NotificationTray::UpdateAfterShelfAlignmentChange() {
-  TrayBackgroundView::UpdateAfterShelfAlignmentChange();
-  // Destroy existing message center bubble so that it won't be reused.
-  message_center_ui_controller_->HideMessageCenterBubble();
-
-  // Destroy any existing popup bubbles and rebuilt if necessary.
-  message_center_ui_controller_->HidePopupBubble();
-  message_center_ui_controller_->ShowPopupBubble();
-}
-
-void NotificationTray::UpdateAfterRootWindowBoundsChange(
-    const gfx::Rect& old_bounds,
-    const gfx::Rect& new_bounds) {
-  TrayBackgroundView::UpdateAfterRootWindowBoundsChange(old_bounds, new_bounds);
-  // Hide the message center bubble, since the bounds may not have enough to
-  // show the current size of the message center. This  handler is invoked when
-  // the screen is rotated or the screen size is changed.
-  message_center_ui_controller_->HideMessageCenterBubble();
-}
-
-void NotificationTray::AnchorUpdated() {
-  if (message_center_bubble()) {
-    UpdateClippingWindowBounds();
-    shelf()->GetSystemTrayAnchorView()->UpdateClippingWindowBounds();
-    message_center_bubble()->bubble_view()->UpdateBubble();
-    // Should check |message_center_bubble_| again here. Since UpdateBubble
-    // above set the bounds of the bubble which will stop the current
-    // animation. If notification bubble is during animation to close,
-    // CloseBubbleObserver in TrayBackgroundView will close the bubble if
-    // animation finished.
-    if (message_center_bubble())
-      UpdateBubbleViewArrow(message_center_bubble()->bubble_view());
-  }
-}
-
-base::string16 NotificationTray::GetAccessibleNameForTray() {
-  return l10n_util::GetStringFUTF16Int(
-      IDS_MESSAGE_CENTER_ACCESSIBLE_NAME,
-      static_cast<int>(message_center_ui_controller_->message_center()
-                           ->NotificationCount()));
-}
-
-void NotificationTray::HideBubbleWithView(const TrayBubbleView* bubble_view) {
-  if (message_center_bubble() &&
-      bubble_view == message_center_bubble()->bubble_view()) {
-    message_center_ui_controller_->HideMessageCenterBubble();
-  } else if (popup_collection_.get()) {
-    message_center_ui_controller_->HidePopupBubble();
-  }
-}
-
-void NotificationTray::BubbleViewDestroyed() {
-  if (message_center_bubble())
-    message_center_bubble()->bubble()->BubbleViewDestroyed();
-}
-
-base::string16 NotificationTray::GetAccessibleNameForBubble() {
-  return GetAccessibleNameForTray();
-}
-
-bool NotificationTray::ShouldEnableExtraKeyboardAccessibility() {
-  return Shell::Get()->accessibility_controller()->IsSpokenFeedbackEnabled();
-}
-
-void NotificationTray::HideBubble(const TrayBubbleView* bubble_view) {
-  HideBubbleWithView(bubble_view);
-}
-
-void NotificationTray::OnMessageCenterContentsChanged() {
-  // Do not update the tray contents directly. Multiple change events can happen
-  // consecutively, and calling Update in the middle of those events will show
-  // intermediate unread counts for a moment.
-  should_update_tray_content_ = true;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&NotificationTray::UpdateTrayContent, AsWeakPtr()));
-}
-
-void NotificationTray::UpdateTrayContent() {
-  if (!should_update_tray_content_)
-    return;
-  should_update_tray_content_ = false;
-
-  std::unordered_set<std::string> notification_ids;
-  for (auto& pair : visible_small_icons_)
-    notification_ids.insert(pair.first);
-
-  // Add small icons (up to kMaximumSmallIconCount = 3).
-  message_center::MessageCenter* message_center =
-      message_center_ui_controller_->message_center();
-  size_t visible_small_icon_count = 0;
-  for (const auto* notification : message_center->GetVisibleNotifications()) {
-    gfx::Image image = notification->GenerateMaskedSmallIcon(
-        kTrayItemInnerIconSize, kTrayIconColor);
-    if (image.IsEmpty())
-      continue;
-
-    if (visible_small_icon_count >= kMaximumSmallIconCount)
-      break;
-    visible_small_icon_count++;
-
-    notification_ids.erase(notification->id());
-    if (visible_small_icons_.count(notification->id()) != 0)
-      continue;
-
-    auto item = std::make_unique<NotificationTrayImageSubview>(
-        image.AsImageSkia(), animation_container_.get(), this);
-    tray_container()->AddChildViewAt(item.get(), 0);
-    item->SetVisible(true);
-    visible_small_icons_.insert(
-        std::make_pair(notification->id(), std::move(item)));
-  }
-
-  // Remove unnecessary icons.
-  for (const std::string& id : notification_ids) {
-    NotificationTrayImageSubview* item = visible_small_icons_[id].release();
-    visible_small_icons_.erase(id);
-    item->HideAndDelete();
-  }
-
-  // Show or hide the bell icon.
-  size_t visible_notification_count = message_center->NotificationCount();
-  bell_icon_->SetVisible(visible_notification_count == 0 &&
-                         !message_center->IsQuietMode());
-  quiet_mode_icon_->SetVisible(visible_notification_count == 0 &&
-                               message_center->IsQuietMode());
-
-  // Show or hide the counter.
-  size_t hidden_icon_count =
-      visible_notification_count - visible_small_icon_count;
-  if (hidden_icon_count != 0) {
-    counter_->SetVisible(true);
-    counter_->SetNotificationCount(
-        (visible_small_icon_count != 0),  // small_icons_exist
-        hidden_icon_count);
-  } else {
-    counter_->SetVisible(false);
-  }
-
-  SetVisible(ShouldShowMessageCenter());
-  PreferredSizeChanged();
-  Layout();
-  SchedulePaint();
-}
-
-void NotificationTray::ClickedOutsideBubble() {
-  // Only hide the message center
-  if (!IsMessageCenterVisible())
-    return;
-
-  message_center_ui_controller_->HideMessageCenterBubble();
-}
-
-bool NotificationTray::PerformAction(const ui::Event& event) {
-  UserMetricsRecorder::RecordUserClickOnTray(
-      LoginMetricsRecorder::TrayClickTarget::kNotificationTray);
-  if (IsMessageCenterVisible())
-    CloseBubble();
-  else
-    ShowBubble(event.IsMouseEvent() || event.IsGestureEvent());
-  return true;
-}
-
-void NotificationTray::CloseBubble() {
-  message_center_ui_controller_->HideMessageCenterBubble();
-}
-
-void NotificationTray::ShowBubble(bool show_by_click) {
-  if (!IsMessageCenterVisible())
-    message_center_ui_controller_->ShowMessageCenterBubble(show_by_click);
-}
-
-void NotificationTray::ActivateBubble() {
-  TrayBubbleView* bubble_view = GetBubbleView();
-  // If the bubble is in the process of closing, do not try to activate it.
-  if (bubble_view->GetWidget()->IsClosed())
-    return;
-  bubble_view->set_can_activate(true);
-  bubble_view->GetWidget()->Activate();
-}
-
-TrayBubbleView* NotificationTray::GetBubbleView() {
-  return message_center_bubble_ ? message_center_bubble_->bubble_view()
-                                : nullptr;
-}
-
-message_center::MessageCenter* NotificationTray::message_center() const {
-  return message_center_ui_controller_->message_center();
-}
-
-// Methods for testing
-
-bool NotificationTray::IsPopupVisible() const {
-  return message_center_ui_controller_->popups_visible();
-}
-
-MessageCenterBubble* NotificationTray::GetMessageCenterBubbleForTest() {
-  if (!message_center_bubble())
-    return nullptr;
-  return static_cast<MessageCenterBubble*>(message_center_bubble()->bubble());
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/notification_tray.h b/ash/system/message_center/notification_tray.h
deleted file mode 100644
index dcd1942f..0000000
--- a/ash/system/message_center/notification_tray.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_TRAY_H_
-#define ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_TRAY_H_
-
-#include <memory>
-
-#include "ash/ash_export.h"
-#include "ash/login_status.h"
-#include "ash/system/message_center/message_center_ui_delegate.h"
-#include "ash/system/tray/tray_background_view.h"
-#include "ash/system/tray/tray_bubble_view.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/gfx/animation/animation_container.h"
-
-namespace aura {
-class Window;
-}
-
-namespace message_center {
-class MessageCenter;
-class MessagePopupCollection;
-}  // namespace message_center
-
-namespace ash {
-class AshPopupAlignmentDelegate;
-class MessageCenterBubble;
-class MessageCenterUiController;
-class NotificationBubbleWrapper;
-class NotificationTrayImageSubview;
-class NotificationTrayLabelSubview;
-
-// Status area tray for showing System, Chrome App, Web and ARC++ app
-// notifications. This hosts a MessageCenter class which manages the
-// notification list. This class contains the Ash specific tray implementation.
-class ASH_EXPORT NotificationTray
-    : public TrayBackgroundView,
-      public MessageCenterUiDelegate,
-      public base::SupportsWeakPtr<NotificationTray> {
- public:
-  NotificationTray(Shelf* shelf, aura::Window* status_area_window);
-  ~NotificationTray() override;
-
-  static void DisableAnimationsForTest(bool disable);
-
-  // Sets the height of the system tray bubble (or legacy notification bubble)
-  // from the edge of the work area so that the notification popups don't
-  // overlap with the tray. Pass 0 if no bubble is shown.
-  void SetTrayBubbleHeight(int height);
-
-  // Returns the current tray bubble height or 0 if there is no bubble.
-  int tray_bubble_height_for_test() const;
-
-  // Returns true if the message center bubble is visible.
-  bool IsMessageCenterVisible() const;
-
-  // Overridden from TrayBackgroundView.
-  void UpdateAfterShelfAlignmentChange() override;
-  void UpdateAfterRootWindowBoundsChange(const gfx::Rect& old_bounds,
-                                         const gfx::Rect& new_bounds) override;
-  void AnchorUpdated() override;
-  base::string16 GetAccessibleNameForTray() override;
-  void HideBubbleWithView(const TrayBubbleView* bubble_view) override;
-  void ClickedOutsideBubble() override;
-  bool PerformAction(const ui::Event& event) override;
-  void CloseBubble() override;
-  void ShowBubble(bool show_by_click) override;
-  TrayBubbleView* GetBubbleView() override;
-
-  // Overridden from TrayBubbleView::Delegate.
-  void BubbleViewDestroyed() override;
-  base::string16 GetAccessibleNameForBubble() override;
-  bool ShouldEnableExtraKeyboardAccessibility() override;
-  void HideBubble(const TrayBubbleView* bubble_view) override;
-
-  // Overridden from message_center::UiDelegate.
-  void OnMessageCenterContentsChanged() override;
-  bool ShowMessageCenter(bool show_by_click) override;
-  void HideMessageCenter() override;
-  bool ShowPopups() override;
-  void HidePopups() override;
-
-  // Activates the notification tray bubble.
-  void ActivateBubble();
-
-  message_center::MessageCenter* message_center() const;
-
- private:
-  friend class NotificationTrayTest;
-
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, Notifications);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, NotificationPopupBubble);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest,
-                           ManyMessageCenterNotifications);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, ManyPopupNotifications);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, PopupShownOnBothDisplays);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, PopupAndSystemTray);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, PopupAndAutoHideShelf);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, VisibleSmallIcon);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, QuietModeIcon);
-  FRIEND_TEST_ALL_PREFIXES(NotificationTrayTest, CloseOnActivation);
-
-  void UpdateTrayContent();
-
-  // Queries login status and the status area widget to determine visibility of
-  // the message center.
-  bool ShouldShowMessageCenter() const;
-
-  NotificationBubbleWrapper* message_center_bubble() const {
-    return message_center_bubble_.get();
-  }
-
-  // Testing accessors.
-  bool IsPopupVisible() const;
-  MessageCenterBubble* GetMessageCenterBubbleForTest();
-
-  aura::Window* status_area_window_;
-  std::unique_ptr<MessageCenterUiController> message_center_ui_controller_;
-  std::unique_ptr<NotificationBubbleWrapper> message_center_bubble_;
-  std::unique_ptr<message_center::MessagePopupCollection> popup_collection_;
-  std::unique_ptr<views::View> bell_icon_;
-  std::unique_ptr<views::View> quiet_mode_icon_;
-  std::unique_ptr<NotificationTrayLabelSubview> counter_;
-
-  scoped_refptr<gfx::AnimationContainer> animation_container_ =
-      new gfx::AnimationContainer();
-
-  std::unordered_map<std::string, std::unique_ptr<NotificationTrayImageSubview>>
-      visible_small_icons_;
-
-  bool show_message_center_on_unlock_;
-
-  bool should_update_tray_content_;
-
-  std::unique_ptr<AshPopupAlignmentDelegate> popup_alignment_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationTray);
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_TRAY_H_
diff --git a/ash/system/message_center/notification_tray_unittest.cc b/ash/system/message_center/notification_tray_unittest.cc
deleted file mode 100644
index 6ef89781..0000000
--- a/ash/system/message_center/notification_tray_unittest.cc
+++ /dev/null
@@ -1,571 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/message_center/notification_tray.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "ash/public/cpp/ash_features.h"
-#include "ash/public/cpp/shell_window_ids.h"
-#include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_layout_manager.h"
-#include "ash/shell.h"
-#include "ash/system/message_center/ash_popup_alignment_delegate.h"
-#include "ash/system/message_center/message_center_bubble.h"
-#include "ash/system/message_center/message_center_ui_controller.h"
-#include "ash/system/message_center/message_center_view.h"
-#include "ash/system/screen_layout_observer.h"
-#include "ash/system/status_area_widget.h"
-#include "ash/system/status_area_widget_test_helper.h"
-#include "ash/system/tray/system_tray.h"
-#include "ash/system/tray/system_tray_item.h"
-#include "ash/system/tray/tray_container.h"
-#include "ash/test/ash_test_base.h"
-#include "ash/wm/window_state.h"
-#include "ash/wm/window_util.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "ui/display/display.h"
-#include "ui/display/manager/display_manager.h"
-#include "ui/display/manager/display_manager_utilities.h"
-#include "ui/display/screen.h"
-#include "ui/events/test/event_generator.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/image/image_unittest_util.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/notification_list.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/public/cpp/notification_types.h"
-#include "ui/message_center/views/message_popup_collection.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace ash {
-
-namespace {
-
-NotificationTray* GetTray() {
-  return StatusAreaWidgetTestHelper::GetStatusAreaWidget()->notification_tray();
-}
-
-NotificationTray* GetSecondaryTray() {
-  StatusAreaWidget* status_area_widget =
-      StatusAreaWidgetTestHelper::GetSecondaryStatusAreaWidget();
-  if (status_area_widget)
-    return status_area_widget->notification_tray();
-  return NULL;
-}
-
-message_center::MessageCenter* GetMessageCenter() {
-  return GetTray()->message_center();
-}
-
-SystemTray* GetSystemTray() {
-  return StatusAreaWidgetTestHelper::GetStatusAreaWidget()->system_tray();
-}
-
-// Trivial item implementation for testing PopupAndSystemTray test case.
-class TestItem : public SystemTrayItem {
- public:
-  TestItem()
-      : SystemTrayItem(GetSystemTray(), SystemTrayItemUmaType::UMA_TEST) {}
-
-  views::View* CreateDefaultView(LoginStatus status) override {
-    views::View* default_view = new views::View;
-    default_view->SetLayoutManager(std::make_unique<views::FillLayout>());
-    default_view->AddChildView(new views::Label(base::UTF8ToUTF16("Default")));
-    return default_view;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestItem);
-};
-
-}  // namespace
-
-class NotificationTrayTest : public AshTestBase {
- public:
-  NotificationTrayTest() = default;
-  ~NotificationTrayTest() override = default;
-
- protected:
-  void AddNotification(const std::string& id) {
-    std::unique_ptr<message_center::Notification> notification;
-    notification.reset(new message_center::Notification(
-        message_center::NOTIFICATION_TYPE_SIMPLE, id,
-        base::ASCIIToUTF16("Test Web Notification"),
-        base::ASCIIToUTF16("Notification message body."), gfx::Image(),
-        base::ASCIIToUTF16("www.test.org"), GURL(),
-        message_center::NotifierId(), message_center::RichNotificationData(),
-        NULL /* delegate */));
-    GetMessageCenter()->AddNotification(std::move(notification));
-  }
-
-  void UpdateNotification(const std::string& old_id,
-                          const std::string& new_id) {
-    std::unique_ptr<message_center::Notification> notification;
-    notification.reset(new message_center::Notification(
-        message_center::NOTIFICATION_TYPE_SIMPLE, new_id,
-        base::ASCIIToUTF16("Updated Web Notification"),
-        base::ASCIIToUTF16("Updated message body."), gfx::Image(),
-        base::ASCIIToUTF16("www.test.org"), GURL(),
-        message_center::NotifierId(), message_center::RichNotificationData(),
-        NULL /* delegate */));
-    GetMessageCenter()->UpdateNotification(old_id, std::move(notification));
-  }
-
-  void RemoveNotification(const std::string& id) {
-    GetMessageCenter()->RemoveNotification(id, false);
-  }
-
-  views::Widget* GetWidget() { return GetTray()->GetWidget(); }
-
-  int GetPopupWorkAreaBottom() {
-    return GetPopupWorkAreaBottomForTray(GetTray());
-  }
-
-  int GetPopupWorkAreaBottomForTray(NotificationTray* tray) {
-    return tray->popup_alignment_delegate_->GetWorkArea().bottom();
-  }
-
-  bool IsPopupVisible() { return GetTray()->IsPopupVisible(); }
-
-  static std::unique_ptr<views::Widget> CreateTestWidget() {
-    return AshTestBase::CreateTestWidget(
-        nullptr, kShellWindowId_DefaultContainer, gfx::Rect(1, 2, 3, 4));
-  }
-
-  static void UpdateAutoHideStateNow() {
-    GetPrimaryShelf()->shelf_layout_manager()->UpdateAutoHideStateNow();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NotificationTrayTest);
-};
-
-TEST_F(NotificationTrayTest, Notifications) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  // TODO(mukai): move this test case to ui/message_center.
-  ASSERT_TRUE(GetWidget());
-
-  // Add a notification.
-  AddNotification("test_id1");
-  EXPECT_EQ(1u, GetMessageCenter()->NotificationCount());
-  EXPECT_TRUE(GetMessageCenter()->FindVisibleNotificationById("test_id1"));
-  AddNotification("test_id2");
-  AddNotification("test_id2");
-  EXPECT_EQ(2u, GetMessageCenter()->NotificationCount());
-  EXPECT_TRUE(GetMessageCenter()->FindVisibleNotificationById("test_id2"));
-
-  // Ensure that updating a notification does not affect the count.
-  UpdateNotification("test_id2", "test_id3");
-  UpdateNotification("test_id3", "test_id3");
-  EXPECT_EQ(2u, GetMessageCenter()->NotificationCount());
-  EXPECT_FALSE(GetMessageCenter()->FindVisibleNotificationById("test_id2"));
-
-  // Ensure that Removing the first notification removes it from the tray.
-  RemoveNotification("test_id1");
-  EXPECT_FALSE(GetMessageCenter()->FindVisibleNotificationById("test_id1"));
-  EXPECT_EQ(1u, GetMessageCenter()->NotificationCount());
-
-  // Remove the remianing notification.
-  RemoveNotification("test_id3");
-  EXPECT_EQ(0u, GetMessageCenter()->NotificationCount());
-  EXPECT_FALSE(GetMessageCenter()->FindVisibleNotificationById("test_id3"));
-}
-
-TEST_F(NotificationTrayTest, NotificationPopupBubble) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  // TODO(mukai): move this test case to ui/message_center.
-  ASSERT_TRUE(GetWidget());
-
-  // Adding a notification should show the popup bubble.
-  AddNotification("test_id1");
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-
-  // Updating a notification should not hide the popup bubble.
-  AddNotification("test_id2");
-  UpdateNotification("test_id2", "test_id3");
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-
-  // Removing the first notification should not hide the popup bubble.
-  RemoveNotification("test_id1");
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-
-  // Removing the visible notification should hide the popup bubble.
-  RemoveNotification("test_id3");
-  EXPECT_FALSE(GetTray()->IsPopupVisible());
-
-  // Now test that we can show multiple popups and then show the message center.
-  AddNotification("test_id4");
-  AddNotification("test_id5");
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-
-  GetTray()->message_center_ui_controller_->ShowMessageCenterBubble(
-      false /* show_by_click */);
-  GetTray()->message_center_ui_controller_->HideMessageCenterBubble();
-
-  EXPECT_FALSE(GetTray()->IsPopupVisible());
-}
-
-using message_center::NotificationList;
-
-TEST_F(NotificationTrayTest, ManyMessageCenterNotifications) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  // Add the max visible notifications +1, ensure the correct visible number.
-  size_t notifications_to_add = MessageCenterView::kMaxVisibleNotifications + 1;
-  for (size_t i = 0; i < notifications_to_add; ++i) {
-    std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
-    AddNotification(id);
-  }
-  bool shown =
-      GetTray()->message_center_ui_controller_->ShowMessageCenterBubble(
-          false /* show_by_click */);
-  EXPECT_TRUE(shown);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(GetTray()->message_center_bubble() != NULL);
-  EXPECT_EQ(notifications_to_add, GetMessageCenter()->NotificationCount());
-  EXPECT_EQ(
-      MessageCenterView::kMaxVisibleNotifications,
-      GetTray()->GetMessageCenterBubbleForTest()->NumMessageViewsForTest());
-}
-
-TEST_F(NotificationTrayTest, ManyPopupNotifications) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  // Add the max visible popup notifications +1, ensure the correct num visible.
-  size_t notifications_to_add =
-      message_center::kMaxVisiblePopupNotifications + 1;
-  for (size_t i = 0; i < notifications_to_add; ++i) {
-    std::string id = base::StringPrintf("test_id%d", static_cast<int>(i));
-    AddNotification(id);
-  }
-  GetTray()->ShowPopups();
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  EXPECT_EQ(notifications_to_add, GetMessageCenter()->NotificationCount());
-  NotificationList::PopupNotifications popups =
-      GetMessageCenter()->GetPopupNotifications();
-  EXPECT_EQ(message_center::kMaxVisiblePopupNotifications, popups.size());
-}
-
-// Verifies if the notification appears on both displays when extended mode.
-TEST_F(NotificationTrayTest, PopupShownOnBothDisplays) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  Shell::Get()->screen_layout_observer()->set_show_notifications_for_testing(
-      true);
-
-  const int64_t first_display_id =
-      display::Screen::GetScreen()->GetPrimaryDisplay().id();
-  const int64_t second_display_id = first_display_id + 1;
-  display::ManagedDisplayInfo first_display_info =
-      display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500));
-  display::ManagedDisplayInfo second_display_info =
-      display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500));
-  std::vector<display::ManagedDisplayInfo> display_info_list;
-  display_info_list.emplace_back(first_display_info);
-  display_info_list.emplace_back(second_display_info);
-  display_manager()->OnNativeDisplaysChanged(display_info_list);
-
-  // OnNativeDisplaysChanged() creates the display notifications, so popup is
-  // visible.
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  NotificationTray* secondary_tray = GetSecondaryTray();
-  ASSERT_TRUE(secondary_tray);
-  EXPECT_TRUE(secondary_tray->IsPopupVisible());
-
-  // Transition to mirroring and then back to extended display, which recreates
-  // root window controller and shelf with having notifications. This code
-  // verifies it doesn't cause crash and popups are still visible. See
-  // http://crbug.com/263664
-
-  // Turn on mirror mode.
-  display_manager()->SetMirrorMode(display::MirrorMode::kNormal, base::nullopt);
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  EXPECT_FALSE(GetSecondaryTray());
-
-  // Disconnect a display to end mirror mode.
-  display_info_list.erase(display_info_list.end() - 1);
-  display_manager()->OnNativeDisplaysChanged(display_info_list);
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  EXPECT_FALSE(GetSecondaryTray());
-
-  // Restore mirror mode.
-  display_info_list.emplace_back(second_display_info);
-  display_manager()->OnNativeDisplaysChanged(display_info_list);
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  EXPECT_FALSE(GetSecondaryTray());
-
-  // Turn off mirror mode.
-  display_manager()->SetMirrorMode(display::MirrorMode::kOff, base::nullopt);
-  display_manager()->OnNativeDisplaysChanged(display_info_list);
-  secondary_tray = GetSecondaryTray();
-  ASSERT_TRUE(secondary_tray);
-  EXPECT_TRUE(secondary_tray->IsPopupVisible());
-}
-
-// PopupAndSystemTray may fail in platforms other than ChromeOS because the
-// RootWindow's bound can be bigger than display::Display's work area so that
-// openingsystem tray doesn't affect at all the work area of popups.
-TEST_F(NotificationTrayTest, PopupAndSystemTray) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  GetSystemTray()->AddTrayItem(std::make_unique<TestItem>());
-
-  AddNotification("test_id");
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  int bottom = GetPopupWorkAreaBottom();
-
-  // System tray is created, the popup's work area should be narrowed but still
-  // visible.
-  GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW,
-                                   false /* show_by_click */);
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  int bottom_with_tray = GetPopupWorkAreaBottom();
-  EXPECT_GT(bottom, bottom_with_tray);
-}
-
-TEST_F(NotificationTrayTest, PopupAndAutoHideShelf) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  AddNotification("test_id");
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  int bottom = GetPopupWorkAreaBottom();
-
-  // Shelf's auto-hide state won't be HIDDEN unless window exists.
-  std::unique_ptr<views::Widget> widget(CreateTestWidget());
-  Shelf* shelf = GetPrimaryShelf();
-  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
-
-  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
-  int bottom_auto_hidden = GetPopupWorkAreaBottom();
-  EXPECT_LT(bottom, bottom_auto_hidden);
-
-  // Close the window, which shows the shelf.
-  widget.reset();
-  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
-  int bottom_auto_shown = GetPopupWorkAreaBottom();
-  EXPECT_EQ(bottom, bottom_auto_shown);
-
-  // Create the system tray during auto-hide.
-  widget = CreateTestWidget();
-  GetSystemTray()->AddTrayItem(std::make_unique<TestItem>());
-  GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW,
-                                   false /* show_by_click */);
-  UpdateAutoHideStateNow();
-
-  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
-  EXPECT_TRUE(GetTray()->IsPopupVisible());
-  int bottom_with_tray = GetPopupWorkAreaBottom();
-  EXPECT_GT(bottom_auto_shown, bottom_with_tray);
-}
-
-TEST_F(NotificationTrayTest, PopupAndFullscreen) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  AddNotification("test_id");
-  EXPECT_TRUE(IsPopupVisible());
-  int bottom = GetPopupWorkAreaBottom();
-
-  // Checks the work area for normal auto-hidden state.
-  std::unique_ptr<views::Widget> widget(CreateTestWidget());
-  Shelf* shelf = GetPrimaryShelf();
-  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
-  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
-  int bottom_auto_hidden = GetPopupWorkAreaBottom();
-  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
-
-  // Put |widget| into fullscreen without forcing the shelf to hide. Currently,
-  // this is used by immersive fullscreen and forces the shelf to be auto
-  // hidden.
-  wm::GetWindowState(widget->GetNativeWindow())
-      ->SetHideShelfWhenFullscreen(false);
-  widget->SetFullscreen(true);
-  base::RunLoop().RunUntilIdle();
-
-  // The work area for auto-hidden status of fullscreen is a bit larger
-  // since it doesn't even have the 3-pixel width.
-  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
-  int bottom_fullscreen_hidden = GetPopupWorkAreaBottom();
-  EXPECT_EQ(bottom_auto_hidden, bottom_fullscreen_hidden);
-
-  // Move the mouse cursor at the bottom, which shows the shelf.
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  gfx::Point bottom_right =
-      display::Screen::GetScreen()->GetPrimaryDisplay().bounds().bottom_right();
-  bottom_right.Offset(-1, -1);
-  generator->MoveMouseTo(bottom_right);
-  shelf->UpdateVisibilityState();
-  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
-  EXPECT_EQ(bottom, GetPopupWorkAreaBottom());
-
-  generator->MoveMouseTo(
-      display::Screen::GetScreen()->GetPrimaryDisplay().bounds().CenterPoint());
-  shelf->UpdateVisibilityState();
-  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
-  EXPECT_EQ(bottom_auto_hidden, GetPopupWorkAreaBottom());
-}
-
-TEST_F(NotificationTrayTest, PopupAndSystemTrayMultiDisplay) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  UpdateDisplay("800x600,600x400");
-
-  AddNotification("test_id");
-  int bottom = GetPopupWorkAreaBottom();
-  int bottom_second = GetPopupWorkAreaBottomForTray(GetSecondaryTray());
-
-  // System tray is created on the primary display. The popups in the secondary
-  // tray aren't affected.
-  GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW,
-                                   false /* show_by_click */);
-  EXPECT_GT(bottom, GetPopupWorkAreaBottom());
-  EXPECT_EQ(bottom_second, GetPopupWorkAreaBottomForTray(GetSecondaryTray()));
-}
-
-TEST_F(NotificationTrayTest, VisibleSmallIcon) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  EXPECT_EQ(0u, GetTray()->visible_small_icons_.size());
-  EXPECT_EQ(3, GetTray()->tray_container()->child_count());
-  std::unique_ptr<message_center::Notification> notification =
-      std::make_unique<message_center::Notification>(
-          message_center::NOTIFICATION_TYPE_SIMPLE, "test",
-          base::ASCIIToUTF16("Test System Notification"),
-          base::ASCIIToUTF16("Notification message body."), gfx::Image(),
-          base::ASCIIToUTF16("system"), GURL(),
-          message_center::NotifierId(
-              message_center::NotifierId::NotifierType::SYSTEM_COMPONENT,
-              "test"),
-          message_center::RichNotificationData(), nullptr /* delegate */);
-  notification->set_small_image(gfx::test::CreateImage(18, 18));
-  GetMessageCenter()->AddNotification(std::move(notification));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1u, GetTray()->visible_small_icons_.size());
-  EXPECT_EQ(4, GetTray()->tray_container()->child_count());
-}
-
-TEST_F(NotificationTrayTest, QuietModeIcon) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  NotificationTray::DisableAnimationsForTest(true);
-
-  AddNotification("test");
-  base::RunLoop().RunUntilIdle();
-
-  // There is a notification, so no bell & quiet mode icons are shown.
-  EXPECT_FALSE(GetTray()->bell_icon_->visible());
-  EXPECT_FALSE(GetTray()->quiet_mode_icon_->visible());
-
-  GetMessageCenter()->SetQuietMode(true);
-  base::RunLoop().RunUntilIdle();
-
-  // If there is a notification, setting quiet mode shouldn't change tray icons.
-  EXPECT_FALSE(GetTray()->bell_icon_->visible());
-  EXPECT_FALSE(GetTray()->quiet_mode_icon_->visible());
-
-  GetMessageCenter()->SetQuietMode(false);
-  GetMessageCenter()->RemoveAllNotifications(
-      false /* by_user */, message_center::MessageCenter::RemoveType::ALL);
-  base::RunLoop().RunUntilIdle();
-
-  // If there is no notification, bell icon should be shown.
-  EXPECT_TRUE(GetTray()->bell_icon_->visible());
-  EXPECT_FALSE(GetTray()->quiet_mode_icon_->visible());
-
-  GetMessageCenter()->SetQuietMode(true);
-  base::RunLoop().RunUntilIdle();
-
-  // If there is no notification and quiet mode is set, it should show quiet
-  // mode icon.
-  EXPECT_FALSE(GetTray()->bell_icon_->visible());
-  EXPECT_TRUE(GetTray()->quiet_mode_icon_->visible());
-
-  NotificationTray::DisableAnimationsForTest(false);
-}
-
-// Makes sure that the system tray bubble closes when another window is
-// activated, and does not crash regardless of the initial activation state.
-TEST_F(NotificationTrayTest, CloseOnActivation) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  NotificationTray* tray = GetTray();
-
-  // Show the notification bubble.
-  tray->ShowBubble(false /* show_by_click */);
-  EXPECT_FALSE(tray->GetBubbleView()->GetWidget()->IsActive());
-
-  // Test 1: no crash when there's no active window to begin with.
-  EXPECT_FALSE(wm::GetActiveWindow());
-
-  // Showing a new window and activating it will close the system bubble.
-  std::unique_ptr<views::Widget> widget(CreateTestWidget());
-  EXPECT_TRUE(widget->IsActive());
-  EXPECT_FALSE(tray->message_center_bubble());
-
-  // Wait for bubble to actually close.
-  base::RunLoop().RunUntilIdle();
-
-  // Show a second widget.
-  std::unique_ptr<views::Widget> second_widget(CreateTestWidget());
-  EXPECT_TRUE(second_widget->IsActive());
-
-  // Re-show the system bubble.
-  tray->ShowBubble(false /* show_by_click */);
-  EXPECT_FALSE(tray->GetBubbleView()->GetWidget()->IsActive());
-
-  // Test 2: also no crash when there is a previously active window.
-  EXPECT_TRUE(wm::GetActiveWindow());
-
-  // Re-activate the first widget. The system bubble should hide again.
-  widget->Activate();
-  EXPECT_FALSE(tray->message_center_bubble());
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/notifier_settings_view.cc b/ash/system/message_center/notifier_settings_view.cc
index c1c675e..7e7bc01 100644
--- a/ash/system/message_center/notifier_settings_view.cc
+++ b/ash/system/message_center/notifier_settings_view.cc
@@ -15,7 +15,6 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/message_center/message_center_controller.h"
 #include "ash/system/message_center/message_center_style.h"
-#include "ash/system/message_center/message_center_view.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/tray/tray_popup_utils.h"
 #include "base/macros.h"
@@ -397,8 +396,7 @@
 // NotifierSettingsView -------------------------------------------------------
 
 NotifierSettingsView::NotifierSettingsView()
-    : title_arrow_(nullptr),
-      quiet_mode_icon_(nullptr),
+    : quiet_mode_icon_(nullptr),
       quiet_mode_toggle_(nullptr),
       header_view_(nullptr),
       top_label_(nullptr),
@@ -602,12 +600,6 @@
 
 void NotifierSettingsView::ButtonPressed(views::Button* sender,
                                          const ui::Event& event) {
-  if (sender == title_arrow_) {
-    MessageCenterView* center_view = static_cast<MessageCenterView*>(parent());
-    center_view->SetSettingsVisible(!center_view->settings_visible());
-    return;
-  }
-
   if (sender == quiet_mode_toggle_) {
     MessageCenter::Get()->SetQuietMode(quiet_mode_toggle_->is_on());
     return;
diff --git a/ash/system/message_center/notifier_settings_view.h b/ash/system/message_center/notifier_settings_view.h
index 32d2442..7a570ad 100644
--- a/ash/system/message_center/notifier_settings_view.h
+++ b/ash/system/message_center/notifier_settings_view.h
@@ -93,7 +93,6 @@
   // Overridden from views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
-  views::ImageButton* title_arrow_;
   views::ImageView* quiet_mode_icon_;
   views::ToggleButton* quiet_mode_toggle_;
   views::View* header_view_;
diff --git a/ash/system/message_center/slidable_message_view.cc b/ash/system/message_center/slidable_message_view.cc
deleted file mode 100644
index 7c91022c..0000000
--- a/ash/system/message_center/slidable_message_view.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 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 "ash/system/message_center/slidable_message_view.h"
-
-#include "ash/system/message_center/notification_swipe_control_view.h"
-#include "ui/message_center/public/cpp/features.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/views/message_view.h"
-#include "ui/message_center/views/notification_background_painter.h"
-#include "ui/views/background.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/view.h"
-
-namespace ash {
-
-SlidableMessageView::SlidableMessageView(
-    message_center::MessageView* message_view)
-    : message_view_(message_view),
-      control_view_(new NotificationSwipeControlView(message_view)) {
-  SetFocusBehavior(views::View::FocusBehavior::NEVER);
-
-  // Draw on its own layer to allow bound animation.
-  SetPaintToLayer();
-  layer()->SetFillsBoundsOpaquely(false);
-  control_view_->UpdateCornerRadius(0, 0);
-
-  SetLayoutManager(std::make_unique<views::FillLayout>());
-
-  AddChildView(control_view_);
-
-  message_view_->AddSlideObserver(this);
-  AddChildView(message_view);
-}
-
-SlidableMessageView::~SlidableMessageView() = default;
-
-void SlidableMessageView::OnSlideChanged(const std::string& notification_id) {
-  control_view_->UpdateButtonsVisibility();
-}
-
-void SlidableMessageView::CloseSwipeControl() {
-  message_view_->CloseSwipeControl();
-}
-
-void SlidableMessageView::ChildPreferredSizeChanged(views::View* child) {
-  PreferredSizeChanged();
-  InvalidateLayout();
-}
-
-void SlidableMessageView::ChildVisibilityChanged(views::View* child) {
-  PreferredSizeChanged();
-  InvalidateLayout();
-}
-
-void SlidableMessageView::UpdateWithNotification(
-    const message_center::Notification& notification) {
-  message_view_->UpdateWithNotification(notification);
-}
-
-gfx::Size SlidableMessageView::CalculatePreferredSize() const {
-  return message_view_->GetPreferredSize();
-}
-
-int SlidableMessageView::GetHeightForWidth(int width) const {
-  return message_view_->GetHeightForWidth(width);
-}
-
-void SlidableMessageView::UpdateCornerRadius(int top_radius,
-                                             int bottom_radius) {
-  control_view_->UpdateCornerRadius(top_radius, bottom_radius);
-}
-
-// static
-SlidableMessageView* SlidableMessageView::GetFromMessageView(
-    message_center::MessageView* message_view) {
-  DCHECK(message_view);
-  DCHECK(message_view->parent());
-  DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
-            message_view->parent()->GetClassName());
-  return static_cast<SlidableMessageView*>(message_view->parent());
-}
-
-}  // namespace ash
diff --git a/ash/system/message_center/slidable_message_view.h b/ash/system/message_center/slidable_message_view.h
deleted file mode 100644
index 15153ec..0000000
--- a/ash/system/message_center/slidable_message_view.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 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 ASH_SYSTEM_MESSAGE_CENTER_SLIDABLE_MESSAGE_VIEW_H_
-#define ASH_SYSTEM_MESSAGE_CENTER_SLIDABLE_MESSAGE_VIEW_H_
-
-#include "ash/ash_export.h"
-#include "ash/system/message_center/notification_swipe_control_view.h"
-#include "ui/message_center/views/message_view.h"
-#include "ui/views/view.h"
-
-namespace message_center {
-class MessageView;
-}  // namespace message_center
-
-namespace ash {
-
-class ASH_EXPORT SlidableMessageView
-    : public views::View,
-      public message_center::MessageView::SlideObserver {
- public:
-  explicit SlidableMessageView(message_center::MessageView* message_view);
-  ~SlidableMessageView() override;
-
-  message_center::MessageView* GetMessageView() const { return message_view_; }
-  static SlidableMessageView* GetFromMessageView(
-      message_center::MessageView* message_view);
-
-  // MessageView::SlideObserver
-  void OnSlideChanged(const std::string& notification_id) override;
-
-  void SetExpanded(bool expanded) {
-    return message_view_->SetExpanded(expanded);
-  }
-
-  bool IsManuallyExpandedOrCollapsed() const {
-    return message_view_->IsManuallyExpandedOrCollapsed();
-  }
-
-  // Updates this view with the new data contained in the notification.
-  void UpdateWithNotification(const message_center::Notification& notification);
-
-  std::string notification_id() const {
-    return message_view_->notification_id();
-  }
-
-  message_center::MessageView::Mode GetMode() const {
-    return message_view_->GetMode();
-  }
-
-  void CloseSwipeControl();
-
-  // views::View
-  void ChildPreferredSizeChanged(views::View* child) override;
-  void ChildVisibilityChanged(views::View* child) override;
-  gfx::Size CalculatePreferredSize() const override;
-  int GetHeightForWidth(int width) const override;
-
-  void UpdateCornerRadius(int top_radius, int bottom_radius);
-
- private:
-  // Owned by views hierarchy.
-  message_center::MessageView* const message_view_;
-  NotificationSwipeControlView* const control_view_;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_MESSAGE_CENTER_SLIDABLE_MESSAGE_VIEW_H_
diff --git a/ash/system/screen_layout_observer_unittest.cc b/ash/system/screen_layout_observer_unittest.cc
index e7ecbdd..686adf2 100644
--- a/ash/system/screen_layout_observer_unittest.cc
+++ b/ash/system/screen_layout_observer_unittest.cc
@@ -6,8 +6,6 @@
 
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/system/message_center/notification_tray.h"
-#include "ash/system/tray/system_tray.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/command_line.h"
@@ -38,16 +36,6 @@
   ~ScreenLayoutObserverTest() override;
 
  protected:
-  void SetUp() override {
-    AshTestBase::SetUp();
-    NotificationTray::DisableAnimationsForTest(true);
-  }
-
-  void TearDown() override {
-    NotificationTray::DisableAnimationsForTest(false);
-    AshTestBase::TearDown();
-  }
-
   ScreenLayoutObserver* GetScreenLayoutObserver();
   void CheckUpdate();
 
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc
index 68e0b64..3b7891d8 100644
--- a/ash/system/status_area_widget.cc
+++ b/ash/system/status_area_widget.cc
@@ -11,7 +11,6 @@
 #include "ash/system/accessibility/select_to_speak_tray.h"
 #include "ash/system/flag_warning/flag_warning_tray.h"
 #include "ash/system/ime_menu/ime_menu_tray.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/overview/overview_button_tray.h"
 #include "ash/system/palette/palette_tray.h"
 #include "ash/system/session/logout_button_tray.h"
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h
index bcbf78d..72ae4a6a 100644
--- a/ash/system/status_area_widget.h
+++ b/ash/system/status_area_widget.h
@@ -30,7 +30,6 @@
 class UnifiedSystemTray;
 class TrayBackgroundView;
 class VirtualKeyboardTray;
-class NotificationTray;
 
 // Widget showing the system tray, notification tray, and other tray views in
 // the bottom-right of the screen. Exists separately from ShelfView/ShelfWidget
@@ -72,8 +71,6 @@
   UnifiedSystemTray* unified_system_tray() {
     return unified_system_tray_.get();
   }
-  // TODO(tetsui): Remove this getter.  https://crbug.com/898419
-  NotificationTray* notification_tray() { return nullptr; }
   DictationButtonTray* dictation_button_tray() {
     return dictation_button_tray_.get();
   }
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc
index 56f9cd3..f5316cc7 100644
--- a/ash/system/status_area_widget_unittest.cc
+++ b/ash/system/status_area_widget_unittest.cc
@@ -10,7 +10,6 @@
 #include "ash/session/test_session_controller_client.h"
 #include "ash/shell.h"
 #include "ash/system/ime_menu/ime_menu_tray.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/overview/overview_button_tray.h"
 #include "ash/system/palette/palette_tray.h"
 #include "ash/system/session/logout_button_tray.h"
@@ -59,10 +58,6 @@
   EXPECT_TRUE(status->virtual_keyboard_tray_for_testing());
   EXPECT_TRUE(status->palette_tray());
 
-  // Needed because NotificationTray updates its initial visibility
-  // asynchronously.
-  RunAllPendingInMessageLoop();
-
   // Default trays are visible.
   EXPECT_FALSE(status->overview_button_tray()->visible());
   EXPECT_TRUE(status->unified_system_tray()->visible());
@@ -147,10 +142,6 @@
   ASSERT_TRUE(status->ime_menu_tray());
   ASSERT_TRUE(status->virtual_keyboard_tray_for_testing());
 
-  // Needed because NotificationTray updates its initial visibility
-  // asynchronously.
-  base::RunLoop().RunUntilIdle();
-
   // Default trays are visible.
   ASSERT_FALSE(status->overview_button_tray()->visible());
   ASSERT_TRUE(status->unified_system_tray()->visible());
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index f4bf597..c06a67e 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -31,7 +31,6 @@
 #include "ash/system/ime/tray_ime_chromeos.h"
 #include "ash/system/keyboard_brightness/tray_keyboard_brightness.h"
 #include "ash/system/media_security/multi_profile_media_tray_item.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/model/clock_model.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/network/tray_network.h"
@@ -504,8 +503,6 @@
     height =
         std::max(0, work_area.bottom() - bubble_view->GetBoundsInScreen().y());
   }
-  if (notification_tray_)
-    notification_tray_->SetTrayBubbleHeight(height);
 }
 
 base::string16 SystemTray::GetAccessibleTimeString(
diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc
index 21dc4a4b..88febe2 100644
--- a/ash/system/tray/system_tray_unittest.cc
+++ b/ash/system/tray/system_tray_unittest.cc
@@ -19,7 +19,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
-#include "ash/system/message_center/notification_tray.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_test_helper.h"
 #include "ash/system/tray/system_tray_bubble.h"
@@ -1058,32 +1057,6 @@
   EXPECT_EQ(1.0f, tray->layer()->GetTargetOpacity());
 }
 
-TEST_F(SystemTrayTest, SystemTrayHeightWithBubble) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  SystemTray* tray = GetPrimarySystemTray();
-  NotificationTray* notification_tray =
-      StatusAreaWidgetTestHelper::GetStatusAreaWidget()->notification_tray();
-
-  // Ensure the initial tray bubble height is zero.
-  EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test());
-
-  // Show the default view, ensure the tray bubble height is changed.
-  tray->ShowDefaultView(BUBBLE_CREATE_NEW, false /* show_by_click */);
-  RunAllPendingInMessageLoop();
-  EXPECT_LT(0, notification_tray->tray_bubble_height_for_test());
-
-  // Hide the default view, ensure the tray bubble height is back to zero.
-  ASSERT_TRUE(tray->HasSystemBubble());
-  tray->CloseBubble();
-  RunAllPendingInMessageLoop();
-
-  EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test());
-}
-
 TEST_F(SystemTrayTest, SeparatorThickness) {
   EXPECT_EQ(kSeparatorWidth, views::Separator::kThickness);
 }
diff --git a/ash/system/tray/tray_popup_utils.cc b/ash/system/tray/tray_popup_utils.cc
index 7739f9e..018820f2 100644
--- a/ash/system/tray/tray_popup_utils.cc
+++ b/ash/system/tray/tray_popup_utils.cc
@@ -367,7 +367,7 @@
 void TrayPopupUtils::InitializeAsCheckableRow(HoverHighlightView* container,
                                               bool checked) {
   gfx::ImageSkia check_mark =
-      CreateVectorIcon(kCheckCircleIcon, gfx::kGoogleGreen700);
+      CreateVectorIcon(kCheckCircleIcon, gfx::kGoogleGreenDark600);
   container->AddRightIcon(check_mark, check_mark.width());
   UpdateCheckMarkVisibility(container, checked);
 }
diff --git a/ash/system/tray_caps_lock_unittest.cc b/ash/system/tray_caps_lock_unittest.cc
deleted file mode 100644
index ae75403..0000000
--- a/ash/system/tray_caps_lock_unittest.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/system/tray_caps_lock.h"
-
-#include "ash/public/cpp/ash_features.h"
-#include "ash/system/message_center/notification_tray.h"
-#include "ash/system/tray/system_tray.h"
-#include "ash/system/tray/system_tray_test_api.h"
-#include "ash/test/ash_test_base.h"
-
-namespace ash {
-
-class TrayCapsLockTest : public AshTestBase {
- public:
-  TrayCapsLockTest() = default;
-  ~TrayCapsLockTest() override = default;
-
-  void SetUp() override {
-    AshTestBase::SetUp();
-    NotificationTray::DisableAnimationsForTest(true);
-  }
-
-  void TearDown() override {
-    NotificationTray::DisableAnimationsForTest(false);
-    AshTestBase::TearDown();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TrayCapsLockTest);
-};
-
-// Tests that the icon becomes visible when the tray controller toggles it.
-TEST_F(TrayCapsLockTest, Visibility) {
-  // TODO(tetsui): Remove the test after UnifiedSystemTray launch.
-  // https://crbug.com/847104
-  if (features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  SystemTray* tray = GetPrimarySystemTray();
-  TrayCapsLock* caps_lock = SystemTrayTestApi(tray).tray_caps_lock();
-
-  // By default the icon isn't visible.
-  EXPECT_FALSE(caps_lock->tray_view()->visible());
-
-  // Simulate turning on caps lock.
-  caps_lock->OnCapsLockChanged(true);
-  EXPECT_TRUE(caps_lock->tray_view()->visible());
-
-  // Simulate turning off caps lock.
-  caps_lock->OnCapsLockChanged(false);
-  EXPECT_FALSE(caps_lock->tray_view()->visible());
-}
-
-}  // namespace ash
diff --git a/ash/system/unified/notification_counter_view.cc b/ash/system/unified/notification_counter_view.cc
index ee23bf7..4a5a3e949 100644
--- a/ash/system/unified/notification_counter_view.cc
+++ b/ash/system/unified/notification_counter_view.cc
@@ -92,8 +92,6 @@
 NotificationCounterView::NotificationCounterView(Shelf* shelf)
     : TrayItemView(shelf) {
   CreateImageView();
-  image_view()->set_tooltip_text(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NOTIFICATIONS_LABEL));
   SetVisible(false);
   Shell::Get()->session_controller()->AddObserver(this);
 }
@@ -116,6 +114,8 @@
         gfx::CanvasImageSource::MakeImageSkia<NumberIconImageSource>(icon_id));
     count_for_display_ = icon_id;
   }
+  image_view()->set_tooltip_text(l10n_util::GetPluralStringFUTF16(
+      IDS_ASH_STATUS_TRAY_NOTIFICATIONS_COUNT_TOOLTIP, notification_count));
   SetVisible(true);
 }
 
@@ -126,6 +126,8 @@
 
 QuietModeView::QuietModeView(Shelf* shelf) : TrayItemView(shelf) {
   CreateImageView();
+  image_view()->set_tooltip_text(
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_QUIET_MODE_TOOLTIP));
   SetVisible(false);
   Shell::Get()->session_controller()->AddObserver(this);
 }
diff --git a/ash/system/unified/unified_slider_view.cc b/ash/system/unified/unified_slider_view.cc
index 28524e0..d1bd9a6 100644
--- a/ash/system/unified/unified_slider_view.cc
+++ b/ash/system/unified/unified_slider_view.cc
@@ -79,6 +79,8 @@
 }
 
 void UnifiedSliderButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+  if (!enabled())
+    return;
   TopShortcutButton::GetAccessibleNodeData(node_data);
   node_data->role = ax::mojom::Role::kToggleButton;
   node_data->SetCheckedState(toggled_ ? ax::mojom::CheckedState::kTrue
diff --git a/ash/wm/pip/pip_positioner.cc b/ash/wm/pip/pip_positioner.cc
index 9361b3d..3ba2b68 100644
--- a/ash/wm/pip/pip_positioner.cc
+++ b/ash/wm/pip/pip_positioner.cc
@@ -14,6 +14,7 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ui/aura/window.h"
+#include "ui/gfx/geometry/insets.h"
 #include "ui/keyboard/keyboard_controller.h"
 
 namespace ash {
@@ -59,19 +60,16 @@
 //   /    \
 //  /BOTTOM
 int GetGravityToClosestEdge(const gfx::Rect& bounds, const gfx::Rect& region) {
-  const int left_edge_dist = bounds.x() - region.x();
-  const int right_edge_dist = region.right() - bounds.right();
-  const int top_edge_dist = bounds.y() - region.y();
-  const int bottom_edge_dist = region.bottom() - bounds.bottom();
-  int minimum_edge_dist = std::min(left_edge_dist, right_edge_dist);
-  minimum_edge_dist = std::min(minimum_edge_dist, top_edge_dist);
-  minimum_edge_dist = std::min(minimum_edge_dist, bottom_edge_dist);
+  const gfx::Insets insets = region.InsetsFrom(bounds);
+  int minimum_edge_dist = std::min(insets.left(), insets.right());
+  minimum_edge_dist = std::min(minimum_edge_dist, insets.top());
+  minimum_edge_dist = std::min(minimum_edge_dist, insets.bottom());
 
-  if (left_edge_dist == minimum_edge_dist) {
+  if (insets.left() == minimum_edge_dist) {
     return GRAVITY_LEFT;
-  } else if (right_edge_dist == minimum_edge_dist) {
+  } else if (insets.right() == minimum_edge_dist) {
     return GRAVITY_RIGHT;
-  } else if (top_edge_dist == minimum_edge_dist) {
+  } else if (insets.top() == minimum_edge_dist) {
     return GRAVITY_TOP;
   } else {
     return GRAVITY_BOTTOM;
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h
index c220eecc..6a4cd64 100644
--- a/base/mac/sdk_forward_declarations.h
+++ b/base/mac/sdk_forward_declarations.h
@@ -368,4 +368,10 @@
 // ----------------------------------------------------------------------------
 BASE_EXPORT extern "C" NSString* const kCWSSIDDidChangeNotification;
 
+// Once Chrome is built with at least the macOS 10.13 SDK, everything within
+// this preprocessor block can be removed.
+#if !defined(MAC_OS_X_VERSION_10_13)
+typedef NSString* NSTextCheckingOptionKey;
+#endif
+
 #endif  // BASE_MAC_SDK_FORWARD_DECLARATIONS_H_
diff --git a/base/memory/platform_shared_memory_region_mac.cc b/base/memory/platform_shared_memory_region_mac.cc
index 406f930f..45bbaa5 100644
--- a/base/memory/platform_shared_memory_region_mac.cc
+++ b/base/memory/platform_shared_memory_region_mac.cc
@@ -57,7 +57,6 @@
     const SharedMemoryHandle& handle,
     Mode mode) {
   CHECK(mode == Mode::kReadOnly || mode == Mode::kUnsafe);
-  CHECK(handle.GetType() == SharedMemoryHandle::MACH);
   if (!handle.IsValid())
     return {};
 
diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h
index c573ef7..10495bd 100644
--- a/base/memory/shared_memory.h
+++ b/base/memory/shared_memory.h
@@ -36,10 +36,7 @@
 
 // Options for creating a shared memory object.
 struct BASE_EXPORT SharedMemoryCreateOptions {
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The type of OS primitive that should back the SharedMemory object.
-  SharedMemoryHandle::Type type = SharedMemoryHandle::MACH;
-#elif !defined(OS_FUCHSIA)
+#if !defined(OS_FUCHSIA)
   // DEPRECATED (crbug.com/345734):
   // If NULL, the object is anonymous.  This pointer is owned by the caller
   // and must live through the call to Create().
@@ -51,7 +48,7 @@
   // shared memory must not exist.  This flag is meaningless unless
   // name_deprecated is non-NULL.
   bool open_existing_deprecated = false;
-#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
+#endif
 
   // Size of the shared memory object to be created.
   // When opening an existing object, this has no effect.
@@ -106,7 +103,7 @@
   // primitive.
   static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle);
 
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
   // This method requires that the SharedMemoryHandle is backed by a POSIX fd.
   static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle);
 #endif
@@ -231,12 +228,6 @@
   SharedMemoryHandle readonly_shm_;
 #endif
 
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The mechanism by which the memory is mapped. Only valid if |memory_| is not
-  // |nullptr|.
-  SharedMemoryHandle::Type mapped_memory_mechanism_ = SharedMemoryHandle::MACH;
-#endif
-
   // The OS primitive that backs the shared memory region.
   SharedMemoryHandle shm_;
 
diff --git a/base/memory/shared_memory_handle.h b/base/memory/shared_memory_handle.h
index 1967cbb..9d854a7 100644
--- a/base/memory/shared_memory_handle.h
+++ b/base/memory/shared_memory_handle.h
@@ -16,7 +16,6 @@
 #elif defined(OS_MACOSX) && !defined(OS_IOS)
 #include <mach/mach.h>
 #include "base/base_export.h"
-#include "base/file_descriptor_posix.h"
 #include "base/macros.h"
 #include "base/process/process_handle.h"
 #elif defined(OS_POSIX)
@@ -101,13 +100,6 @@
                      const base::UnguessableToken& guid);
   zx_handle_t GetHandle() const;
 #elif defined(OS_MACOSX) && !defined(OS_IOS)
-  enum Type {
-    // The SharedMemoryHandle is backed by a POSIX fd.
-    POSIX,
-    // The SharedMemoryHandle is backed by the Mach primitive "memory object".
-    MACH,
-  };
-
   // Makes a Mach-based SharedMemoryHandle of the given size. On error,
   // subsequent calls to IsValid() return false.
   // Passing the wrong |size| has no immediate consequence, but may cause errors
@@ -122,8 +114,6 @@
                      mach_vm_size_t size,
                      const base::UnguessableToken& guid);
 
-  Type GetType() const { return type_; }
-
   // Exposed so that the SharedMemoryHandle can be transported between
   // processes.
   mach_port_t GetMemoryObject() const;
@@ -165,7 +155,7 @@
   bool SetRegionReadOnly() const;
 #endif
 
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
   // Constructs a SharedMemoryHandle backed by a FileDescriptor. The newly
   // created instance has the same ownership semantics as base::FileDescriptor.
   // This typically means that the SharedMemoryHandle takes ownership of the
@@ -203,23 +193,13 @@
   friend bool CheckReadOnlySharedMemoryHandleForTesting(
       SharedMemoryHandle handle);
 
-  Type type_ = MACH;
+  mach_port_t memory_object_ = MACH_PORT_NULL;
 
-  // Each instance of a SharedMemoryHandle is backed either by a POSIX fd or a
-  // mach port. |type_| determines the backing member.
-  union {
-    FileDescriptor file_descriptor_;
-
-    struct {
-      mach_port_t memory_object_ = MACH_PORT_NULL;
-
-      // Whether passing this object as a parameter to an IPC message passes
-      // ownership of |memory_object_| to the IPC stack. This is meant to mimic
-      // the behavior of the |auto_close| parameter of FileDescriptor.
-      // Defaults to |false|.
-      bool ownership_passes_to_ipc_ = false;
-    };
-  };
+  // Whether passing this object as a parameter to an IPC message passes
+  // ownership of |memory_object_| to the IPC stack. This is meant to mimic
+  // the behavior of the |auto_close| parameter of FileDescriptor.
+  // Defaults to |false|.
+  bool ownership_passes_to_ipc_ = false;
 #elif defined(OS_ANDROID)
   friend class SharedMemory;
 
diff --git a/base/memory/shared_memory_handle_mac.cc b/base/memory/shared_memory_handle_mac.cc
index 0e863fa67..28f69c47 100644
--- a/base/memory/shared_memory_handle_mac.cc
+++ b/base/memory/shared_memory_handle_mac.cc
@@ -6,30 +6,17 @@
 
 #include <mach/mach_vm.h>
 #include <stddef.h>
-#include <sys/mman.h>
-#include <unistd.h>
 
 #include "base/mac/mac_util.h"
 #include "base/mac/mach_logging.h"
-#include "base/posix/eintr_wrapper.h"
 #include "base/unguessable_token.h"
 
 namespace base {
 
 SharedMemoryHandle::SharedMemoryHandle() {}
 
-SharedMemoryHandle::SharedMemoryHandle(
-    const base::FileDescriptor& file_descriptor,
-    size_t size,
-    const base::UnguessableToken& guid)
-    : type_(POSIX),
-      file_descriptor_(file_descriptor),
-      guid_(guid),
-      size_(size) {}
-
 SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size,
                                        const base::UnguessableToken& guid) {
-  type_ = MACH;
   mach_port_t named_right;
   kern_return_t kr = mach_make_memory_entry_64(
       mach_task_self(),
@@ -52,48 +39,29 @@
 SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object,
                                        mach_vm_size_t size,
                                        const base::UnguessableToken& guid)
-    : type_(MACH),
-      memory_object_(memory_object),
+    : memory_object_(memory_object),
       ownership_passes_to_ipc_(false),
       guid_(guid),
       size_(size) {}
 
 SharedMemoryHandle SharedMemoryHandle::Duplicate() const {
-  switch (type_) {
-    case POSIX: {
-      if (!IsValid())
-        return SharedMemoryHandle();
-      int duped_fd = HANDLE_EINTR(dup(file_descriptor_.fd));
-      if (duped_fd < 0)
-        return SharedMemoryHandle();
-      return SharedMemoryHandle(FileDescriptor(duped_fd, true), size_, guid_);
-    }
-    case MACH: {
-      if (!IsValid())
-        return SharedMemoryHandle();
+  if (!IsValid())
+    return SharedMemoryHandle();
 
-      // Increment the ref count.
-      kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_,
-                                            MACH_PORT_RIGHT_SEND, 1);
-      DCHECK_EQ(kr, KERN_SUCCESS);
-      SharedMemoryHandle handle(*this);
-      handle.SetOwnershipPassesToIPC(true);
-      return handle;
-    }
-  }
+  // Increment the ref count.
+  kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_,
+                                        MACH_PORT_RIGHT_SEND, 1);
+  DCHECK_EQ(kr, KERN_SUCCESS);
+  SharedMemoryHandle handle(*this);
+  handle.SetOwnershipPassesToIPC(true);
+  return handle;
 }
 
 bool SharedMemoryHandle::IsValid() const {
-  switch (type_) {
-    case POSIX:
-      return file_descriptor_.fd >= 0;
-    case MACH:
-      return memory_object_ != MACH_PORT_NULL;
-  }
+  return memory_object_ != MACH_PORT_NULL;
 }
 
 mach_port_t SharedMemoryHandle::GetMemoryObject() const {
-  DCHECK_EQ(type_, MACH);
   return memory_object_;
 }
 
@@ -102,52 +70,32 @@
                                void** memory,
                                bool read_only) {
   DCHECK(IsValid());
-  switch (type_) {
-    case SharedMemoryHandle::POSIX:
-      *memory = mmap(nullptr, bytes, PROT_READ | (read_only ? 0 : PROT_WRITE),
-                     MAP_SHARED, file_descriptor_.fd, offset);
-      return *memory != MAP_FAILED;
-    case SharedMemoryHandle::MACH:
-      kern_return_t kr = mach_vm_map(
-          mach_task_self(),
-          reinterpret_cast<mach_vm_address_t*>(memory),    // Output parameter
-          bytes,
-          0,                                               // Alignment mask
-          VM_FLAGS_ANYWHERE,
-          memory_object_,
-          offset,
-          FALSE,                                           // Copy
-          VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE),  // Current protection
-          VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK,  // Maximum protection
-          VM_INHERIT_NONE);
-      return kr == KERN_SUCCESS;
-  }
+  kern_return_t kr = mach_vm_map(
+      mach_task_self(),
+      reinterpret_cast<mach_vm_address_t*>(memory),  // Output parameter
+      bytes,
+      0,  // Alignment mask
+      VM_FLAGS_ANYWHERE, memory_object_, offset,
+      FALSE,                                           // Copy
+      VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE),  // Current protection
+      VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK,  // Maximum protection
+      VM_INHERIT_NONE);
+  return kr == KERN_SUCCESS;
 }
 
 void SharedMemoryHandle::Close() const {
   if (!IsValid())
     return;
 
-  switch (type_) {
-    case POSIX:
-      if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0)
-        DPLOG(ERROR) << "Error closing fd";
-      break;
-    case MACH:
-      kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_);
-      if (kr != KERN_SUCCESS)
-        MACH_DLOG(ERROR, kr) << "Error deallocating mach port";
-      break;
-  }
+  kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_);
+  MACH_DLOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "Error deallocating mach port";
 }
 
 void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) {
-  DCHECK_EQ(type_, MACH);
   ownership_passes_to_ipc_ = ownership_passes;
 }
 
 bool SharedMemoryHandle::OwnershipPassesToIPC() const {
-  DCHECK_EQ(type_, MACH);
   return ownership_passes_to_ipc_;
 }
 
diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc
index 0a233e5..fc1af80 100644
--- a/base/memory/shared_memory_mac.cc
+++ b/base/memory/shared_memory_mac.cc
@@ -11,8 +11,6 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
@@ -21,12 +19,10 @@
 #include "base/memory/shared_memory_tracker.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/posix/eintr_wrapper.h"
 #include "base/posix/safe_strerror.h"
 #include "base/process/process_metrics.h"
 #include "base/scoped_generic.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
 #include "base/unguessable_token.h"
 #include "build/build_config.h"
 
@@ -85,9 +81,7 @@
 SharedMemory::SharedMemory() {}
 
 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
-    : mapped_memory_mechanism_(SharedMemoryHandle::POSIX),
-      shm_(handle),
-      read_only_(read_only) {}
+    : shm_(handle), read_only_(read_only) {}
 
 SharedMemory::~SharedMemory() {
   Unmap();
@@ -115,12 +109,6 @@
   return handle.Duplicate();
 }
 
-// static
-int SharedMemory::GetFdFromSharedMemoryHandle(
-    const SharedMemoryHandle& handle) {
-  return handle.file_descriptor_.fd;
-}
-
 bool SharedMemory::CreateAndMapAnonymous(size_t size) {
   return CreateAnonymous(size) && Map(size);
 }
@@ -135,48 +123,9 @@
   if (options.size > static_cast<size_t>(std::numeric_limits<int>::max()))
     return false;
 
-  if (options.type == SharedMemoryHandle::MACH) {
-    shm_ = SharedMemoryHandle(options.size, UnguessableToken::Create());
-    requested_size_ = options.size;
-    return shm_.IsValid();
-  }
-
-  // This function theoretically can block on the disk. Both profiling of real
-  // users and local instrumentation shows that this is a real problem.
-  // https://code.google.com/p/chromium/issues/detail?id=466437
-  ThreadRestrictions::ScopedAllowIO allow_io;
-
-  ScopedFD fd;
-  ScopedFD readonly_fd;
-
-  FilePath path;
-  bool result = CreateAnonymousSharedMemory(options, &fd, &readonly_fd, &path);
-  if (!result)
-    return false;
-  // Should be guaranteed by CreateAnonymousSharedMemory().
-  DCHECK(fd.is_valid());
-
-  // Get current size.
-  struct stat stat;
-  if (fstat(fd.get(), &stat) != 0)
-    return false;
-  const size_t current_size = stat.st_size;
-  if (current_size != options.size) {
-    if (HANDLE_EINTR(ftruncate(fd.get(), options.size)) != 0)
-      return false;
-  }
+  shm_ = SharedMemoryHandle(options.size, UnguessableToken::Create());
   requested_size_ = options.size;
-
-  int mapped_file = -1;
-  int readonly_mapped_file = -1;
-  result = PrepareMapFile(std::move(fd), std::move(readonly_fd), &mapped_file,
-                          &readonly_mapped_file);
-  shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), options.size,
-                            UnguessableToken::Create());
-  readonly_shm_ =
-      SharedMemoryHandle(FileDescriptor(readonly_mapped_file, false),
-                         options.size, shm_.GetGUID());
-  return result;
+  return shm_.IsValid();
 }
 
 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
@@ -192,7 +141,6 @@
     mapped_size_ = bytes;
     DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
                       (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
-    mapped_memory_mechanism_ = shm_.type_;
     mapped_id_ = shm_.GetGUID();
     SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this);
   } else {
@@ -207,16 +155,9 @@
     return false;
 
   SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this);
-  switch (mapped_memory_mechanism_) {
-    case SharedMemoryHandle::POSIX:
-      munmap(memory_, mapped_size_);
-      break;
-    case SharedMemoryHandle::MACH:
       mach_vm_deallocate(mach_task_self(),
                          reinterpret_cast<mach_vm_address_t>(memory_),
                          mapped_size_);
-      break;
-  }
   memory_ = nullptr;
   mapped_size_ = 0;
   mapped_id_ = UnguessableToken();
@@ -237,22 +178,9 @@
 void SharedMemory::Close() {
   shm_.Close();
   shm_ = SharedMemoryHandle();
-  if (shm_.type_ == SharedMemoryHandle::POSIX) {
-    if (readonly_shm_.IsValid()) {
-      readonly_shm_.Close();
-      readonly_shm_ = SharedMemoryHandle();
-    }
-  }
 }
 
 SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const {
-  if (shm_.type_ == SharedMemoryHandle::POSIX) {
-    // We could imagine re-opening the file from /dev/fd, but that can't make it
-    // readonly on Mac: https://codereview.chromium.org/27265002/#msg10.
-    CHECK(readonly_shm_.IsValid());
-    return readonly_shm_.Duplicate();
-  }
-
   DCHECK(shm_.IsValid());
   SharedMemoryHandle new_handle;
   bool success = MakeMachSharedMemoryHandleReadOnly(&new_handle, shm_, memory_);
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
index 6608c31..16621e9 100644
--- a/base/memory/shared_memory_unittest.cc
+++ b/base/memory/shared_memory_unittest.cc
@@ -359,6 +359,8 @@
   }
 }
 
+#if !(defined(OS_MACOSX) && !defined(OS_IOS))
+// The Mach functionality is tested in shared_memory_mac_unittest.cc.
 TEST_P(SharedMemoryTest, GetReadOnlyHandle) {
   StringPiece contents = "Hello World";
 
@@ -366,10 +368,6 @@
   SharedMemoryCreateOptions options;
   options.size = contents.size();
   options.share_read_only = true;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
-  options.type = SharedMemoryHandle::POSIX;
-#endif
   ASSERT_TRUE(writable_shmem.Create(options));
   ASSERT_TRUE(writable_shmem.Map(options.size));
   memcpy(writable_shmem.memory(), contents.data(), contents.size());
@@ -467,6 +465,7 @@
 #error Unexpected platform; write a test that tries to make 'handle' writable.
 #endif  // defined(OS_POSIX) || defined(OS_WIN)
 }
+#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
 
 TEST_P(SharedMemoryTest, ShareToSelf) {
   StringPiece contents = "Hello World";
@@ -584,7 +583,8 @@
 
 #if defined(OS_POSIX)
 // This test is not applicable for iOS (crbug.com/399384).
-#if !defined(OS_IOS)
+// The Mach functionality is tested in shared_memory_mac_unittest.cc.
+#if !defined(OS_MACOSX) && !defined(OS_IOS)
 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
 TEST_P(SharedMemoryTest, AnonymousExecutable) {
 #if defined(OS_LINUX)
@@ -602,10 +602,6 @@
   SharedMemoryCreateOptions options;
   options.size = kTestSize;
   options.executable = true;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
-  options.type = SharedMemoryHandle::POSIX;
-#endif
 
   EXPECT_TRUE(shared_memory.Create(options));
   EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
@@ -613,7 +609,7 @@
   EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
                         PROT_READ | PROT_EXEC));
 }
-#endif  // !defined(OS_IOS)
+#endif  // !defined(OS_MACOSX) && !defined(OS_IOS)
 
 #if defined(OS_ANDROID)
 // This test is restricted to Android since there is no way on other platforms
@@ -658,16 +654,14 @@
 };
 
 // Create a shared memory object, check its permissions.
+#if !(defined(OS_MACOSX) && !defined(OS_IOS))
+// The Mach functionality is tested in shared_memory_mac_unittest.cc.
 TEST_P(SharedMemoryTest, FilePermissionsAnonymous) {
   const uint32_t kTestSize = 1 << 8;
 
   SharedMemory shared_memory;
   SharedMemoryCreateOptions options;
   options.size = kTestSize;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
-  options.type = SharedMemoryHandle::POSIX;
-#endif
   // Set a file mode creation mask that gives all permissions.
   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
 
@@ -682,18 +676,17 @@
   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
 }
+#endif  // !(defined(OS_MACOSX) && !defined(OS_IOS)
 
 // Create a shared memory object, check its permissions.
+#if !(defined(OS_MACOSX) && !defined(OS_IOS))
+// The Mach functionality is tested in shared_memory_mac_unittest.cc.
 TEST_P(SharedMemoryTest, FilePermissionsNamed) {
   const uint32_t kTestSize = 1 << 8;
 
   SharedMemory shared_memory;
   SharedMemoryCreateOptions options;
   options.size = kTestSize;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
-  options.type = SharedMemoryHandle::POSIX;
-#endif
 
   // Set a file mode creation mask that gives all permissions.
   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
@@ -708,6 +701,7 @@
   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
 }
+#endif  // !(defined(OS_MACOSX) && !defined(OS_IOS)
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
 #endif  // defined(OS_POSIX)
@@ -854,15 +848,13 @@
 #endif  // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) &&
         // !defined(OS_FUCHSIA)
 
+#if !(defined(OS_MACOSX) && !defined(OS_IOS))
+// The Mach functionality is tested in shared_memory_mac_unittest.cc.
 TEST_P(SharedMemoryTest, MappedId) {
   const uint32_t kDataSize = 1024;
   SharedMemory memory;
   SharedMemoryCreateOptions options;
   options.size = kDataSize;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // The Mach functionality is tested in shared_memory_mac_unittest.cc.
-  options.type = SharedMemoryHandle::POSIX;
-#endif
 
   EXPECT_TRUE(memory.Create(options));
   base::UnguessableToken id = memory.handle().GetGUID();
@@ -878,6 +870,7 @@
   memory.Unmap();
   EXPECT_TRUE(memory.mapped_id().is_empty());
 }
+#endif  // !(defined(OS_MACOSX) && !defined(OS_IOS)
 
 INSTANTIATE_TEST_CASE_P(Default,
                         SharedMemoryTest,
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc
index 6037aab5..edfd92a 100644
--- a/base/process/process_metrics_win.cc
+++ b/base/process/process_metrics_win.cc
@@ -18,6 +18,7 @@
 #include "base/process/memory.h"
 #include "base/process/process_metrics_iocounters.h"
 #include "base/sys_info.h"
+#include "base/threading/scoped_blocking_call.h"
 
 namespace base {
 namespace {
@@ -345,12 +346,15 @@
     return false;
 
   SYSTEM_PERFORMANCE_INFORMATION counters = {};
-  const NTSTATUS status = query_system_information_ptr(
-      ::SystemPerformanceInformation, &counters,
-      sizeof(SYSTEM_PERFORMANCE_INFORMATION), nullptr);
-
-  if (status != STATUS_SUCCESS)
-    return false;
+  {
+    // The call to NtQuerySystemInformation might block on a lock.
+    base::ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
+    if (query_system_information_ptr(::SystemPerformanceInformation, &counters,
+                                     sizeof(SYSTEM_PERFORMANCE_INFORMATION),
+                                     nullptr) != STATUS_SUCCESS) {
+      return false;
+    }
+  }
 
   info->idle_time = counters.IdleTime.QuadPart;
   info->read_transfer_count = counters.ReadTransferCount.QuadPart;
diff --git a/base/profiler/native_stack_sampler_posix.cc b/base/profiler/native_stack_sampler_posix.cc
index fdc18e0..62983d8 100644
--- a/base/profiler/native_stack_sampler_posix.cc
+++ b/base/profiler/native_stack_sampler_posix.cc
@@ -4,6 +4,11 @@
 
 #include "base/profiler/native_stack_sampler.h"
 
+#include <pthread.h>
+
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+
 namespace base {
 
 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
@@ -13,7 +18,24 @@
 }
 
 size_t NativeStackSampler::GetStackBufferSize() {
-  return 0;
+  size_t stack_size = PlatformThread::GetDefaultThreadStackSize();
+
+  pthread_attr_t attr;
+  if (stack_size == 0 && pthread_attr_init(&attr) == 0) {
+    if (pthread_attr_getstacksize(&attr, &stack_size) != 0)
+      stack_size = 0;
+    pthread_attr_destroy(&attr);
+  }
+
+// If we can't get stack limit from pthreads then use default value.
+#if defined(OS_ANDROID)
+  // 1MB is default thread limit set by Android at art/runtime/thread_pool.h.
+  constexpr size_t kDefaultStackLimit = 1 << 20;
+#else
+  // Maximum limits under NPTL implementation.
+  constexpr size_t kDefaultStackLimit = 4 * (1 << 20);
+#endif
+  return stack_size > 0 ? stack_size : kDefaultStackLimit;
 }
 
 }  // namespace base
diff --git a/base/test/test_shared_memory_util.cc b/base/test/test_shared_memory_util.cc
index b1364b6..5093e67c 100644
--- a/base/test/test_shared_memory_util.cc
+++ b/base/test/test_shared_memory_util.cc
@@ -41,7 +41,7 @@
 // Common routine used with Posix file descriptors. Check that shared memory
 // file descriptor |fd| does not allow writable mappings. Return true on
 // success, false otherwise.
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
 static bool CheckReadOnlySharedMemoryFdPosix(int fd) {
 // Note that the error on Android is EPERM, unlike other platforms where
 // it will be EACCES.
@@ -66,7 +66,7 @@
   }
   return true;
 }
-#endif  // OS_POSIX
+#endif  // OS_POSIX && !(defined(OS_MACOSX) && !defined(OS_IOS))
 
 #if defined(OS_FUCHSIA)
 // Fuchsia specific implementation.
@@ -118,11 +118,7 @@
 
 bool CheckReadOnlySharedMemoryHandleForTesting(SharedMemoryHandle handle) {
 #if defined(OS_MACOSX) && !defined(OS_IOS)
-  // For OSX, the code has to deal with both POSIX and MACH handles.
-  if (handle.type_ == SharedMemoryHandle::POSIX)
-    return CheckReadOnlySharedMemoryFdPosix(handle.file_descriptor_.fd);
-  else
-    return CheckReadOnlySharedMemoryMachPort(handle.memory_object_);
+  return CheckReadOnlySharedMemoryMachPort(handle.memory_object_);
 #elif defined(OS_FUCHSIA)
   return CheckReadOnlySharedMemoryFuchsiaHandle(
       zx::unowned_vmo(handle.GetHandle()));
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 3458115..85bd8207 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -41,6 +41,10 @@
 
 }  // namespace
 
+bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) {
+  return false;
+}
+
 TraceEvent::TraceEvent()
     : duration_(TimeDelta::FromInternalValue(-1)),
       scope_(trace_event_internal::kGlobalScope),
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 4b4b88f5..c35a65b 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -49,6 +49,21 @@
   // appended.
   virtual void AppendAsTraceFormat(std::string* out) const = 0;
 
+  // Append the class info directly into the Perfetto-defined proto
+  // format; this is attempted first and if this returns true,
+  // AppendAsTraceFormat is not called. The ProtoAppender interface
+  // acts as a bridge to avoid proto/Perfetto dependencies in base.
+  class BASE_EXPORT ProtoAppender {
+   public:
+    virtual ~ProtoAppender() = default;
+
+    virtual void AddBuffer(uint8_t* begin, uint8_t* end) = 0;
+    // Copy all of the previous buffers registered with AddBuffer
+    // into the proto, with the given |field_id|.
+    virtual size_t Finalize(uint32_t field_id) = 0;
+  };
+  virtual bool AppendToProto(ProtoAppender* appender);
+
   virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
 
   std::string ToString() const {
@@ -146,7 +161,7 @@
   const char* arg_name(size_t index) const { return arg_names_[index]; }
   const TraceValue& arg_value(size_t index) const { return arg_values_[index]; }
 
-  const ConvertableToTraceFormat* arg_convertible_value(size_t index) const {
+  ConvertableToTraceFormat* arg_convertible_value(size_t index) {
     return convertable_values_[index].get();
   }
 
diff --git a/base/trace_event/trace_event_system_stats_monitor.cc b/base/trace_event/trace_event_system_stats_monitor.cc
index 7e082f3..599be19 100644
--- a/base/trace_event/trace_event_system_stats_monitor.cc
+++ b/base/trace_event/trace_event_system_stats_monitor.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/bind.h"
 #include "base/debug/leak_annotations.h"
 #include "base/json/json_writer.h"
 #include "base/lazy_instance.h"
@@ -14,6 +15,7 @@
 #include "base/process/process_metrics.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/task/post_task.h"
 #include "base/threading/thread_local_storage.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
@@ -49,6 +51,17 @@
   system_stats_ = SystemMetrics::Sample();
 }
 
+void DumpSystemStatsImpl(TraceEventSystemStatsMonitor* stats_monitor) {
+  std::unique_ptr<SystemStatsHolder> dump_holder =
+      std::make_unique<SystemStatsHolder>();
+  dump_holder->GetSystemProfilingStats();
+
+  TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
+      TRACE_DISABLED_BY_DEFAULT("system_stats"),
+      "base::TraceEventSystemStatsMonitor::SystemStats", stats_monitor,
+      std::move(dump_holder));
+}
+
 }  // namespace
 
 //////////////////////////////////////////////////////////////////////////////
@@ -102,15 +115,17 @@
                                weak_factory_.GetWeakPtr()));
 }
 
-// If system tracing is enabled, dumps a profile to the tracing system.
 void TraceEventSystemStatsMonitor::DumpSystemStats() {
-  std::unique_ptr<SystemStatsHolder> dump_holder(new SystemStatsHolder());
-  dump_holder->GetSystemProfilingStats();
-
-  TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
-      TRACE_DISABLED_BY_DEFAULT("system_stats"),
-      "base::TraceEventSystemStatsMonitor::SystemStats", this,
-      std::move(dump_holder));
+  // Calls to |DumpSystemStatsImpl| might be blocking.
+  //
+  // TODO(sebmarchand): Ideally the timer that calls this function should use a
+  // thread with the MayBlock trait to avoid having to use a trampoline here.
+  // This isn't currently possible due to https://crbug.com/896990.
+  base::PostTaskWithTraits(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+      base::BindOnce(&DumpSystemStatsImpl, base::Unretained(this)));
 }
 
 void TraceEventSystemStatsMonitor::StopProfiling() {
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 82474dd7..505de0ce 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -1302,7 +1302,7 @@
                                bind_id, num_args, arg_names, arg_types,
                                arg_values, convertable_values, flags);
 
-    trace_event_override(new_trace_event);
+    trace_event_override(&new_trace_event);
     return handle;
   }
 
@@ -1508,7 +1508,7 @@
           trace_event_internal::kNoId /* id */,
           trace_event_internal::kNoId /* bind_id */, 0, nullptr, nullptr,
           nullptr, nullptr, TRACE_EVENT_FLAG_NONE);
-      trace_event_override(new_trace_event);
+      trace_event_override(&new_trace_event);
 
 #if defined(OS_ANDROID)
       new_trace_event.SendToATrace();
@@ -1560,7 +1560,7 @@
     TraceEvent trace_event;
     InitializeMetadataEvent(&trace_event, thread_id, metadata_name, arg_name,
                             value);
-    trace_event_override(trace_event);
+    trace_event_override(&trace_event);
   } else {
     InitializeMetadataEvent(
         AddEventToThreadSharedChunkWhileLocked(nullptr, false), thread_id,
@@ -1577,7 +1577,7 @@
   // Move metadata added by |AddMetadataEvent| into the trace log.
   if (trace_event_override) {
     while (!metadata_events_.empty()) {
-      trace_event_override(*metadata_events_.back());
+      trace_event_override(metadata_events_.back().get());
       metadata_events_.pop_back();
     }
   } else {
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h
index e1d233a..94c57d4 100644
--- a/base/trace_event/trace_log.h
+++ b/base/trace_event/trace_log.h
@@ -185,7 +185,7 @@
   // Cancels tracing and discards collected data.
   void CancelTracing(const OutputCallback& cb);
 
-  typedef void (*AddTraceEventOverrideCallback)(const TraceEvent&);
+  typedef void (*AddTraceEventOverrideCallback)(TraceEvent*);
   typedef void (*OnFlushCallback)();
   // The callback will be called up until the point where the flush is
   // finished, i.e. must be callable until OutputCallback is called with
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc
index 3f4c743..4addbda 100644
--- a/base/trace_event/traced_value.cc
+++ b/base/trace_event/traced_value.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include <atomic>
 #include <utility>
 
 #include "base/bits.h"
@@ -15,6 +16,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_impl.h"
 #include "base/trace_event/trace_event_memory_overhead.h"
+#include "base/trace_event/trace_log.h"
 #include "base/values.h"
 
 namespace base {
@@ -31,6 +33,8 @@
 const char kTypeString = 's';
 const char kTypeCStr = '*';  // only used for key names
 
+std::atomic<TracedValue::WriterFactoryCallback> g_writer_factory_callback;
+
 #ifndef NDEBUG
 const bool kStackTypeDict = false;
 const bool kStackTypeArray = true;
@@ -77,14 +81,385 @@
   DCHECK(res);
   return key_name;
 }
+
+class PickleWriter final : public TracedValue::Writer {
+ public:
+  explicit PickleWriter(size_t capacity) {
+    if (capacity) {
+      pickle_.Reserve(capacity);
+    }
+  }
+
+  bool IsPickleWriter() const override { return true; }
+  bool IsProtoWriter() const override { return false; }
+
+  void SetInteger(const char* name, int value) override {
+    pickle_.WriteBytes(&kTypeInt, 1);
+    pickle_.WriteInt(value);
+    WriteKeyNameAsRawPtr(pickle_, name);
+  }
+
+  void SetIntegerWithCopiedName(base::StringPiece name, int value) override {
+    pickle_.WriteBytes(&kTypeInt, 1);
+    pickle_.WriteInt(value);
+    WriteKeyNameWithCopy(pickle_, name);
+  }
+
+  void SetDouble(const char* name, double value) override {
+    pickle_.WriteBytes(&kTypeDouble, 1);
+    pickle_.WriteDouble(value);
+    WriteKeyNameAsRawPtr(pickle_, name);
+  }
+
+  void SetDoubleWithCopiedName(base::StringPiece name, double value) override {
+    pickle_.WriteBytes(&kTypeDouble, 1);
+    pickle_.WriteDouble(value);
+    WriteKeyNameWithCopy(pickle_, name);
+  }
+
+  void SetBoolean(const char* name, bool value) override {
+    pickle_.WriteBytes(&kTypeBool, 1);
+    pickle_.WriteBool(value);
+    WriteKeyNameAsRawPtr(pickle_, name);
+  }
+
+  void SetBooleanWithCopiedName(base::StringPiece name, bool value) override {
+    pickle_.WriteBytes(&kTypeBool, 1);
+    pickle_.WriteBool(value);
+    WriteKeyNameWithCopy(pickle_, name);
+  }
+
+  void SetString(const char* name, base::StringPiece value) override {
+    pickle_.WriteBytes(&kTypeString, 1);
+    pickle_.WriteString(value);
+    WriteKeyNameAsRawPtr(pickle_, name);
+  }
+
+  void SetStringWithCopiedName(base::StringPiece name,
+                               base::StringPiece value) override {
+    pickle_.WriteBytes(&kTypeString, 1);
+    pickle_.WriteString(value);
+    WriteKeyNameWithCopy(pickle_, name);
+  }
+
+  void SetValue(const char* name, Writer* value) override {
+    DCHECK(value->IsPickleWriter());
+    const PickleWriter* pickle_writer = static_cast<const PickleWriter*>(value);
+
+    BeginDictionary(name);
+    pickle_.WriteBytes(pickle_writer->pickle_.payload(),
+                       static_cast<int>(pickle_writer->pickle_.payload_size()));
+    EndDictionary();
+  }
+
+  void SetValueWithCopiedName(base::StringPiece name, Writer* value) override {
+    DCHECK(value->IsPickleWriter());
+    const PickleWriter* pickle_writer = static_cast<const PickleWriter*>(value);
+
+    BeginDictionaryWithCopiedName(name);
+    pickle_.WriteBytes(pickle_writer->pickle_.payload(),
+                       static_cast<int>(pickle_writer->pickle_.payload_size()));
+    EndDictionary();
+  }
+
+  void BeginArray() override { pickle_.WriteBytes(&kTypeStartArray, 1); }
+
+  void BeginDictionary() override { pickle_.WriteBytes(&kTypeStartDict, 1); }
+
+  void BeginDictionary(const char* name) override {
+    pickle_.WriteBytes(&kTypeStartDict, 1);
+    WriteKeyNameAsRawPtr(pickle_, name);
+  }
+
+  void BeginDictionaryWithCopiedName(base::StringPiece name) override {
+    pickle_.WriteBytes(&kTypeStartDict, 1);
+    WriteKeyNameWithCopy(pickle_, name);
+  }
+
+  void BeginArray(const char* name) override {
+    pickle_.WriteBytes(&kTypeStartArray, 1);
+    WriteKeyNameAsRawPtr(pickle_, name);
+  }
+
+  void BeginArrayWithCopiedName(base::StringPiece name) override {
+    pickle_.WriteBytes(&kTypeStartArray, 1);
+    WriteKeyNameWithCopy(pickle_, name);
+  }
+
+  void EndDictionary() override { pickle_.WriteBytes(&kTypeEndDict, 1); }
+  void EndArray() override { pickle_.WriteBytes(&kTypeEndArray, 1); }
+
+  void AppendInteger(int value) override {
+    pickle_.WriteBytes(&kTypeInt, 1);
+    pickle_.WriteInt(value);
+  }
+
+  void AppendDouble(double value) override {
+    pickle_.WriteBytes(&kTypeDouble, 1);
+    pickle_.WriteDouble(value);
+  }
+
+  void AppendBoolean(bool value) override {
+    pickle_.WriteBytes(&kTypeBool, 1);
+    pickle_.WriteBool(value);
+  }
+
+  void AppendString(base::StringPiece value) override {
+    pickle_.WriteBytes(&kTypeString, 1);
+    pickle_.WriteString(value);
+  }
+
+  void AppendAsTraceFormat(std::string* out) const override {
+    struct State {
+      enum Type { kTypeDict, kTypeArray };
+      Type type;
+      bool needs_comma;
+    };
+
+    auto maybe_append_key_name = [](State current_state, PickleIterator* it,
+                                    std::string* out) {
+      if (current_state.type == State::kTypeDict) {
+        EscapeJSONString(ReadKeyName(*it), true, out);
+        out->append(":");
+      }
+    };
+
+    base::circular_deque<State> state_stack;
+
+    out->append("{");
+    state_stack.push_back({State::kTypeDict});
+
+    PickleIterator it(pickle_);
+    for (const char* type; it.ReadBytes(&type, 1);) {
+      switch (*type) {
+        case kTypeEndDict:
+          out->append("}");
+          state_stack.pop_back();
+          continue;
+
+        case kTypeEndArray:
+          out->append("]");
+          state_stack.pop_back();
+          continue;
+      }
+
+      // Use an index so it will stay valid across resizes.
+      size_t current_state_index = state_stack.size() - 1;
+      if (state_stack[current_state_index].needs_comma) {
+        out->append(",");
+      }
+
+      switch (*type) {
+        case kTypeStartDict: {
+          maybe_append_key_name(state_stack[current_state_index], &it, out);
+          out->append("{");
+          state_stack.push_back({State::kTypeDict});
+          break;
+        }
+
+        case kTypeStartArray: {
+          maybe_append_key_name(state_stack[current_state_index], &it, out);
+          out->append("[");
+          state_stack.push_back({State::kTypeArray});
+          break;
+        }
+
+        case kTypeBool: {
+          TraceEvent::TraceValue json_value;
+          CHECK(it.ReadBool(&json_value.as_bool));
+          maybe_append_key_name(state_stack[current_state_index], &it, out);
+          TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out);
+          break;
+        }
+
+        case kTypeInt: {
+          int value;
+          CHECK(it.ReadInt(&value));
+          maybe_append_key_name(state_stack[current_state_index], &it, out);
+          TraceEvent::TraceValue json_value;
+          json_value.as_int = value;
+          TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out);
+          break;
+        }
+
+        case kTypeDouble: {
+          TraceEvent::TraceValue json_value;
+          CHECK(it.ReadDouble(&json_value.as_double));
+          maybe_append_key_name(state_stack[current_state_index], &it, out);
+          TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value,
+                                        out);
+          break;
+        }
+
+        case kTypeString: {
+          std::string value;
+          CHECK(it.ReadString(&value));
+          maybe_append_key_name(state_stack[current_state_index], &it, out);
+          TraceEvent::TraceValue json_value;
+          json_value.as_string = value.c_str();
+          TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value,
+                                        out);
+          break;
+        }
+
+        default:
+          NOTREACHED();
+      }
+
+      state_stack[current_state_index].needs_comma = true;
+    }
+
+    out->append("}");
+    state_stack.pop_back();
+
+    DCHECK(state_stack.empty());
+  }
+
+  void EstimateTraceMemoryOverhead(
+      TraceEventMemoryOverhead* overhead) override {
+    overhead->Add(TraceEventMemoryOverhead::kTracedValue,
+                  /* allocated size */
+                  pickle_.GetTotalAllocatedSize(),
+                  /* resident size */
+                  pickle_.size());
+  }
+
+  std::unique_ptr<base::Value> ToBaseValue() const override {
+    base::Value root(base::Value::Type::DICTIONARY);
+    Value* cur_dict = &root;
+    Value* cur_list = nullptr;
+    std::vector<Value*> stack;
+    PickleIterator it(pickle_);
+    const char* type;
+
+    while (it.ReadBytes(&type, 1)) {
+      DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict));
+      switch (*type) {
+        case kTypeStartDict: {
+          base::Value new_dict(base::Value::Type::DICTIONARY);
+          if (cur_dict) {
+            stack.push_back(cur_dict);
+            cur_dict = cur_dict->SetKey(ReadKeyName(it), std::move(new_dict));
+          } else {
+            cur_list->GetList().push_back(std::move(new_dict));
+            // |new_dict| is invalidated at this point, so |cur_dict| needs to
+            // be reset.
+            cur_dict = &cur_list->GetList().back();
+            stack.push_back(cur_list);
+            cur_list = nullptr;
+          }
+        } break;
+
+        case kTypeEndArray:
+        case kTypeEndDict: {
+          if (stack.back()->is_dict()) {
+            cur_dict = stack.back();
+            cur_list = nullptr;
+          } else if (stack.back()->is_list()) {
+            cur_list = stack.back();
+            cur_dict = nullptr;
+          }
+          stack.pop_back();
+        } break;
+
+        case kTypeStartArray: {
+          base::Value new_list(base::Value::Type::LIST);
+          if (cur_dict) {
+            stack.push_back(cur_dict);
+            cur_list = cur_dict->SetKey(ReadKeyName(it), std::move(new_list));
+            cur_dict = nullptr;
+          } else {
+            cur_list->GetList().push_back(std::move(new_list));
+            stack.push_back(cur_list);
+            // |cur_list| is invalidated at this point by the Append, so it
+            // needs to be reset.
+            cur_list = &cur_list->GetList().back();
+          }
+        } break;
+
+        case kTypeBool: {
+          bool value;
+          CHECK(it.ReadBool(&value));
+          base::Value new_bool(value);
+          if (cur_dict) {
+            cur_dict->SetKey(ReadKeyName(it), std::move(new_bool));
+          } else {
+            cur_list->GetList().push_back(std::move(new_bool));
+          }
+        } break;
+
+        case kTypeInt: {
+          int value;
+          CHECK(it.ReadInt(&value));
+          base::Value new_int(value);
+          if (cur_dict) {
+            cur_dict->SetKey(ReadKeyName(it), std::move(new_int));
+          } else {
+            cur_list->GetList().push_back(std::move(new_int));
+          }
+        } break;
+
+        case kTypeDouble: {
+          double value;
+          CHECK(it.ReadDouble(&value));
+          base::Value new_double(value);
+          if (cur_dict) {
+            cur_dict->SetKey(ReadKeyName(it), std::move(new_double));
+          } else {
+            cur_list->GetList().push_back(std::move(new_double));
+          }
+        } break;
+
+        case kTypeString: {
+          std::string value;
+          CHECK(it.ReadString(&value));
+          base::Value new_str(std::move(value));
+          if (cur_dict) {
+            cur_dict->SetKey(ReadKeyName(it), std::move(new_str));
+          } else {
+            cur_list->GetList().push_back(std::move(new_str));
+          }
+        } break;
+
+        default:
+          NOTREACHED();
+      }
+    }
+    DCHECK(stack.empty());
+    return base::Value::ToUniquePtrValue(std::move(root));
+  }
+
+ private:
+  Pickle pickle_;
+};
+
+std::unique_ptr<TracedValue::Writer> CreateWriter(size_t capacity) {
+  TracedValue::WriterFactoryCallback callback =
+      g_writer_factory_callback.load();
+  if (callback) {
+    return callback(capacity);
+  }
+
+  return std::make_unique<PickleWriter>(capacity);
+}
+
 }  // namespace
 
+bool TracedValue::Writer::AppendToProto(ProtoAppender* appender) {
+  return false;
+}
+
+// static
+void TracedValue::SetWriterFactoryCallback(WriterFactoryCallback callback) {
+  g_writer_factory_callback.store(callback);
+}
+
 TracedValue::TracedValue() : TracedValue(0) {}
 
 TracedValue::TracedValue(size_t capacity) {
   DEBUG_PUSH_CONTAINER(kStackTypeDict);
-  if (capacity)
-    pickle_.Reserve(capacity);
+
+  writer_ = CreateWriter(capacity);
 }
 
 TracedValue::~TracedValue() {
@@ -95,487 +470,143 @@
 
 void TracedValue::SetInteger(const char* name, int value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeInt, 1);
-  pickle_.WriteInt(value);
-  WriteKeyNameAsRawPtr(pickle_, name);
+  writer_->SetInteger(name, value);
 }
 
 void TracedValue::SetIntegerWithCopiedName(base::StringPiece name, int value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeInt, 1);
-  pickle_.WriteInt(value);
-  WriteKeyNameWithCopy(pickle_, name);
+  writer_->SetIntegerWithCopiedName(name, value);
 }
 
 void TracedValue::SetDouble(const char* name, double value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeDouble, 1);
-  pickle_.WriteDouble(value);
-  WriteKeyNameAsRawPtr(pickle_, name);
+  writer_->SetDouble(name, value);
 }
 
 void TracedValue::SetDoubleWithCopiedName(base::StringPiece name,
                                           double value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeDouble, 1);
-  pickle_.WriteDouble(value);
-  WriteKeyNameWithCopy(pickle_, name);
+  writer_->SetDoubleWithCopiedName(name, value);
 }
 
 void TracedValue::SetBoolean(const char* name, bool value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeBool, 1);
-  pickle_.WriteBool(value);
-  WriteKeyNameAsRawPtr(pickle_, name);
+  writer_->SetBoolean(name, value);
 }
 
 void TracedValue::SetBooleanWithCopiedName(base::StringPiece name, bool value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeBool, 1);
-  pickle_.WriteBool(value);
-  WriteKeyNameWithCopy(pickle_, name);
+  writer_->SetBooleanWithCopiedName(name, value);
 }
 
 void TracedValue::SetString(const char* name, base::StringPiece value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeString, 1);
-  pickle_.WriteString(value);
-  WriteKeyNameAsRawPtr(pickle_, name);
+  writer_->SetString(name, value);
 }
 
 void TracedValue::SetStringWithCopiedName(base::StringPiece name,
                                           base::StringPiece value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeString, 1);
-  pickle_.WriteString(value);
-  WriteKeyNameWithCopy(pickle_, name);
+  writer_->SetStringWithCopiedName(name, value);
 }
 
-void TracedValue::SetValue(const char* name, const TracedValue& value) {
+void TracedValue::SetValue(const char* name, TracedValue* value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  BeginDictionary(name);
-  pickle_.WriteBytes(value.pickle_.payload(),
-                     static_cast<int>(value.pickle_.payload_size()));
-  EndDictionary();
+  writer_->SetValue(name, value->writer_.get());
 }
 
 void TracedValue::SetValueWithCopiedName(base::StringPiece name,
-                                         const TracedValue& value) {
+                                         TracedValue* value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  BeginDictionaryWithCopiedName(name);
-  pickle_.WriteBytes(value.pickle_.payload(),
-                     static_cast<int>(value.pickle_.payload_size()));
-  EndDictionary();
+  writer_->SetValueWithCopiedName(name, value->writer_.get());
 }
 
 void TracedValue::BeginDictionary(const char* name) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
   DEBUG_PUSH_CONTAINER(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeStartDict, 1);
-  WriteKeyNameAsRawPtr(pickle_, name);
+  writer_->BeginDictionary(name);
 }
 
 void TracedValue::BeginDictionaryWithCopiedName(base::StringPiece name) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
   DEBUG_PUSH_CONTAINER(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeStartDict, 1);
-  WriteKeyNameWithCopy(pickle_, name);
+  writer_->BeginDictionaryWithCopiedName(name);
 }
 
 void TracedValue::BeginArray(const char* name) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
   DEBUG_PUSH_CONTAINER(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeStartArray, 1);
-  WriteKeyNameAsRawPtr(pickle_, name);
+  writer_->BeginArray(name);
 }
 
 void TracedValue::BeginArrayWithCopiedName(base::StringPiece name) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
   DEBUG_PUSH_CONTAINER(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeStartArray, 1);
-  WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::EndDictionary() {
-  DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  DEBUG_POP_CONTAINER();
-  pickle_.WriteBytes(&kTypeEndDict, 1);
+  writer_->BeginArrayWithCopiedName(name);
 }
 
 void TracedValue::AppendInteger(int value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeInt, 1);
-  pickle_.WriteInt(value);
+  writer_->AppendInteger(value);
 }
 
 void TracedValue::AppendDouble(double value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeDouble, 1);
-  pickle_.WriteDouble(value);
+  writer_->AppendDouble(value);
 }
 
 void TracedValue::AppendBoolean(bool value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeBool, 1);
-  pickle_.WriteBool(value);
+  writer_->AppendBoolean(value);
 }
 
 void TracedValue::AppendString(base::StringPiece value) {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeString, 1);
-  pickle_.WriteString(value);
+  writer_->AppendString(value);
 }
 
 void TracedValue::BeginArray() {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
   DEBUG_PUSH_CONTAINER(kStackTypeArray);
-  pickle_.WriteBytes(&kTypeStartArray, 1);
+  writer_->BeginArray();
 }
 
 void TracedValue::BeginDictionary() {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
   DEBUG_PUSH_CONTAINER(kStackTypeDict);
-  pickle_.WriteBytes(&kTypeStartDict, 1);
+  writer_->BeginDictionary();
 }
 
 void TracedValue::EndArray() {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
   DEBUG_POP_CONTAINER();
-  pickle_.WriteBytes(&kTypeEndArray, 1);
+  writer_->EndArray();
 }
 
-void TracedValue::SetValue(const char* name,
-                           std::unique_ptr<base::Value> value) {
-  SetBaseValueWithCopiedName(name, *value);
-}
-
-void TracedValue::SetBaseValueWithCopiedName(base::StringPiece name,
-                                             const base::Value& value) {
+void TracedValue::EndDictionary() {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
-  switch (value.type()) {
-    case base::Value::Type::NONE:
-    case base::Value::Type::BINARY:
-      NOTREACHED();
-      break;
-
-    case base::Value::Type::BOOLEAN: {
-      bool bool_value;
-      value.GetAsBoolean(&bool_value);
-      SetBooleanWithCopiedName(name, bool_value);
-    } break;
-
-    case base::Value::Type::INTEGER: {
-      int int_value;
-      value.GetAsInteger(&int_value);
-      SetIntegerWithCopiedName(name, int_value);
-    } break;
-
-    case base::Value::Type::DOUBLE: {
-      double double_value;
-      value.GetAsDouble(&double_value);
-      SetDoubleWithCopiedName(name, double_value);
-    } break;
-
-    case base::Value::Type::STRING: {
-      const Value* string_value;
-      value.GetAsString(&string_value);
-      SetStringWithCopiedName(name, string_value->GetString());
-    } break;
-
-    case base::Value::Type::DICTIONARY: {
-      const DictionaryValue* dict_value;
-      value.GetAsDictionary(&dict_value);
-      BeginDictionaryWithCopiedName(name);
-      for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
-           it.Advance()) {
-        SetBaseValueWithCopiedName(it.key(), it.value());
-      }
-      EndDictionary();
-    } break;
-
-    case base::Value::Type::LIST: {
-      const ListValue* list_value;
-      value.GetAsList(&list_value);
-      BeginArrayWithCopiedName(name);
-      for (const auto& base_value : *list_value)
-        AppendBaseValue(base_value);
-      EndArray();
-    } break;
-  }
-}
-
-void TracedValue::AppendBaseValue(const base::Value& value) {
-  DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
-  switch (value.type()) {
-    case base::Value::Type::NONE:
-    case base::Value::Type::BINARY:
-      NOTREACHED();
-      break;
-
-    case base::Value::Type::BOOLEAN: {
-      bool bool_value;
-      value.GetAsBoolean(&bool_value);
-      AppendBoolean(bool_value);
-    } break;
-
-    case base::Value::Type::INTEGER: {
-      int int_value;
-      value.GetAsInteger(&int_value);
-      AppendInteger(int_value);
-    } break;
-
-    case base::Value::Type::DOUBLE: {
-      double double_value;
-      value.GetAsDouble(&double_value);
-      AppendDouble(double_value);
-    } break;
-
-    case base::Value::Type::STRING: {
-      const Value* string_value;
-      value.GetAsString(&string_value);
-      AppendString(string_value->GetString());
-    } break;
-
-    case base::Value::Type::DICTIONARY: {
-      const DictionaryValue* dict_value;
-      value.GetAsDictionary(&dict_value);
-      BeginDictionary();
-      for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
-           it.Advance()) {
-        SetBaseValueWithCopiedName(it.key(), it.value());
-      }
-      EndDictionary();
-    } break;
-
-    case base::Value::Type::LIST: {
-      const ListValue* list_value;
-      value.GetAsList(&list_value);
-      BeginArray();
-      for (const auto& base_value : *list_value)
-        AppendBaseValue(base_value);
-      EndArray();
-    } break;
-  }
+  DEBUG_POP_CONTAINER();
+  writer_->EndDictionary();
 }
 
 std::unique_ptr<base::Value> TracedValue::ToBaseValue() const {
-  base::Value root(base::Value::Type::DICTIONARY);
-  Value* cur_dict = &root;
-  Value* cur_list = nullptr;
-  std::vector<Value*> stack;
-  PickleIterator it(pickle_);
-  const char* type;
-
-  while (it.ReadBytes(&type, 1)) {
-    DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict));
-    switch (*type) {
-      case kTypeStartDict: {
-        base::Value new_dict(base::Value::Type::DICTIONARY);
-        if (cur_dict) {
-          stack.push_back(cur_dict);
-          cur_dict = cur_dict->SetKey(ReadKeyName(it), std::move(new_dict));
-        } else {
-          cur_list->GetList().push_back(std::move(new_dict));
-          // |new_dict| is invalidated at this point, so |cur_dict| needs to be
-          // reset.
-          cur_dict = &cur_list->GetList().back();
-          stack.push_back(cur_list);
-          cur_list = nullptr;
-        }
-      } break;
-
-      case kTypeEndArray:
-      case kTypeEndDict: {
-        if (stack.back()->is_dict()) {
-          cur_dict = stack.back();
-          cur_list = nullptr;
-        } else if (stack.back()->is_list()) {
-          cur_list = stack.back();
-          cur_dict = nullptr;
-        }
-        stack.pop_back();
-      } break;
-
-      case kTypeStartArray: {
-        base::Value new_list(base::Value::Type::LIST);
-        if (cur_dict) {
-          stack.push_back(cur_dict);
-          cur_list = cur_dict->SetKey(ReadKeyName(it), std::move(new_list));
-          cur_dict = nullptr;
-        } else {
-          cur_list->GetList().push_back(std::move(new_list));
-          stack.push_back(cur_list);
-          // |cur_list| is invalidated at this point by the Append, so it needs
-          // to be reset.
-          cur_list = &cur_list->GetList().back();
-        }
-      } break;
-
-      case kTypeBool: {
-        bool value;
-        CHECK(it.ReadBool(&value));
-        base::Value new_bool(value);
-        if (cur_dict) {
-          cur_dict->SetKey(ReadKeyName(it), std::move(new_bool));
-        } else {
-          cur_list->GetList().push_back(std::move(new_bool));
-        }
-      } break;
-
-      case kTypeInt: {
-        int value;
-        CHECK(it.ReadInt(&value));
-        base::Value new_int(value);
-        if (cur_dict) {
-          cur_dict->SetKey(ReadKeyName(it), std::move(new_int));
-        } else {
-          cur_list->GetList().push_back(std::move(new_int));
-        }
-      } break;
-
-      case kTypeDouble: {
-        double value;
-        CHECK(it.ReadDouble(&value));
-        base::Value new_double(value);
-        if (cur_dict) {
-          cur_dict->SetKey(ReadKeyName(it), std::move(new_double));
-        } else {
-          cur_list->GetList().push_back(std::move(new_double));
-        }
-      } break;
-
-      case kTypeString: {
-        std::string value;
-        CHECK(it.ReadString(&value));
-        base::Value new_str(std::move(value));
-        if (cur_dict) {
-          cur_dict->SetKey(ReadKeyName(it), std::move(new_str));
-        } else {
-          cur_list->GetList().push_back(std::move(new_str));
-        }
-      } break;
-
-      default:
-        NOTREACHED();
-    }
-  }
-  DCHECK(stack.empty());
-  return base::Value::ToUniquePtrValue(std::move(root));
+  return writer_->ToBaseValue();
 }
 
 void TracedValue::AppendAsTraceFormat(std::string* out) const {
   DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
   DCHECK_CONTAINER_STACK_DEPTH_EQ(1u);
 
-  struct State {
-    enum Type { kTypeDict, kTypeArray };
-    Type type;
-    bool needs_comma;
-  };
+  writer_->AppendAsTraceFormat(out);
+}
 
-  auto maybe_append_key_name = [](State current_state, PickleIterator* it,
-                                  std::string* out) {
-    if (current_state.type == State::kTypeDict) {
-      EscapeJSONString(ReadKeyName(*it), true, out);
-      out->append(":");
-    }
-  };
-
-  base::circular_deque<State> state_stack;
-
-  out->append("{");
-  state_stack.push_back({State::kTypeDict});
-
-  PickleIterator it(pickle_);
-  for (const char* type; it.ReadBytes(&type, 1);) {
-    switch (*type) {
-      case kTypeEndDict:
-        out->append("}");
-        state_stack.pop_back();
-        continue;
-
-      case kTypeEndArray:
-        out->append("]");
-        state_stack.pop_back();
-        continue;
-    }
-
-    // Use an index so it will stay valid across resizes.
-    size_t current_state_index = state_stack.size() - 1;
-    if (state_stack[current_state_index].needs_comma)
-      out->append(",");
-
-    switch (*type) {
-      case kTypeStartDict: {
-        maybe_append_key_name(state_stack[current_state_index], &it, out);
-        out->append("{");
-        state_stack.push_back({State::kTypeDict});
-        break;
-      }
-
-      case kTypeStartArray: {
-        maybe_append_key_name(state_stack[current_state_index], &it, out);
-        out->append("[");
-        state_stack.push_back({State::kTypeArray});
-        break;
-      }
-
-      case kTypeBool: {
-        TraceEvent::TraceValue json_value;
-        CHECK(it.ReadBool(&json_value.as_bool));
-        maybe_append_key_name(state_stack[current_state_index], &it, out);
-        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out);
-        break;
-      }
-
-      case kTypeInt: {
-        int value;
-        CHECK(it.ReadInt(&value));
-        maybe_append_key_name(state_stack[current_state_index], &it, out);
-        TraceEvent::TraceValue json_value;
-        json_value.as_int = value;
-        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out);
-        break;
-      }
-
-      case kTypeDouble: {
-        TraceEvent::TraceValue json_value;
-        CHECK(it.ReadDouble(&json_value.as_double));
-        maybe_append_key_name(state_stack[current_state_index], &it, out);
-        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out);
-        break;
-      }
-
-      case kTypeString: {
-        std::string value;
-        CHECK(it.ReadString(&value));
-        maybe_append_key_name(state_stack[current_state_index], &it, out);
-        TraceEvent::TraceValue json_value;
-        json_value.as_string = value.c_str();
-        TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out);
-        break;
-      }
-
-      default:
-        NOTREACHED();
-    }
-
-    state_stack[current_state_index].needs_comma = true;
-  }
-
-  out->append("}");
-  state_stack.pop_back();
-
-  DCHECK(state_stack.empty());
+bool TracedValue::AppendToProto(ProtoAppender* appender) {
+  return writer_->AppendToProto(appender);
 }
 
 void TracedValue::EstimateTraceMemoryOverhead(
     TraceEventMemoryOverhead* overhead) {
-  overhead->Add(TraceEventMemoryOverhead::kTracedValue,
-                /* allocated size */
-                pickle_.GetTotalAllocatedSize(),
-                /* resident size */
-                pickle_.size());
+  writer_->EstimateTraceMemoryOverhead(overhead);
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/traced_value.h b/base/trace_event/traced_value.h
index 97c52a076..aebd562d 100644
--- a/base/trace_event/traced_value.h
+++ b/base/trace_event/traced_value.h
@@ -36,7 +36,7 @@
   void SetDouble(const char* name, double value);
   void SetBoolean(const char* name, bool value);
   void SetString(const char* name, base::StringPiece value);
-  void SetValue(const char* name, const TracedValue& value);
+  void SetValue(const char* name, TracedValue* value);
   void BeginDictionary(const char* name);
   void BeginArray(const char* name);
 
@@ -45,7 +45,7 @@
   void SetDoubleWithCopiedName(base::StringPiece name, double value);
   void SetBooleanWithCopiedName(base::StringPiece name, bool value);
   void SetStringWithCopiedName(base::StringPiece name, base::StringPiece value);
-  void SetValueWithCopiedName(base::StringPiece name, const TracedValue& value);
+  void SetValueWithCopiedName(base::StringPiece name, TracedValue* value);
   void BeginDictionaryWithCopiedName(base::StringPiece name);
   void BeginArrayWithCopiedName(base::StringPiece name);
 
@@ -58,23 +58,73 @@
 
   // ConvertableToTraceFormat implementation.
   void AppendAsTraceFormat(std::string* out) const override;
+  bool AppendToProto(ProtoAppender* appender) override;
 
   void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
 
-  // DEPRECATED: do not use, here only for legacy reasons. These methods causes
-  // a copy-and-translation of the base::Value into the equivalent TracedValue.
-  // TODO(primiano): migrate the (three) existing clients to the cheaper
-  // SetValue(TracedValue) API. crbug.com/495628.
-  void SetValue(const char* name, std::unique_ptr<base::Value> value);
-  void SetBaseValueWithCopiedName(base::StringPiece name,
-                                  const base::Value& value);
-  void AppendBaseValue(const base::Value& value);
+  // A custom serialization class can be supplied by implementing the
+  // Writer interface and supplying a factory class to SetWriterFactoryCallback.
+  // Primarily used by Perfetto to write TracedValues directly into its proto
+  // format, which lets us do a direct memcpy() in AppendToProto() rather than
+  // a JSON serialization step in AppendAsTraceFormat.
+  class BASE_EXPORT Writer {
+   public:
+    virtual ~Writer() = default;
+
+    virtual void BeginArray() = 0;
+    virtual void BeginDictionary() = 0;
+    virtual void EndDictionary() = 0;
+    virtual void EndArray() = 0;
+
+    // These methods assume that |name| is a long lived "quoted" string.
+    virtual void SetInteger(const char* name, int value) = 0;
+    virtual void SetDouble(const char* name, double value) = 0;
+    virtual void SetBoolean(const char* name, bool value) = 0;
+    virtual void SetString(const char* name, base::StringPiece value) = 0;
+    virtual void SetValue(const char* name, Writer* value) = 0;
+    virtual void BeginDictionary(const char* name) = 0;
+    virtual void BeginArray(const char* name) = 0;
+
+    // These, instead, can be safely passed a temporary string.
+    virtual void SetIntegerWithCopiedName(base::StringPiece name,
+                                          int value) = 0;
+    virtual void SetDoubleWithCopiedName(base::StringPiece name,
+                                         double value) = 0;
+    virtual void SetBooleanWithCopiedName(base::StringPiece name,
+                                          bool value) = 0;
+    virtual void SetStringWithCopiedName(base::StringPiece name,
+                                         base::StringPiece value) = 0;
+    virtual void SetValueWithCopiedName(base::StringPiece name,
+                                        Writer* value) = 0;
+    virtual void BeginDictionaryWithCopiedName(base::StringPiece name) = 0;
+    virtual void BeginArrayWithCopiedName(base::StringPiece name) = 0;
+
+    virtual void AppendInteger(int) = 0;
+    virtual void AppendDouble(double) = 0;
+    virtual void AppendBoolean(bool) = 0;
+    virtual void AppendString(base::StringPiece) = 0;
+
+    virtual void AppendAsTraceFormat(std::string* out) const = 0;
+
+    virtual bool AppendToProto(ProtoAppender* appender);
+
+    virtual void EstimateTraceMemoryOverhead(
+        TraceEventMemoryOverhead* overhead) = 0;
+
+    virtual std::unique_ptr<base::Value> ToBaseValue() const = 0;
+
+    virtual bool IsPickleWriter() const = 0;
+    virtual bool IsProtoWriter() const = 0;
+  };
+
+  typedef std::unique_ptr<Writer> (*WriterFactoryCallback)(size_t capacity);
+  static void SetWriterFactoryCallback(WriterFactoryCallback callback);
 
   // Public for tests only.
   std::unique_ptr<base::Value> ToBaseValue() const;
 
  private:
-  Pickle pickle_;
+  std::unique_ptr<Writer> writer_;
 
 #ifndef NDEBUG
   // In debug builds checks the pairings of {Start,End}{Dictionary,Array}
diff --git a/base/trace_event/traced_value_unittest.cc b/base/trace_event/traced_value_unittest.cc
index 21f58c66..4278c453c 100644
--- a/base/trace_event/traced_value_unittest.cc
+++ b/base/trace_event/traced_value_unittest.cc
@@ -95,40 +95,6 @@
             json);
 }
 
-TEST(TraceEventArgumentTest, PassBaseValue) {
-  Value int_value(42);
-  Value bool_value(true);
-  Value double_value(42.0f);
-
-  auto dict_value = std::make_unique<DictionaryValue>();
-  dict_value->SetBoolean("bool", true);
-  dict_value->SetInteger("int", 42);
-  dict_value->SetDouble("double", 42.0f);
-  dict_value->SetString("string", std::string("a") + "b");
-  dict_value->SetString("string", std::string("a") + "b");
-
-  auto list_value = std::make_unique<ListValue>();
-  list_value->AppendBoolean(false);
-  list_value->AppendInteger(1);
-  list_value->AppendString("in_list");
-  list_value->Append(std::move(dict_value));
-
-  std::unique_ptr<TracedValue> value(new TracedValue());
-  value->BeginDictionary("outer_dict");
-  value->SetValue("inner_list", std::move(list_value));
-  value->EndDictionary();
-
-  dict_value.reset();
-  list_value.reset();
-
-  std::string json;
-  value->AppendAsTraceFormat(&json);
-  EXPECT_EQ(
-      "{\"outer_dict\":{\"inner_list\":[false,1,\"in_list\",{\"bool\":true,"
-      "\"double\":42.0,\"int\":42,\"string\":\"ab\"}]}}",
-      json);
-}
-
 TEST(TraceEventArgumentTest, PassTracedValue) {
   auto dict_value = std::make_unique<TracedValue>();
   dict_value->SetInteger("a", 1);
@@ -139,7 +105,7 @@
   nested_dict_value->AppendString("foo");
   nested_dict_value->EndArray();
 
-  dict_value->SetValue("e", *nested_dict_value);
+  dict_value->SetValue("e", nested_dict_value.get());
 
   // Check the merged result.
   std::string json;
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index cd544e8..2ff94137 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-347788cdd047836f67a991285b6d93b93615d82c
\ No newline at end of file
+b50dfdfe8d6d893ea58526a56950d904ea0c9a26
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 25639bd..cefe895 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-aba94fa29d31e783ae10d9930d176336697d538a
\ No newline at end of file
+87575d6a191bf4f9e7c13d62f8b283de157aeaf7
\ No newline at end of file
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index f976fa6..d2dbd42 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -53,7 +53,6 @@
       sorting_context_id(0),
       use_parent_backface_visibility(false),
       background_color(0),
-      backdrop_filter_quality(1.0f),
       scrollable(false),
       is_scrollbar(false),
       user_scrollable_horizontal(true),
@@ -555,10 +554,6 @@
   SetNeedsCommit();
 }
 
-void Layer::SetBackdropFilterQuality(const float quality) {
-  inputs_.backdrop_filter_quality = quality;
-}
-
 void Layer::SetFiltersOrigin(const gfx::PointF& filters_origin) {
   DCHECK(IsPropertyChangeAllowed());
   if (inputs_.filters_origin == filters_origin)
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index b90f455..8a4094ca 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -283,11 +283,6 @@
     return inputs_.backdrop_filters;
   }
 
-  void SetBackdropFilterQuality(const float quality);
-  float backdrop_filter_quality() const {
-    return inputs_.backdrop_filter_quality;
-  }
-
   // Set or get an optimization hint that the contents of this layer are fully
   // opaque or not. If true, every pixel of content inside the layer's bounds
   // must be opaque or visual errors can occur. This applies only to this layer
@@ -902,7 +897,6 @@
     FilterOperations filters;
     FilterOperations backdrop_filters;
     gfx::PointF filters_origin;
-    float backdrop_filter_quality;
 
     gfx::ScrollOffset scroll_offset;
 
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 7be0727..3a1f4e9 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -789,7 +789,7 @@
                                               *state);
 
   if (debug_info_)
-    state->SetValue("debug_info", *debug_info_);
+    state->SetValue("debug_info", debug_info_);
 }
 
 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
diff --git a/cc/layers/layer_impl_test_properties.h b/cc/layers/layer_impl_test_properties.h
index c931d45..31cebf4 100644
--- a/cc/layers/layer_impl_test_properties.h
+++ b/cc/layers/layer_impl_test_properties.h
@@ -48,7 +48,6 @@
   float opacity;
   FilterOperations filters;
   FilterOperations backdrop_filters;
-  float backdrop_filter_quality;
   gfx::PointF filters_origin;
   SkBlendMode blend_mode;
   LayerPositionConstraint position_constraint;
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index d4a0e72f..4e90999 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -464,8 +464,7 @@
   quad->SetNew(shared_quad_state, content_rect(), unoccluded_content_rect, id(),
                mask_resource_id, mask_uv_rect, mask_texture_size,
                surface_contents_scale, FiltersOrigin(), tex_coord_rect,
-               !layer_tree_impl_->settings().enable_edge_anti_aliasing,
-               OwningEffectNode()->backdrop_filter_quality);
+               !layer_tree_impl_->settings().enable_edge_anti_aliasing);
 }
 
 void RenderSurfaceImpl::TileMaskLayer(
@@ -577,7 +576,6 @@
         quad_space_to_surface_space_transform, gfx::RectF(quad_rect));
     tex_coord_rect.Offset(-content_rect().OffsetFromOrigin());
 
-    constexpr float backdrop_filter_quality = 1.0;
     switch (temp_quad->material) {
       case viz::DrawQuad::TILED_CONTENT: {
         DCHECK_EQ(1U, temp_quad->resources.count);
@@ -625,8 +623,7 @@
                      temp_quad->resources.ids[0], mask_uv_rect,
                      mask_texture_size, owning_layer_to_surface_contents_scale,
                      FiltersOrigin(), tex_coord_rect,
-                     !layer_tree_impl_->settings().enable_edge_anti_aliasing,
-                     backdrop_filter_quality);
+                     !layer_tree_impl_->settings().enable_edge_anti_aliasing);
       } break;
       case viz::DrawQuad::SOLID_COLOR: {
         SkColor temp_color =
@@ -645,8 +642,7 @@
                      gfx::RectF(), gfx::Size(),
                      owning_layer_to_surface_contents_scale, FiltersOrigin(),
                      tex_coord_rect,
-                     !layer_tree_impl_->settings().enable_edge_anti_aliasing,
-                     backdrop_filter_quality);
+                     !layer_tree_impl_->settings().enable_edge_anti_aliasing);
       } break;
       case viz::DrawQuad::DEBUG_BORDER:
         NOTIMPLEMENTED();
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index 17a2047..e1f83fa 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -114,7 +114,7 @@
   auto* quad = to_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>();
   quad->SetNew(shared_state, output_rect, output_rect, contributing_pass->id, 0,
                gfx::RectF(), gfx::Size(), gfx::Vector2dF(), gfx::PointF(),
-               gfx::RectF(), false, 1.0f);
+               gfx::RectF(), false);
 }
 
 void AddRenderPassQuad(viz::RenderPass* to_pass,
@@ -132,7 +132,7 @@
   quad->SetNew(shared_state, output_rect, output_rect, contributing_pass->id,
                mask_resource_id, gfx::RectF(output_rect),
                arbitrary_nonzero_size, gfx::Vector2dF(), gfx::PointF(),
-               gfx::RectF(), false, 1.0f);
+               gfx::RectF(), false);
 }
 
 std::vector<viz::ResourceId> AddOneOfEveryQuadType(
@@ -184,7 +184,7 @@
     render_pass_quad->SetNew(shared_state, rect, visible_rect, child_pass_id,
                              resource5, gfx::RectF(rect), gfx::Size(73, 26),
                              gfx::Vector2dF(), gfx::PointF(), gfx::RectF(),
-                             false, 1.0f);
+                             false);
   }
 
   auto* solid_color_quad =
@@ -360,7 +360,7 @@
     render_pass_quad->SetNew(shared_state, rect, visible_rect, child_pass_id,
                              mapped_resource5, gfx::RectF(rect),
                              gfx::Size(73, 26), gfx::Vector2dF(), gfx::PointF(),
-                             gfx::RectF(), false, 1.0f);
+                             gfx::RectF(), false);
   }
 
   viz::SolidColorDrawQuad* solid_color_quad =
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h
index 0f8bf33..61fb30a 100644
--- a/cc/trees/effect_node.h
+++ b/cc/trees/effect_node.h
@@ -40,7 +40,6 @@
 
   FilterOperations filters;
   FilterOperations backdrop_filters;
-  float backdrop_filter_quality;
   gfx::PointF filters_origin;
 
   SkBlendMode blend_mode;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 674b121..cf98d8e8 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -748,14 +748,6 @@
   return layer->test_properties()->backdrop_filters;
 }
 
-static inline float BackdropFilterQuality(Layer* layer) {
-  return layer->backdrop_filter_quality();
-}
-
-static inline float BackdropFilterQuality(LayerImpl* layer) {
-  return layer->test_properties()->backdrop_filter_quality;
-}
-
 static inline bool HideLayerAndSubtree(Layer* layer) {
   return layer->hide_layer_and_subtree();
 }
@@ -992,7 +984,6 @@
   node->has_copy_request = HasCopyRequest(layer);
   node->filters = Filters(layer);
   node->backdrop_filters = BackdropFilters(layer);
-  node->backdrop_filter_quality = BackdropFilterQuality(layer);
   node->filters_origin = FiltersOrigin(layer);
   node->trilinear_filtering = TrilinearFiltering(layer);
   node->has_potential_opacity_animation = has_potential_opacity_animation;
diff --git a/chrome/VERSION b/chrome/VERSION
index d1c7f00..1e5a2f66 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=72
 MINOR=0
-BUILD=3596
+BUILD=3597
 PATCH=0
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 1554be1..4a1820d 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-72.0.3595.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-72.0.3596.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index e1ee297..6acd6a1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -9245,6 +9245,23 @@
        Use Touch ID with <ph name="APP_NAME">$1<ex>example.com</ex></ph>
      </message>
    </if>
+
+   <!-- Incognito Window Counter bubble. -->
+    <message name="IDS_INCOGNITO_WINDOW_COUNTER_TITLE" desc="The title of the incognito window counter dialog.">
+      Incognito
+    </message>
+    <message name="IDS_INCOGNITO_WINDOW_COUNTER_MESSAGE" desc="The message showing the number of open incogntio windows. [ICU Syntax]">
+      {0, plural,
+        =1 {You have one incognito window.}
+        other {You have # incognito windows.}
+      }
+    </message>
+    <message name="IDS_INCOGNITO_WINDOW_COUNTER_CLOSE_BUTTON" desc="The text of the button offering to close all incognito windows. [ICU Syntax]">
+      {0, plural,
+        =1 {Close this window}
+        other {Close all incognito windows}
+      }
+    </message>
   </messages>
  </release>
 </grit>
diff --git a/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_CLOSE_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_CLOSE_BUTTON.png.sha1
new file mode 100644
index 0000000..89806355
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_CLOSE_BUTTON.png.sha1
@@ -0,0 +1 @@
+a8c210abfdce48c1efaaeee8e840640d0e7b88d8
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_MESSAGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_MESSAGE.png.sha1
new file mode 100644
index 0000000..3403d05
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_MESSAGE.png.sha1
@@ -0,0 +1 @@
+f8e8c12628b5f41d612974e54ebc270bffdb134e
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_TITLE.png.sha1
new file mode 100644
index 0000000..6669a63
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_INCOGNITO_WINDOW_COUNTER_TITLE.png.sha1
@@ -0,0 +1 @@
+3274b9f360d9dea6550d20775ee73086ee92b587
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 764fb25..7fb5ff7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3166,6 +3166,9 @@
     {"crostini-files", flag_descriptions::kCrostiniFilesName,
      flag_descriptions::kCrostiniFilesDescription, kOsCrOS,
      SINGLE_VALUE_TYPE(chromeos::switches::kCrostiniFiles)},
+    {"crostini-usb-support", flag_descriptions::kCrostiniUsbSupportName,
+     flag_descriptions::kCrostiniUsbSupportDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kCrostiniUsbSupport)},
 #endif  // OS_CHROMEOS
 
 #if defined(OS_WIN)
diff --git a/chrome/browser/apps/app_shim/app_shim_handler_mac.h b/chrome/browser/apps/app_shim/app_shim_handler_mac.h
index 629d6208..9baa3f8c 100644
--- a/chrome/browser/apps/app_shim/app_shim_handler_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_handler_mac.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_APPS_APP_SHIM_APP_SHIM_HANDLER_MAC_H_
 #define CHROME_BROWSER_APPS_APP_SHIM_APP_SHIM_HANDLER_MAC_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -15,14 +16,23 @@
 class BridgeFactoryHost;
 }  // namespace views
 
+class AppShimHostBootstrap;
+
 namespace apps {
 
 // Registrar, and interface for services that can handle interactions with OSX
 // shim processes.
 class AppShimHandler {
  public:
+  // TODO(ccameron): Remove this virtual interface and always use AppShimHost
+  // directly.
+  // https://crbug.com/896917
   class Host {
    public:
+    // Invoked when the app shim process has finished launching. The |bootstrap|
+    // object owns the lifetime of the app shim process.
+    virtual void OnBootstrapConnected(
+        std::unique_ptr<AppShimHostBootstrap> bootstrap) = 0;
     // Invoked when the app is successfully launched.
     virtual void OnAppLaunchComplete(AppShimLaunchResult result) = 0;
     // Invoked when the app is closed in the browser process.
@@ -75,9 +85,8 @@
   // |launch_type| indicates the type of launch.
   // |files|, if non-empty, holds an array of files paths given as arguments, or
   // dragged onto the app bundle or dock icon.
-  virtual void OnShimLaunch(Host* host,
-                            AppShimLaunchType launch_type,
-                            const std::vector<base::FilePath>& files) = 0;
+  virtual void OnShimLaunch(
+      std::unique_ptr<AppShimHostBootstrap> bootstrap) = 0;
 
   // Invoked by the shim host when the connection to the shim process is closed.
   virtual void OnShimClose(Host* host) = 0;
diff --git a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
index bea5124..831c5d3 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
@@ -48,24 +48,15 @@
   delete this;
 }
 
+apps::AppShimHandler* AppShimHostBootstrap::GetHandler() {
+  return apps::AppShimHandler::GetForAppMode(app_id_);
+}
+
 chrome::mojom::AppShimHostRequest
 AppShimHostBootstrap::GetLaunchAppShimHostRequest() {
   return std::move(app_shim_host_request_);
 }
 
-apps::AppShimLaunchType AppShimHostBootstrap::GetLaunchType() const {
-  return launch_type_;
-}
-
-const std::vector<base::FilePath>& AppShimHostBootstrap::GetLaunchFiles()
-    const {
-  return files_;
-}
-
-apps::AppShimHandler::Host* AppShimHostBootstrap::GetHostForTesting() {
-  return connected_host_;
-}
-
 void AppShimHostBootstrap::LaunchApp(
     chrome::mojom::AppShimHostRequest app_shim_host_request,
     const base::FilePath& profile_dir,
@@ -80,6 +71,8 @@
     return;
 
   app_shim_host_request_ = std::move(app_shim_host_request);
+  profile_path_ = profile_dir;
+  app_id_ = app_id;
   launch_type_ = launch_type;
   files_ = files;
   launch_app_callback_ = std::move(callback);
@@ -90,13 +83,23 @@
   has_received_launch_app_ = true;
   std::unique_ptr<AppShimHostBootstrap> deleter(this);
 
-  // |connected_host_| takes ownership of itself and |this|.
-  connected_host_ = new AppShimHost(app_id, profile_dir);
-  connected_host_->OnBootstrapConnected(std::move(deleter));
+  // |handler| takes ownership of |this| now.
+  apps::AppShimHandler* handler = GetHandler();
+  if (handler)
+    handler->OnShimLaunch(std::move(deleter));
+  // |handler| can only be NULL after AppShimHostManager is destroyed. Since
+  // this only happens at shutdown, do nothing here.
 }
 
-void AppShimHostBootstrap::OnLaunchAppComplete(
-    apps::AppShimLaunchResult result,
+void AppShimHostBootstrap::OnLaunchAppSucceeded(
     chrome::mojom::AppShimRequest app_shim_request) {
-  std::move(launch_app_callback_).Run(result, std::move(app_shim_request));
+  std::move(launch_app_callback_)
+      .Run(apps::APP_SHIM_LAUNCH_SUCCESS, std::move(app_shim_request));
+}
+
+void AppShimHostBootstrap::OnLaunchAppFailed(apps::AppShimLaunchResult result) {
+  // Because there will be users of the AppShim interface in failure, just
+  // return a dummy request.
+  chrome::mojom::AppShimPtr dummy_ptr;
+  std::move(launch_app_callback_).Run(result, mojo::MakeRequest(&dummy_ptr));
 }
diff --git a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
index f961ffd..e545274 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
@@ -25,19 +25,20 @@
   static void CreateForChannel(mojo::PlatformChannelEndpoint endpoint);
   ~AppShimHostBootstrap() override;
 
-  void OnLaunchAppComplete(apps::AppShimLaunchResult result,
-                           chrome::mojom::AppShimRequest app_shim_request);
+  void OnLaunchAppSucceeded(chrome::mojom::AppShimRequest app_shim_request);
+  void OnLaunchAppFailed(apps::AppShimLaunchResult result);
 
   chrome::mojom::AppShimHostRequest GetLaunchAppShimHostRequest();
-  apps::AppShimLaunchType GetLaunchType() const;
-  const std::vector<base::FilePath>& GetLaunchFiles() const;
-
-  apps::AppShimHandler::Host* GetHostForTesting();
+  const std::string& GetAppId() const { return app_id_; }
+  const base::FilePath& GetProfilePath() const { return profile_path_; }
+  apps::AppShimLaunchType GetLaunchType() const { return launch_type_; }
+  const std::vector<base::FilePath>& GetLaunchFiles() const { return files_; }
 
  protected:
   AppShimHostBootstrap();
   void ServeChannel(mojo::PlatformChannelEndpoint endpoint);
   void ChannelError(uint32_t custom_reason, const std::string& description);
+  virtual apps::AppShimHandler* GetHandler();
 
   // chrome::mojom::AppShimHostBootstrap.
   void LaunchApp(chrome::mojom::AppShimHostRequest app_shim_host_request,
@@ -54,14 +55,12 @@
   // yet.
   bool has_received_launch_app_ = false;
   chrome::mojom::AppShimHostRequest app_shim_host_request_;
+  base::FilePath profile_path_;
+  std::string app_id_;
   apps::AppShimLaunchType launch_type_;
   std::vector<base::FilePath> files_;
   LaunchAppCallback launch_app_callback_;
 
-  // The AppShimHost that has taken ownership of this object. Weak, set in
-  // LaunchApp.
-  AppShimHost* connected_host_ = nullptr;
-
   THREAD_CHECKER(thread_checker_);
   DISALLOW_COPY_AND_ASSIGN(AppShimHostBootstrap);
 };
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
index 0f24d8f..08873fd 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
@@ -58,9 +58,10 @@
 
 AppShimHost::~AppShimHost() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
-  if (handler)
-    handler->OnShimClose(this);
+  // Ensure that we send a response to the bootstrap even if we failed to finish
+  // loading.
+  if (bootstrap_ && !has_sent_on_launch_complete_)
+    bootstrap_->OnLaunchAppFailed(apps::APP_SHIM_LAUNCH_APP_NOT_FOUND);
 }
 
 void AppShimHost::ChannelError(uint32_t custom_reason,
@@ -72,9 +73,18 @@
 
 void AppShimHost::Close() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  // Note that we must call GetAppShimHandler here and not in the destructor
+  // because some tests override the method.
+  apps::AppShimHandler* handler = GetAppShimHandler();
+  if (handler)
+    handler->OnShimClose(this);
   delete this;
 }
 
+apps::AppShimHandler* AppShimHost::GetAppShimHandler() const {
+  return apps::AppShimHandler::GetForAppMode(app_id_);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // AppShimHost, chrome::mojom::AppShimHost
 
@@ -87,33 +97,26 @@
   host_binding_.Bind(bootstrap_->GetLaunchAppShimHostRequest());
   host_binding_.set_connection_error_with_reason_handler(
       base::BindOnce(&AppShimHost::ChannelError, base::Unretained(this)));
-
-  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
-  if (handler)
-    handler->OnShimLaunch(this, bootstrap_->GetLaunchType(),
-                          bootstrap_->GetLaunchFiles());
-  // |handler| can only be NULL after AppShimHostManager is destroyed. Since
-  // this only happens at shutdown, do nothing here.
 }
 
 void AppShimHost::FocusApp(apps::AppShimFocusType focus_type,
                            const std::vector<base::FilePath>& files) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+  apps::AppShimHandler* handler = GetAppShimHandler();
   if (handler)
     handler->OnShimFocus(this, focus_type, files);
 }
 
 void AppShimHost::SetAppHidden(bool hidden) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+  apps::AppShimHandler* handler = GetAppShimHandler();
   if (handler)
     handler->OnShimSetHidden(this, hidden);
 }
 
 void AppShimHost::QuitApp() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+  apps::AppShimHandler* handler = GetAppShimHandler();
   if (handler)
     handler->OnShimQuit(this);
 }
@@ -122,11 +125,13 @@
 // AppShimHost, apps::AppShimHandler::Host
 
 void AppShimHost::OnAppLaunchComplete(apps::AppShimLaunchResult result) {
-  if (!has_sent_on_launch_complete_) {
-    DCHECK(bootstrap_);
-    bootstrap_->OnLaunchAppComplete(result, std::move(app_shim_request_));
-    has_sent_on_launch_complete_ = true;
-  }
+  DCHECK(!has_sent_on_launch_complete_);
+  DCHECK(bootstrap_);
+  if (result == apps::APP_SHIM_LAUNCH_SUCCESS)
+    bootstrap_->OnLaunchAppSucceeded(std::move(app_shim_request_));
+  else
+    bootstrap_->OnLaunchAppFailed(result);
+  has_sent_on_launch_complete_ = true;
 }
 
 void AppShimHost::OnAppClosed() {
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.h b/chrome/browser/apps/app_shim/app_shim_host_mac.h
index b89fa994..25ca5e25 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.h
@@ -33,23 +33,10 @@
                     public apps::AppShimHandler::Host {
  public:
   AppShimHost(const std::string& app_id, const base::FilePath& profile_path);
-  ~AppShimHost() override;
-
-  void OnBootstrapConnected(std::unique_ptr<AppShimHostBootstrap> bootstrap);
-
- protected:
-  void ChannelError(uint32_t custom_reason, const std::string& description);
-
-  // Closes the channel and destroys the AppShimHost.
-  void Close();
-
-  // chrome::mojom::AppShimHost.
-  void FocusApp(apps::AppShimFocusType focus_type,
-                const std::vector<base::FilePath>& files) override;
-  void SetAppHidden(bool hidden) override;
-  void QuitApp() override;
 
   // apps::AppShimHandler::Host overrides:
+  void OnBootstrapConnected(
+      std::unique_ptr<AppShimHostBootstrap> bootstrap) override;
   void OnAppLaunchComplete(apps::AppShimLaunchResult result) override;
   void OnAppClosed() override;
   void OnAppHide() override;
@@ -59,6 +46,24 @@
   std::string GetAppId() const override;
   views::BridgeFactoryHost* GetViewsBridgeFactoryHost() const override;
 
+ protected:
+  // AppShimHost is owned by itself. It will delete itself in Close (called on
+  // channel error and OnAppClosed).
+  ~AppShimHost() override;
+  void ChannelError(uint32_t custom_reason, const std::string& description);
+
+  // Closes the channel and destroys the AppShimHost.
+  void Close();
+
+  // Return the AppShimHandler for this app (virtual for tests).
+  virtual apps::AppShimHandler* GetAppShimHandler() const;
+
+  // chrome::mojom::AppShimHost.
+  void FocusApp(apps::AppShimFocusType focus_type,
+                const std::vector<base::FilePath>& files) override;
+  void SetAppHidden(bool hidden) override;
+  void QuitApp() override;
+
   mojo::Binding<chrome::mojom::AppShimHost> host_binding_;
   chrome::mojom::AppShimPtr app_shim_;
   chrome::mojom::AppShimRequest app_shim_request_;
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
index 22167a78..34fd814 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/test_simple_task_runner.h"
@@ -62,6 +63,22 @@
   DISALLOW_COPY_AND_ASSIGN(TestingAppShim);
 };
 
+class TestingAppShimHost : public AppShimHost {
+ public:
+  TestingAppShimHost(const std::string& app_id,
+                     const base::FilePath& profile_path)
+      : AppShimHost(app_id, profile_path), test_weak_factory_(this) {}
+
+  base::WeakPtr<TestingAppShimHost> GetWeakPtr() {
+    return test_weak_factory_.GetWeakPtr();
+  }
+
+ private:
+  ~TestingAppShimHost() override {}
+  base::WeakPtrFactory<TestingAppShimHost> test_weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(TestingAppShimHost);
+};
+
 class TestingAppShimHostBootstrap : public AppShimHostBootstrap {
  public:
   explicit TestingAppShimHostBootstrap(
@@ -76,6 +93,8 @@
     return test_weak_factory_.GetWeakPtr();
   }
 
+  using AppShimHostBootstrap::LaunchApp;
+
  private:
   base::WeakPtrFactory<TestingAppShimHostBootstrap> test_weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(TestingAppShimHostBootstrap);
@@ -91,7 +110,7 @@
 
   ~AppShimHostTest() override {
     if (host_)
-      delete host_.get();
+      host_->OnAppClosed();
     DCHECK(!host_);
   }
 
@@ -99,17 +118,16 @@
   scoped_refptr<base::SingleThreadTaskRunner> task_runner() {
     return task_runner_;
   }
-  TestingAppShimHostBootstrap* host() { return host_.get(); }
-  chrome::mojom::AppShimHostBootstrap* GetBootstrapMojoHost() {
-    return host_.get();
-  }
+  apps::AppShimHandler::Host* host() { return host_.get(); }
   chrome::mojom::AppShimHost* GetMojoHost() { return host_ptr_.get(); }
 
   void LaunchApp(apps::AppShimLaunchType launch_type) {
-    GetBootstrapMojoHost()->LaunchApp(
-        mojo::MakeRequest(&host_ptr_), base::FilePath(kTestProfileDir),
-        kTestAppId, launch_type, std::vector<base::FilePath>(),
-        shim_->GetLaunchAppCallback());
+    // Ownership of TestingAppShimHostBootstrap will be transferred to its host.
+    (new TestingAppShimHostBootstrap(shim_->GetHostBootstrapRequest()))
+        ->LaunchApp(mojo::MakeRequest(&host_ptr_),
+                    base::FilePath(kTestProfileDir), kTestAppId, launch_type,
+                    std::vector<base::FilePath>(),
+                    shim_->GetLaunchAppCallback());
   }
 
   apps::AppShimLaunchResult GetLaunchResult() {
@@ -120,13 +138,17 @@
   void SimulateDisconnect() { host_ptr_.reset(); }
 
  protected:
-  void OnShimLaunch(Host* host,
-                    apps::AppShimLaunchType launch_type,
-                    const std::vector<base::FilePath>& file) override {
+  void OnShimLaunch(std::unique_ptr<AppShimHostBootstrap> bootstrap) override {
     ++launch_count_;
-    if (launch_type == apps::APP_SHIM_LAUNCH_NORMAL)
+    if (bootstrap->GetLaunchType() == apps::APP_SHIM_LAUNCH_NORMAL)
       ++launch_now_count_;
-    host->OnAppLaunchComplete(launch_result_);
+    // Maintain only a weak reference to |host_| because it is owned by itself
+    // and will delete itself upon closing.
+    host_ = (new TestingAppShimHost(bootstrap->GetAppId(),
+                                    bootstrap->GetProfilePath()))
+                ->GetWeakPtr();
+    host_->OnBootstrapConnected(std::move(bootstrap));
+    host_->OnAppLaunchComplete(launch_result_);
   }
 
   void OnShimClose(Host* host) override { ++close_count_; }
@@ -152,9 +174,6 @@
   void SetUp() override {
     testing::Test::SetUp();
     shim_.reset(new TestingAppShim());
-    TestingAppShimHostBootstrap* host =
-        new TestingAppShimHostBootstrap(shim_->GetHostBootstrapRequest());
-    host_ = host->GetWeakPtr();
   }
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -162,9 +181,11 @@
 
   std::unique_ptr<TestingAppShim> shim_;
 
+  std::unique_ptr<AppShimHostBootstrap> launched_bootstrap_;
+
   // AppShimHost will destroy itself in AppShimHost::Close, so use a weak
   // pointer here to avoid lifetime issues.
-  base::WeakPtr<TestingAppShimHostBootstrap> host_;
+  base::WeakPtr<TestingAppShimHost> host_;
   chrome::mojom::AppShimHostPtr host_ptr_;
 
   DISALLOW_COPY_AND_ASSIGN(AppShimHostTest);
@@ -176,18 +197,13 @@
 TEST_F(AppShimHostTest, TestLaunchAppWithHandler) {
   apps::AppShimHandler::RegisterHandler(kTestAppId, this);
   LaunchApp(apps::APP_SHIM_LAUNCH_NORMAL);
-  EXPECT_EQ(kTestAppId, host()->GetHostForTesting()->GetAppId());
+  EXPECT_EQ(kTestAppId, host()->GetAppId());
   EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult());
   EXPECT_EQ(1, launch_count_);
   EXPECT_EQ(1, launch_now_count_);
   EXPECT_EQ(0, focus_count_);
   EXPECT_EQ(0, close_count_);
 
-  // A second OnAppLaunchComplete is ignored.
-  host()->GetHostForTesting()->OnAppLaunchComplete(
-      apps::APP_SHIM_LAUNCH_APP_NOT_FOUND);
-  EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult());
-
   GetMojoHost()->FocusApp(apps::APP_SHIM_FOCUS_NORMAL,
                           std::vector<base::FilePath>());
   RunUntilIdle();
@@ -207,7 +223,7 @@
 TEST_F(AppShimHostTest, TestNoLaunchNow) {
   apps::AppShimHandler::RegisterHandler(kTestAppId, this);
   LaunchApp(apps::APP_SHIM_LAUNCH_REGISTER_ONLY);
-  EXPECT_EQ(kTestAppId, host()->GetHostForTesting()->GetAppId());
+  EXPECT_EQ(kTestAppId, host()->GetAppId());
   EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult());
   EXPECT_EQ(1, launch_count_);
   EXPECT_EQ(0, launch_now_count_);
diff --git a/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm b/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
index 325ca959..b17c6e7 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
+++ b/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
 #include "chrome/browser/apps/app_shim/test/app_shim_host_manager_test_api_mac.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
@@ -99,9 +100,10 @@
 // Browser Test for AppShimHostManager to test IPC interactions across the
 // UNIX domain socket.
 class AppShimHostManagerBrowserTest : public InProcessBrowserTest,
-                                      public apps::AppShimHandler {
+                                      public apps::AppShimHandler,
+                                      public chrome::mojom::AppShimHost {
  public:
-  AppShimHostManagerBrowserTest() {}
+  AppShimHostManagerBrowserTest() : binding_(this) {}
 
  protected:
   // Wait for OnShimLaunch, then send a quit, and wait for the response. Used to
@@ -113,23 +115,32 @@
   void TearDownOnMainThread() override;
 
   // AppShimHandler overrides:
-  void OnShimLaunch(apps::AppShimHandler::Host* host,
-                    apps::AppShimLaunchType launch_type,
-                    const std::vector<base::FilePath>& files) override;
+  void OnShimLaunch(std::unique_ptr<AppShimHostBootstrap> bootstrap) override;
   void OnShimClose(apps::AppShimHandler::Host* host) override {}
   void OnShimFocus(apps::AppShimHandler::Host* host,
                    apps::AppShimFocusType focus_type,
                    const std::vector<base::FilePath>& files) override {}
   void OnShimSetHidden(apps::AppShimHandler::Host* host, bool hidden) override {
   }
-  void OnShimQuit(apps::AppShimHandler::Host* host) override;
+  void OnShimQuit(apps::AppShimHandler::Host* host) override {}
 
   std::unique_ptr<TestShimClient> test_client_;
   std::vector<base::FilePath> last_launch_files_;
   apps::AppShimLaunchType last_launch_type_ = apps::APP_SHIM_LAUNCH_NUM_TYPES;
 
  private:
+  // chrome::mojom::AppShimHost.
+  void FocusApp(apps::AppShimFocusType focus_type,
+                const std::vector<base::FilePath>& files) override {}
+  void SetAppHidden(bool hidden) override {}
+  void QuitApp() override {
+    ++quit_count_;
+    runner_->Quit();
+  }
+
   std::unique_ptr<base::RunLoop> runner_;
+  mojo::Binding<chrome::mojom::AppShimHost> binding_;
+  chrome::mojom::AppShimPtr app_shim_ptr_;
 
   int launch_count_ = 0;
   int quit_count_ = 0;
@@ -146,7 +157,7 @@
   runner_ = std::make_unique<base::RunLoop>();
   test_client_->host()->QuitApp();
   EXPECT_EQ(0, quit_count_);
-  runner_->Run();  // Will stop in OnShimQuit().
+  runner_->Run();  // Will stop in QuitApp().
   EXPECT_EQ(1, quit_count_);
 
   test_client_.reset();
@@ -162,19 +173,13 @@
 }
 
 void AppShimHostManagerBrowserTest::OnShimLaunch(
-    apps::AppShimHandler::Host* host,
-    apps::AppShimLaunchType launch_type,
-    const std::vector<base::FilePath>& files) {
-  host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_SUCCESS);
+    std::unique_ptr<AppShimHostBootstrap> bootstrap) {
   ++launch_count_;
-  last_launch_type_ = launch_type;
-  last_launch_files_ = files;
-  runner_->Quit();
-}
+  binding_.Bind(bootstrap->GetLaunchAppShimHostRequest());
+  last_launch_type_ = bootstrap->GetLaunchType();
+  last_launch_files_ = bootstrap->GetLaunchFiles();
 
-void AppShimHostManagerBrowserTest::OnShimQuit(
-    apps::AppShimHandler::Host* host) {
-  ++quit_count_;
+  bootstrap->OnLaunchAppSucceeded(mojo::MakeRequest(&app_shim_ptr_));
   runner_->Quit();
 }
 
diff --git a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm
index 83166ac..d36e26d 100644
--- a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm
+++ b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #import <Cocoa/Cocoa.h>
+#include <memory>
+#include <utility>
 #include <vector>
 
 #include "apps/app_lifetime_monitor_factory.h"
@@ -24,6 +26,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
@@ -95,13 +98,11 @@
   }
 
   // AppShimHandler overrides:
-  void OnShimLaunch(Host* host,
-                    apps::AppShimLaunchType launch_type,
-                    const std::vector<base::FilePath>& files) override {
+  void OnShimLaunch(std::unique_ptr<AppShimHostBootstrap> bootstrap) override {
     // Remove self and pass through to the default handler.
     apps::AppShimHandler::RemoveHandler(app_mode_id_);
     apps::AppShimHandler::GetForAppMode(app_mode_id_)
-        ->OnShimLaunch(host, launch_type, files);
+        ->OnShimLaunch(std::move(bootstrap));
     observed_ = true;
     if (run_loop_.get())
       run_loop_->Quit();
diff --git a/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm b/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm
index d41afb7..37f8ad7 100644
--- a/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm
+++ b/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm
@@ -8,7 +8,10 @@
 #include <vector>
 
 #include "apps/switches.h"
+#include "base/bind.h"
 #include "base/macros.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
@@ -28,32 +31,14 @@
 
 namespace {
 
-class FakeHost : public apps::AppShimHandler::Host {
+// Test class used to expose protected methods of AppShimHostBootstrap.
+class TestAppShimHostBootstrap : public AppShimHostBootstrap {
  public:
-  FakeHost(const base::FilePath& profile_path,
-           const std::string& app_id,
-           ExtensionAppShimHandler* handler)
-      : profile_path_(profile_path),
-        app_id_(app_id),
-        handler_(handler) {}
-
-  void OnAppLaunchComplete(AppShimLaunchResult result) override {}
-  void OnAppClosed() override { handler_->OnShimClose(this); }
-  void OnAppHide() override {}
-  void OnAppUnhideWithoutActivation() override {}
-  void OnAppRequestUserAttention(AppShimAttentionType type) override {}
-  base::FilePath GetProfilePath() const override { return profile_path_; }
-  std::string GetAppId() const override { return app_id_; }
-  views::BridgeFactoryHost* GetViewsBridgeFactoryHost() const override {
-    return nullptr;
-  }
+  TestAppShimHostBootstrap() {}
+  using AppShimHostBootstrap::LaunchApp;
 
  private:
-  base::FilePath profile_path_;
-  std::string app_id_;
-  ExtensionAppShimHandler* handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeHost);
+  DISALLOW_COPY_AND_ASSIGN(TestAppShimHostBootstrap);
 };
 
 // Starts an app without a browser window using --load_and_launch_app and
@@ -76,13 +61,14 @@
         extensions::ExtensionRegistry::Get(profile());
     extension_id_ =
         GetExtensionByPath(registry->enabled_extensions(), app_path_)->id();
-    host_.reset(new FakeHost(profile()->GetPath().BaseName(),
-                             extension_id_,
-                             handler_));
-    handler_->OnShimLaunch(host_.get(),
-                           APP_SHIM_LAUNCH_REGISTER_ONLY,
-                           std::vector<base::FilePath>());
-    EXPECT_EQ(host_.get(), handler_->FindHost(profile(), extension_id_));
+    chrome::mojom::AppShimHostPtr host_ptr;
+    (new TestAppShimHostBootstrap)
+        ->LaunchApp(mojo::MakeRequest(&host_ptr),
+                    profile()->GetPath().BaseName(), extension_id_,
+                    APP_SHIM_LAUNCH_REGISTER_ONLY,
+                    std::vector<base::FilePath>(),
+                    base::BindOnce(&AppShimQuitTest::DoShimLaunchDone,
+                                   base::Unretained(this)));
 
     // Focus the app window.
     NSWindow* window = [[NSApp windows] objectAtIndex:0];
@@ -90,6 +76,9 @@
     content::RunAllPendingInMessageLoop();
   }
 
+  void DoShimLaunchDone(apps::AppShimLaunchResult result,
+                        chrome::mojom::AppShimRequest app_shim_request) {}
+
   void SetUpCommandLine(base::CommandLine* command_line) override {
     PlatformAppBrowserTest::SetUpCommandLine(command_line);
     // Simulate an app shim initiated launch, i.e. launch app but not browser.
@@ -104,7 +93,6 @@
   base::FilePath app_path_;
   ExtensionAppShimHandler* handler_;
   std::string extension_id_;
-  std::unique_ptr<FakeHost> host_;
 
   DISALLOW_COPY_AND_ASSIGN(AppShimQuitTest);
 };
diff --git a/chrome/browser/apps/app_shim/apps_page_shim_handler.h b/chrome/browser/apps/app_shim/apps_page_shim_handler.h
index 68dd13c..5a7ed3c 100644
--- a/chrome/browser/apps/app_shim/apps_page_shim_handler.h
+++ b/chrome/browser/apps/app_shim/apps_page_shim_handler.h
@@ -17,9 +17,7 @@
   AppsPageShimHandler() {}
 
   // AppShimHandler:
-  void OnShimLaunch(apps::AppShimHandler::Host* host,
-                    apps::AppShimLaunchType launch_type,
-                    const std::vector<base::FilePath>& files) override;
+  void OnShimLaunch(std::unique_ptr<AppShimHostBootstrap> bootstrap) override;
   void OnShimClose(apps::AppShimHandler::Host* host) override;
   void OnShimFocus(apps::AppShimHandler::Host* host,
                    apps::AppShimFocusType focus_type,
diff --git a/chrome/browser/apps/app_shim/apps_page_shim_handler.mm b/chrome/browser/apps/app_shim/apps_page_shim_handler.mm
index ef1b6c8..93fadaf 100644
--- a/chrome/browser/apps/app_shim/apps_page_shim_handler.mm
+++ b/chrome/browser/apps/app_shim/apps_page_shim_handler.mm
@@ -6,6 +6,7 @@
 
 #import "base/mac/foundation_util.h"
 #import "chrome/browser/app_controller_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
@@ -53,15 +54,13 @@
 }  // namespace
 
 void AppsPageShimHandler::OnShimLaunch(
-    apps::AppShimHandler::Host* host,
-    apps::AppShimLaunchType launch_type,
-    const std::vector<base::FilePath>& files) {
+    std::unique_ptr<AppShimHostBootstrap> bootstrap) {
   AppController* controller =
       base::mac::ObjCCastStrict<AppController>([NSApp delegate]);
   OpenAppsPage([controller lastProfile]);
 
   // Always close the shim process immediately.
-  host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_DUPLICATE_HOST);
+  bootstrap->OnLaunchAppFailed(apps::APP_SHIM_LAUNCH_DUPLICATE_HOST);
 }
 
 void AppsPageShimHandler::OnShimClose(apps::AppShimHandler::Host* host) {}
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
index 2a233a1..885161a0 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -8,9 +8,12 @@
 
 #include "apps/app_lifetime_monitor_factory.h"
 #include "apps/launcher.h"
+#include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -58,18 +61,6 @@
 
 typedef AppWindowRegistry::AppWindowList AppWindowList;
 
-void ProfileLoadedCallback(base::Callback<void(Profile*)> callback,
-                           Profile* profile,
-                           Profile::CreateStatus status) {
-  if (status == Profile::CREATE_STATUS_INITIALIZED) {
-    callback.Run(profile);
-    return;
-  }
-
-  // This should never get an error since it only loads existing profiles.
-  DCHECK_EQ(Profile::CREATE_STATUS_CREATED, status);
-}
-
 void SetAppHidden(Profile* profile, const std::string& app_id, bool hidden) {
   AppWindowList windows =
       AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id);
@@ -183,13 +174,10 @@
 
 void ExtensionAppShimHandler::Delegate::LoadProfileAsync(
     const base::FilePath& path,
-    base::Callback<void(Profile*)> callback) {
+    base::OnceCallback<void(Profile*)> callback) {
   ProfileManager* profile_manager = g_browser_process->profile_manager();
   base::FilePath full_path = profile_manager->user_data_dir().Append(path);
-  profile_manager->CreateProfileAsync(
-      full_path,
-      base::Bind(&ProfileLoadedCallback, callback),
-      base::string16(), std::string());
+  profile_manager->LoadProfileByPath(full_path, false, std::move(callback));
 }
 
 bool ExtensionAppShimHandler::Delegate::IsProfileLockedForPath(
@@ -211,6 +199,12 @@
   return ExtensionAppShimHandler::MaybeGetAppExtension(context, extension_id);
 }
 
+AppShimHandler::Host* ExtensionAppShimHandler::Delegate::CreateHost(
+    const std::string& app_id,
+    const base::FilePath& profile_path) {
+  return new AppShimHost(app_id, profile_path);
+}
+
 void ExtensionAppShimHandler::Delegate::EnableExtension(
     Profile* profile,
     const std::string& extension_id,
@@ -418,13 +412,12 @@
 }
 
 void ExtensionAppShimHandler::OnShimLaunch(
-    Host* host,
-    AppShimLaunchType launch_type,
-    const std::vector<base::FilePath>& files) {
-  const std::string& app_id = host->GetAppId();
+    std::unique_ptr<AppShimHostBootstrap> bootstrap) {
+  const std::string& app_id = bootstrap->GetAppId();
+  AppShimLaunchType launch_type = bootstrap->GetLaunchType();
   DCHECK(crx_file::id_util::IdIsValid(app_id));
 
-  const base::FilePath& profile_path = host->GetProfilePath();
+  const base::FilePath& profile_path = bootstrap->GetProfilePath();
   DCHECK(!profile_path.empty());
 
   if (!delegate_->ProfileExistsForPath(profile_path)) {
@@ -432,34 +425,31 @@
     // TODO(jackhou): Add some UI for this case and remove the LOG.
     LOG(ERROR) << "Requested directory is not a known profile '"
                << profile_path.value() << "'.";
-    host->OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND);
+    bootstrap->OnLaunchAppFailed(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND);
     return;
   }
 
   if (delegate_->IsProfileLockedForPath(profile_path)) {
     LOG(WARNING) << "Requested profile is locked.  Showing User Manager.";
-    host->OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_LOCKED);
+    bootstrap->OnLaunchAppFailed(APP_SHIM_LAUNCH_PROFILE_LOCKED);
     delegate_->LaunchUserManager();
     return;
   }
 
   Profile* profile = delegate_->ProfileForPath(profile_path);
-
   if (profile) {
-    OnProfileLoaded(host, launch_type, files, profile);
-    return;
+    OnProfileLoaded(std::move(bootstrap), profile);
+  } else {
+    // If the profile is not loaded, this must have been a launch by the shim.
+    // Load the profile asynchronously, the host will be registered in
+    // OnProfileLoaded.
+    DCHECK_EQ(APP_SHIM_LAUNCH_NORMAL, launch_type);
+    delegate_->LoadProfileAsync(
+        profile_path,
+        base::BindOnce(&ExtensionAppShimHandler::OnProfileLoaded,
+                       weak_factory_.GetWeakPtr(), std::move(bootstrap)));
   }
 
-  // If the profile is not loaded, this must have been a launch by the shim.
-  // Load the profile asynchronously, the host will be registered in
-  // OnProfileLoaded.
-  DCHECK_EQ(APP_SHIM_LAUNCH_NORMAL, launch_type);
-  delegate_->LoadProfileAsync(
-      profile_path,
-      base::Bind(&ExtensionAppShimHandler::OnProfileLoaded,
-                 weak_factory_.GetWeakPtr(),
-                 host, launch_type, files));
-
   // Return now. OnAppLaunchComplete will be called when the app is activated.
 }
 
@@ -503,23 +493,26 @@
 }
 
 void ExtensionAppShimHandler::OnProfileLoaded(
-    Host* host,
-    AppShimLaunchType launch_type,
-    const std::vector<base::FilePath>& files,
+    std::unique_ptr<AppShimHostBootstrap> bootstrap,
     Profile* profile) {
-  const std::string& app_id = host->GetAppId();
+  const std::string& app_id = bootstrap->GetAppId();
+  AppShimLaunchType launch_type = bootstrap->GetLaunchType();
+  const std::vector<base::FilePath>& files = bootstrap->GetLaunchFiles();
 
   // The first host to claim this (profile, app_id) becomes the main host.
   // For any others, focus or relaunch the app.
-  if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) {
+  Host*& host = hosts_[make_pair(profile, app_id)];
+  if (!host) {
+    host = delegate_->CreateHost(app_id, bootstrap->GetProfilePath());
+  } else {
     OnShimFocus(host,
                 launch_type == APP_SHIM_LAUNCH_NORMAL ?
                     APP_SHIM_FOCUS_REOPEN : APP_SHIM_FOCUS_NORMAL,
                 files);
-    host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST);
+    bootstrap->OnLaunchAppFailed(APP_SHIM_LAUNCH_DUPLICATE_HOST);
     return;
   }
-
+  host->OnBootstrapConnected(std::move(bootstrap));
   if (launch_type != APP_SHIM_LAUNCH_NORMAL) {
     host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS);
     return;
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
index f226456..02abbd8e 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "apps/app_lifetime_monitor.h"
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
@@ -52,7 +53,7 @@
     virtual bool ProfileExistsForPath(const base::FilePath& path);
     virtual Profile* ProfileForPath(const base::FilePath& path);
     virtual void LoadProfileAsync(const base::FilePath& path,
-                                  base::Callback<void(Profile*)> callback);
+                                  base::OnceCallback<void(Profile*)> callback);
     virtual bool IsProfileLockedForPath(const base::FilePath& path);
 
     virtual extensions::AppWindowRegistry::AppWindowList GetWindows(
@@ -62,6 +63,8 @@
     virtual const extensions::Extension* MaybeGetAppExtension(
         content::BrowserContext* context,
         const std::string& extension_id);
+    virtual Host* CreateHost(const std::string& app_id,
+                             const base::FilePath& profile_path);
     virtual void EnableExtension(Profile* profile,
                                  const std::string& extension_id,
                                  const base::Callback<void()>& callback);
@@ -119,9 +122,7 @@
   void OnChromeWillHide();
 
   // AppShimHandler overrides:
-  void OnShimLaunch(Host* host,
-                    AppShimLaunchType launch_type,
-                    const std::vector<base::FilePath>& files) override;
+  void OnShimLaunch(std::unique_ptr<AppShimHostBootstrap> bootstrap) override;
   void OnShimClose(Host* host) override;
   void OnShimFocus(Host* host,
                    AppShimFocusType focus_type,
@@ -173,9 +174,7 @@
 
   // This is passed to Delegate::LoadProfileAsync for shim-initiated launches
   // where the profile was not yet loaded.
-  void OnProfileLoaded(Host* host,
-                       AppShimLaunchType launch_type,
-                       const std::vector<base::FilePath>& files,
+  void OnProfileLoaded(std::unique_ptr<AppShimHostBootstrap> bootstrap,
                        Profile* profile);
 
   // This is passed to Delegate::EnableViaPrompt for shim-initiated launches
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
index d57a6cb..ed60fc1 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -4,10 +4,14 @@
 
 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
 
+#include <map>
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
+#include "base/optional.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/test/base/testing_profile.h"
@@ -34,9 +38,10 @@
 
   MOCK_METHOD1(ProfileExistsForPath, bool(const base::FilePath&));
   MOCK_METHOD1(ProfileForPath, Profile*(const base::FilePath&));
-  MOCK_METHOD2(LoadProfileAsync,
-               void(const base::FilePath&,
-                    base::Callback<void(Profile*)>));
+  void LoadProfileAsync(const base::FilePath& path,
+                        base::OnceCallback<void(Profile*)> callback) override {
+    CaptureLoadProfileCallback(path, std::move(callback));
+  }
   MOCK_METHOD1(IsProfileLockedForPath, bool(const base::FilePath&));
 
   MOCK_METHOD2(GetWindows, AppWindowList(Profile*, const std::string&));
@@ -55,16 +60,26 @@
 
   MOCK_METHOD0(MaybeTerminate, void());
 
-  void CaptureLoadProfileCallback(
-      const base::FilePath& path,
-      base::Callback<void(Profile*)> callback) {
-    callbacks_[path] = callback;
+  void SetHostForCreate(AppShimHandler::Host* host_for_create) {
+    host_for_create_ = host_for_create;
+  }
+  AppShimHandler::Host* CreateHost(
+      const std::string& app_id,
+      const base::FilePath& profile_path) override {
+    auto* result = host_for_create_;
+    host_for_create_ = nullptr;
+    return result;
+  }
+
+  void CaptureLoadProfileCallback(const base::FilePath& path,
+                                  base::OnceCallback<void(Profile*)> callback) {
+    callbacks_[path] = std::move(callback);
   }
 
   bool RunLoadProfileCallback(
       const base::FilePath& path,
       Profile* profile) {
-    callbacks_[path].Run(profile);
+    std::move(callbacks_[path]).Run(profile);
     return callbacks_.erase(path);
   }
 
@@ -73,8 +88,8 @@
   }
 
  private:
-  std::map<base::FilePath,
-           base::Callback<void(Profile*)> > callbacks_;
+  std::map<base::FilePath, base::OnceCallback<void(Profile*)>> callbacks_;
+  AppShimHandler::Host* host_for_create_ = nullptr;
 };
 
 class TestingExtensionAppShimHandler : public ExtensionAppShimHandler {
@@ -107,45 +122,53 @@
   DISALLOW_COPY_AND_ASSIGN(TestingExtensionAppShimHandler);
 };
 
+class TestingAppShimHostBootstrap : public AppShimHostBootstrap {
+ public:
+  TestingAppShimHostBootstrap(apps::AppShimHandler* handler)
+      : handler_(handler) {}
+  using AppShimHostBootstrap::LaunchApp;
+  apps::AppShimHandler* GetHandler() override { return handler_; }
+
+ private:
+  apps::AppShimHandler* const handler_;
+  DISALLOW_COPY_AND_ASSIGN(TestingAppShimHostBootstrap);
+};
+
 const char kTestAppIdA[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
 const char kTestAppIdB[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
 
-class FakeHost : public apps::AppShimHandler::Host {
+class TestHost : public AppShimHost {
  public:
-  FakeHost(const base::FilePath& profile_path,
+  TestHost(const base::FilePath& profile_path,
            const std::string& app_id,
+           base::Optional<apps::AppShimLaunchResult>* launch_result,
            TestingExtensionAppShimHandler* handler)
-      : profile_path_(profile_path),
-        app_id_(app_id),
+      : AppShimHost(app_id, profile_path),
+        launch_result_(launch_result),
         handler_(handler),
-        close_count_(0) {}
+        weak_factory_(this) {}
 
-  MOCK_METHOD1(OnAppLaunchComplete, void(AppShimLaunchResult));
+  // Override the GetAppShimHandler for testing.
+  apps::AppShimHandler* GetAppShimHandler() const override { return handler_; }
 
-  void OnAppClosed() override {
-    handler_->OnShimClose(this);
-    ++close_count_;
+  void SetLaunchResult(apps::AppShimLaunchResult result) {
+    launch_result_->emplace(result);
   }
-  void OnAppHide() override {}
-  void OnAppUnhideWithoutActivation() override {}
-  void OnAppRequestUserAttention(AppShimAttentionType type) override {}
-  base::FilePath GetProfilePath() const override {
-    return profile_path_;
+  apps::AppShimLaunchResult GetLaunchResult() {
+    DCHECK(*launch_result_);
+    return *(*launch_result_);
   }
-  std::string GetAppId() const override { return app_id_; }
-  views::BridgeFactoryHost* GetViewsBridgeFactoryHost() const override {
-    return nullptr;
-  }
-
-  int close_count() { return close_count_; }
+  base::WeakPtr<TestHost> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
 
  private:
-  base::FilePath profile_path_;
-  std::string app_id_;
+  ~TestHost() override {}
+  // Note that |launch_result_| is optional so that we can track whether or not
+  // the callback to set it has arrived.
+  base::Optional<apps::AppShimLaunchResult>* launch_result_;
   TestingExtensionAppShimHandler* handler_;
-  int close_count_;
 
-  DISALLOW_COPY_AND_ASSIGN(FakeHost);
+  base::WeakPtrFactory<TestHost> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(TestHost);
 };
 
 class ExtensionAppShimHandlerTest : public testing::Test {
@@ -154,11 +177,21 @@
       : delegate_(new MockDelegate),
         handler_(new TestingExtensionAppShimHandler(delegate_)),
         profile_path_a_("Profile A"),
-        profile_path_b_("Profile B"),
-        host_aa_(profile_path_a_, kTestAppIdA, handler_.get()),
-        host_ab_(profile_path_a_, kTestAppIdB, handler_.get()),
-        host_bb_(profile_path_b_, kTestAppIdB, handler_.get()),
-        host_aa_duplicate_(profile_path_a_, kTestAppIdA, handler_.get()) {
+        profile_path_b_("Profile B") {
+    host_aa_ = (new TestHost(profile_path_a_, kTestAppIdA,
+                             &host_aa_launch_result_, handler_.get()))
+                   ->GetWeakPtr();
+    host_ab_ = (new TestHost(profile_path_a_, kTestAppIdB,
+                             &host_ab_launch_result_, handler_.get()))
+                   ->GetWeakPtr();
+    host_bb_ = (new TestHost(profile_path_b_, kTestAppIdB,
+                             &host_bb_launch_result_, handler_.get()))
+                   ->GetWeakPtr();
+    host_aa_duplicate_ =
+        (new TestHost(profile_path_a_, kTestAppIdA,
+                      &host_aa_duplicate_launch_result_, handler_.get()))
+            ->GetWeakPtr();
+
     base::FilePath extension_path("/fake/path");
     extension_a_ = extensions::ExtensionBuilder("Fake Name")
                        .SetLocation(extensions::Manifest::INTERNAL)
@@ -199,29 +232,56 @@
         .WillRepeatedly(Return());
   }
 
-  void NormalLaunch(AppShimHandler::Host* host) {
-    handler_->OnShimLaunch(host,
-                           APP_SHIM_LAUNCH_NORMAL,
-                           std::vector<base::FilePath>());
+  ~ExtensionAppShimHandlerTest() override {
+    if (host_aa_)
+      host_aa_->OnAppClosed();
+    if (host_ab_)
+      host_ab_->OnAppClosed();
+    if (host_bb_)
+      host_bb_->OnAppClosed();
+    if (host_aa_duplicate_)
+      host_aa_duplicate_->OnAppClosed();
   }
 
-  void RegisterOnlyLaunch(AppShimHandler::Host* host) {
-    handler_->OnShimLaunch(host,
-                           APP_SHIM_LAUNCH_REGISTER_ONLY,
-                           std::vector<base::FilePath>());
+  void DoShimLaunch(TestHost* host,
+                    apps::AppShimLaunchType launch_type,
+                    const std::vector<base::FilePath>& files) {
+    delegate_->SetHostForCreate(host);
+    chrome::mojom::AppShimHostPtr host_ptr;
+    (new TestingAppShimHostBootstrap(handler_.get()))
+        ->LaunchApp(
+            mojo::MakeRequest(&host_ptr), host->GetProfilePath(),
+            host->GetAppId(), launch_type, files,
+            base::BindOnce(&ExtensionAppShimHandlerTest::DoShimLaunchDone,
+                           base::Unretained(this), host));
+  }
+
+  void DoShimLaunchDone(TestHost* host,
+                        apps::AppShimLaunchResult result,
+                        chrome::mojom::AppShimRequest app_shim_request) {
+    host->SetLaunchResult(result);
+  }
+
+  void NormalLaunch(TestHost* host) {
+    DoShimLaunch(host, APP_SHIM_LAUNCH_NORMAL, std::vector<base::FilePath>());
+  }
+
+  void RegisterOnlyLaunch(TestHost* host) {
+    DoShimLaunch(host, APP_SHIM_LAUNCH_REGISTER_ONLY,
+                 std::vector<base::FilePath>());
   }
 
   // Completely launch a shim host and leave it running.
-  void LaunchAndActivate(FakeHost* host, Profile* profile) {
+  void LaunchAndActivate(TestHost* host, Profile* profile) {
     NormalLaunch(host);
     EXPECT_EQ(host, handler_->FindHost(profile, host->GetAppId()));
-    EXPECT_CALL(*host, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS));
     EXPECT_CALL(*handler_, OnShimFocus(host, APP_SHIM_FOCUS_NORMAL, _));
     handler_->OnAppActivated(profile, host->GetAppId());
+    EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, host->GetLaunchResult());
   }
 
   // Simulates a focus request coming from a running app shim.
-  void ShimNormalFocus(FakeHost* host) {
+  void ShimNormalFocus(TestHost* host) {
     EXPECT_CALL(*handler_, OnShimFocus(host, APP_SHIM_FOCUS_NORMAL, _))
         .WillOnce(Invoke(handler_.get(),
                          &TestingExtensionAppShimHandler::RealOnShimFocus));
@@ -231,7 +291,7 @@
   }
 
   // Simulates a hide (or unhide) request coming from a running app shim.
-  void ShimSetHidden(FakeHost* host, bool hidden) {
+  void ShimSetHidden(TestHost* host, bool hidden) {
     handler_->OnShimSetHidden(host, hidden);
   }
 
@@ -242,10 +302,14 @@
   base::FilePath profile_path_b_;
   TestingProfile profile_a_;
   TestingProfile profile_b_;
-  FakeHost host_aa_;
-  FakeHost host_ab_;
-  FakeHost host_bb_;
-  FakeHost host_aa_duplicate_;
+  base::Optional<apps::AppShimLaunchResult> host_aa_launch_result_;
+  base::Optional<apps::AppShimLaunchResult> host_ab_launch_result_;
+  base::Optional<apps::AppShimLaunchResult> host_bb_launch_result_;
+  base::Optional<apps::AppShimLaunchResult> host_aa_duplicate_launch_result_;
+  base::WeakPtr<TestHost> host_aa_;
+  base::WeakPtr<TestHost> host_ab_;
+  base::WeakPtr<TestHost> host_bb_;
+  base::WeakPtr<TestHost> host_aa_duplicate_;
   scoped_refptr<const Extension> extension_a_;
   scoped_refptr<const Extension> extension_b_;
 
@@ -258,17 +322,17 @@
   EXPECT_CALL(*delegate_, ProfileExistsForPath(profile_path_a_))
       .WillOnce(Return(false))
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND));
-  NormalLaunch(&host_aa_);
+  NormalLaunch(host_aa_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND, *host_aa_launch_result_);
 }
 
 TEST_F(ExtensionAppShimHandlerTest, LaunchProfileIsLocked) {
   // Profile is locked.
   EXPECT_CALL(*delegate_, IsProfileLockedForPath(profile_path_a_))
       .WillOnce(Return(true));
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_LOCKED));
   EXPECT_CALL(*delegate_, LaunchUserManager());
-  NormalLaunch(&host_aa_);
+  NormalLaunch(host_aa_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_PROFILE_LOCKED, *host_aa_launch_result_);
 }
 
 TEST_F(ExtensionAppShimHandlerTest, LaunchAppNotFound) {
@@ -277,8 +341,8 @@
       .WillRepeatedly(Return(static_cast<const Extension*>(NULL)));
   EXPECT_CALL(*delegate_, EnableExtension(&profile_a_, kTestAppIdA, _))
       .WillOnce(WithArgs<2>(Invoke(delegate_, &MockDelegate::RunCallback)));
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND));
-  NormalLaunch(&host_aa_);
+  NormalLaunch(host_aa_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_APP_NOT_FOUND, *host_aa_launch_result_);
 }
 
 TEST_F(ExtensionAppShimHandlerTest, LaunchAppNotEnabled) {
@@ -288,48 +352,47 @@
       .WillRepeatedly(Return(extension_a_.get()));
   EXPECT_CALL(*delegate_, EnableExtension(&profile_a_, kTestAppIdA, _))
       .WillOnce(WithArgs<2>(Invoke(delegate_, &MockDelegate::RunCallback)));
-  NormalLaunch(&host_aa_);
+  NormalLaunch(host_aa_.get());
 }
 
 TEST_F(ExtensionAppShimHandlerTest, LaunchAndCloseShim) {
   // Normal startup.
-  NormalLaunch(&host_aa_);
-  EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
+  NormalLaunch(host_aa_.get());
+  EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA));
 
-  NormalLaunch(&host_ab_);
-  EXPECT_EQ(&host_ab_, handler_->FindHost(&profile_a_, kTestAppIdB));
+  NormalLaunch(host_ab_.get());
+  EXPECT_EQ(host_ab_.get(), handler_->FindHost(&profile_a_, kTestAppIdB));
 
   std::vector<base::FilePath> some_file(1, base::FilePath("some_file"));
   EXPECT_CALL(*delegate_,
               LaunchApp(&profile_b_, extension_b_.get(), some_file));
-  handler_->OnShimLaunch(&host_bb_, APP_SHIM_LAUNCH_NORMAL, some_file);
-  EXPECT_EQ(&host_bb_, handler_->FindHost(&profile_b_, kTestAppIdB));
+  DoShimLaunch(host_bb_.get(), APP_SHIM_LAUNCH_NORMAL, some_file);
+  EXPECT_EQ(host_bb_.get(), handler_->FindHost(&profile_b_, kTestAppIdB));
 
   // Activation when there is a registered shim finishes launch with success and
   // focuses the app.
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS));
-  EXPECT_CALL(*handler_, OnShimFocus(&host_aa_, APP_SHIM_FOCUS_NORMAL, _));
+  EXPECT_CALL(*handler_, OnShimFocus(host_aa_.get(), APP_SHIM_FOCUS_NORMAL, _));
   handler_->OnAppActivated(&profile_a_, kTestAppIdA);
+  EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *host_aa_launch_result_);
 
-  // Starting and closing a second host just focuses the app.
-  EXPECT_CALL(*handler_, OnShimFocus(&host_aa_duplicate_,
-                                     APP_SHIM_FOCUS_REOPEN,
-                                     some_file));
-  EXPECT_CALL(host_aa_duplicate_,
-              OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST));
-  handler_->OnShimLaunch(&host_aa_duplicate_,
-                         APP_SHIM_LAUNCH_NORMAL,
-                         some_file);
-  EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
-  handler_->OnShimClose(&host_aa_duplicate_);
-  EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
+  // Starting and closing a second host just focuses the original host of the
+  // app.
+  EXPECT_CALL(*handler_,
+              OnShimFocus(host_aa_.get(), APP_SHIM_FOCUS_REOPEN, some_file));
+
+  DoShimLaunch(host_aa_duplicate_.get(), APP_SHIM_LAUNCH_NORMAL, some_file);
+  EXPECT_EQ(APP_SHIM_LAUNCH_DUPLICATE_HOST, *host_aa_duplicate_launch_result_);
+
+  EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA));
+  handler_->OnShimClose(host_aa_duplicate_.get());
+  EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA));
 
   // Normal close.
-  handler_->OnShimClose(&host_aa_);
+  handler_->OnShimClose(host_aa_.get());
   EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA));
 
   // Closing the second host afterward does nothing.
-  handler_->OnShimClose(&host_aa_duplicate_);
+  handler_->OnShimClose(host_aa_duplicate_.get());
   EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA));
 }
 
@@ -343,9 +406,9 @@
   EXPECT_CALL(*delegate_,
               LaunchApp(&profile_a_, extension_a_.get(), _))
       .Times(0);
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS));
-  RegisterOnlyLaunch(&host_aa_);
-  EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
+  RegisterOnlyLaunch(host_aa_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *host_aa_launch_result_);
+  EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA));
 
   // Return no app windows for OnShimFocus and OnShimQuit.
   AppWindowList app_window_list;
@@ -356,39 +419,40 @@
   EXPECT_CALL(*delegate_,
               LaunchApp(&profile_a_, extension_a_.get(), _))
       .Times(0);
-  ShimNormalFocus(&host_aa_);
+  ShimNormalFocus(host_aa_.get());
 
   // Reopen focus launches the app.
-  EXPECT_CALL(*handler_, OnShimFocus(&host_aa_, APP_SHIM_FOCUS_REOPEN, _))
+  EXPECT_CALL(*handler_, OnShimFocus(host_aa_.get(), APP_SHIM_FOCUS_REOPEN, _))
       .WillOnce(Invoke(handler_.get(),
                        &TestingExtensionAppShimHandler::RealOnShimFocus));
   std::vector<base::FilePath> some_file(1, base::FilePath("some_file"));
   EXPECT_CALL(*delegate_,
               LaunchApp(&profile_a_, extension_a_.get(), some_file));
-  handler_->OnShimFocus(&host_aa_, APP_SHIM_FOCUS_REOPEN, some_file);
+  handler_->OnShimFocus(host_aa_.get(), APP_SHIM_FOCUS_REOPEN, some_file);
 
   // Quit just closes all the windows. This tests that it doesn't terminate,
   // but we expect closing all windows triggers a OnAppDeactivated from
   // AppLifetimeMonitor.
-  handler_->OnShimQuit(&host_aa_);
+  handler_->OnShimQuit(host_aa_.get());
 
   // Closing all windows closes the shim and checks if Chrome should be
   // terminated.
   EXPECT_CALL(*delegate_, MaybeTerminate())
       .WillOnce(Return());
+  EXPECT_NE(nullptr, host_aa_.get());
   handler_->OnAppDeactivated(&profile_a_, kTestAppIdA);
-  EXPECT_EQ(1, host_aa_.close_count());
+  EXPECT_EQ(nullptr, host_aa_.get());
 }
 
 TEST_F(ExtensionAppShimHandlerTest, MaybeTerminate) {
   // Launch shims, adding entries in the map.
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS));
-  RegisterOnlyLaunch(&host_aa_);
-  EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
+  RegisterOnlyLaunch(host_aa_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *host_aa_launch_result_);
+  EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA));
 
-  EXPECT_CALL(host_ab_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS));
-  RegisterOnlyLaunch(&host_ab_);
-  EXPECT_EQ(&host_ab_, handler_->FindHost(&profile_a_, kTestAppIdB));
+  RegisterOnlyLaunch(host_ab_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *host_ab_launch_result_);
+  EXPECT_EQ(host_ab_.get(), handler_->FindHost(&profile_a_, kTestAppIdB));
 
   // Return empty window list.
   AppWindowList app_window_list;
@@ -409,12 +473,12 @@
   // For an APP_SHIM_LAUNCH_REGISTER_ONLY, don't launch the app.
   EXPECT_CALL(*delegate_, LaunchApp(_, _, _))
       .Times(0);
-  EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS));
-  RegisterOnlyLaunch(&host_aa_);
+  RegisterOnlyLaunch(host_aa_.get());
+  EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *host_aa_launch_result_);
   EXPECT_TRUE(handler_->FindHost(&profile_a_, kTestAppIdA));
 
   // Close the shim, removing the entry in the map.
-  handler_->OnShimClose(&host_aa_);
+  handler_->OnShimClose(host_aa_.get());
   EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA));
 }
 
@@ -425,9 +489,7 @@
   EXPECT_CALL(*delegate_, ProfileForPath(profile_path_a_))
       .WillOnce(Return(static_cast<Profile*>(NULL)))
       .WillRepeatedly(Return(&profile_a_));
-  EXPECT_CALL(*delegate_, LoadProfileAsync(profile_path_a_, _))
-      .WillOnce(Invoke(delegate_, &MockDelegate::CaptureLoadProfileCallback));
-  NormalLaunch(&host_aa_);
+  NormalLaunch(host_aa_.get());
   EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA));
   delegate_->RunLoadProfileCallback(profile_path_a_, &profile_a_);
   EXPECT_TRUE(handler_->FindHost(&profile_a_, kTestAppIdA));
@@ -436,15 +498,15 @@
 // Tests that calls to OnShimFocus, OnShimHide correctly handle a null extension
 // being provided by the extension system.
 TEST_F(ExtensionAppShimHandlerTest, ExtensionUninstalled) {
-  LaunchAndActivate(&host_aa_, &profile_a_);
+  LaunchAndActivate(host_aa_.get(), &profile_a_);
 
   // Have GetWindows() return an empty window list for focus (otherwise, it
   // will contain a single nullptr, which can't be focused). Expect 1 call only.
   AppWindowList empty_window_list;
   EXPECT_CALL(*delegate_, GetWindows(_, _)).WillOnce(Return(empty_window_list));
 
-  ShimNormalFocus(&host_aa_);
-  EXPECT_EQ(0, host_aa_.close_count());
+  ShimNormalFocus(host_aa_.get());
+  EXPECT_NE(nullptr, host_aa_.get());
 
   // Set up the mock to return a null extension, as if it were uninstalled.
   EXPECT_CALL(*delegate_, MaybeGetAppExtension(&profile_a_, kTestAppIdA))
@@ -452,18 +514,18 @@
 
   // Now trying to focus should automatically close the shim, and not try to
   // get the window list.
-  ShimNormalFocus(&host_aa_);
-  EXPECT_EQ(1, host_aa_.close_count());
+  ShimNormalFocus(host_aa_.get());
+  EXPECT_EQ(nullptr, host_aa_.get());
 
   // Do the same for SetHidden on host_bb.
-  LaunchAndActivate(&host_bb_, &profile_b_);
-  ShimSetHidden(&host_bb_, true);
-  EXPECT_EQ(0, host_bb_.close_count());
+  LaunchAndActivate(host_bb_.get(), &profile_b_);
+  ShimSetHidden(host_bb_.get(), true);
+  EXPECT_NE(nullptr, host_bb_.get());
 
   EXPECT_CALL(*delegate_, MaybeGetAppExtension(&profile_b_, kTestAppIdB))
       .WillRepeatedly(Return(nullptr));
-  ShimSetHidden(&host_bb_, true);
-  EXPECT_EQ(1, host_bb_.close_count());
+  ShimSetHidden(host_bb_.get(), true);
+  EXPECT_EQ(nullptr, host_bb_.get());
 }
 
 }  // namespace apps
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 56f5ceb..e037ded 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -578,6 +578,8 @@
     "child_accounts/screen_time_controller.h",
     "child_accounts/screen_time_controller_factory.cc",
     "child_accounts/screen_time_controller_factory.h",
+    "child_accounts/time_limit_notifier.cc",
+    "child_accounts/time_limit_notifier.h",
     "child_accounts/usage_time_limit_processor.cc",
     "child_accounts/usage_time_limit_processor.h",
     "chrome_browser_main_chromeos.cc",
@@ -2093,6 +2095,7 @@
     "authpolicy/auth_policy_credentials_manager_unittest.cc",
     "base/file_flusher_unittest.cc",
     "certificate_provider/certificate_provider_service_unittest.cc",
+    "child_accounts/time_limit_notifier_unittest.cc",
     "child_accounts/usage_time_limit_processor_unittest.cc",
     "crostini/crostini_manager_unittest.cc",
     "crostini/crostini_share_path_unittest.cc",
@@ -2212,6 +2215,7 @@
     "login/quick_unlock/pin_storage_prefs_unittest.cc",
     "login/quick_unlock/quick_unlock_storage_unittest.cc",
     "login/saml/saml_offline_signin_limiter_unittest.cc",
+    "login/screens/multidevice_setup_screen_unittest.cc",
     "login/screens/network_screen_unittest.cc",
     "login/screens/update_screen_unittest.cc",
     "login/signin/merge_session_navigation_throttle_unittest.cc",
diff --git a/chrome/browser/chromeos/app_mode/fake_cws.cc b/chrome/browser/chromeos/app_mode/fake_cws.cc
index c8fd127..6b20913 100644
--- a/chrome/browser/chromeos/app_mode/fake_cws.cc
+++ b/chrome/browser/chromeos/app_mode/fake_cws.cc
@@ -12,6 +12,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -114,7 +115,10 @@
       test_data_dir.AppendASCII("chromeos/app_mode/webstore/downloads")
           .AppendASCII(crx_file);
   std::string crx_content;
-  ASSERT_TRUE(base::ReadFileToString(crx_file_path, &crx_content));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::ReadFileToString(crx_file_path, &crx_content));
+  }
 
   const std::string sha256 = crypto::SHA256HashString(crx_content);
   const std::string sha256_hex = base::HexEncode(sha256.c_str(), sha256.size());
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
index 4ede611..bb33950 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -412,7 +413,10 @@
     base::FilePath crx_path;
     std::string crx_version;
     EXPECT_TRUE(GetCachedCrx(id, &crx_path, &crx_version));
-    EXPECT_TRUE(base::PathExists(crx_path));
+    {
+      base::ScopedAllowBlockingForTesting allow_io;
+      EXPECT_TRUE(base::PathExists(crx_path));
+    }
     EXPECT_EQ(expected_version, crx_version);
     // Verify the original crx file is identical to the cached file.
     base::FilePath test_data_dir;
@@ -420,7 +424,10 @@
     std::string src_file_path_str =
         std::string("chromeos/app_mode/webstore/downloads/") + crx_file_name;
     base::FilePath src_file_path = test_data_dir.Append(src_file_path_str);
-    EXPECT_TRUE(base::PathExists(src_file_path));
+    {
+      base::ScopedAllowBlockingForTesting allow_io;
+      EXPECT_TRUE(base::PathExists(src_file_path));
+    }
     EXPECT_TRUE(base::ContentsEqual(src_file_path, crx_path));
 
     CheckAppDataAndCache(id, expected_app_name,
@@ -431,6 +438,8 @@
   // of the copied file.
   base::FilePath CopyFileToTempDir(const base::FilePath& file) {
     base::FilePath target_file = temp_dir_.GetPath().Append(file.BaseName());
+
+    base::ScopedAllowBlockingForTesting allow_io;
     CHECK(base::CopyFile(file, target_file));
     return target_file;
   }
@@ -677,7 +686,10 @@
   base::FilePath crx_path;
   std::string version;
   EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
-  EXPECT_TRUE(base::PathExists(crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(crx_path));
+  }
   EXPECT_EQ("1.0.0", version);
 
   // Remove the app now.
@@ -685,7 +697,10 @@
   content::RunAllTasksUntilIdle();
   manager()->GetApps(&apps);
   ASSERT_EQ(0u, apps.size());
-  EXPECT_FALSE(base::PathExists(crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_FALSE(base::PathExists(crx_path));
+  }
   EXPECT_FALSE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
 }
 
@@ -698,7 +713,10 @@
   base::FilePath crx_path;
   std::string version;
   EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &crx_path, &version));
-  EXPECT_TRUE(base::PathExists(crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(crx_path));
+  }
   EXPECT_EQ("1.0.0", version);
 
   // Update to version 2.
@@ -718,14 +736,20 @@
   std::string new_version;
   EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &new_crx_path, &new_version));
   EXPECT_EQ("2.0.0", new_version);
-  EXPECT_TRUE(base::PathExists(new_crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(new_crx_path));
+  }
   // Get original version 2 source download crx file path.
   base::FilePath test_data_dir;
   base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
   base::FilePath v2_file_path = test_data_dir.Append(FILE_PATH_LITERAL(
       "chromeos/app_mode/webstore/downloads/"
       "bmbpicmpniaclbbpdkfglgipkkebnbjf_v2_read_and_verify_data.crx"));
-  EXPECT_TRUE(base::PathExists(v2_file_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(v2_file_path));
+  }
   EXPECT_TRUE(base::ContentsEqual(v2_file_path, new_crx_path));
 }
 
@@ -738,7 +762,10 @@
   base::FilePath v1_crx_path;
   std::string version;
   EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &v1_crx_path, &version));
-  EXPECT_TRUE(base::PathExists(v1_crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(v1_crx_path));
+  }
   EXPECT_EQ("1.0.0", version);
 
   // Update to version 2.
@@ -759,8 +786,11 @@
   EXPECT_TRUE(GetCachedCrx(kTestLocalFsKioskApp, &v2_crx_path, &new_version));
   EXPECT_EQ("2.0.0", new_version);
   // Verify both v1 and v2 crx files exist.
-  EXPECT_TRUE(base::PathExists(v1_crx_path));
-  EXPECT_TRUE(base::PathExists(v2_crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(v1_crx_path));
+    EXPECT_TRUE(base::PathExists(v2_crx_path));
+  }
 
   // Remove the app now.
   manager()->RemoveApp(kTestLocalFsKioskApp, owner_settings_service_.get());
@@ -768,8 +798,11 @@
   manager()->GetApps(&apps);
   ASSERT_EQ(0u, apps.size());
   // Verify both v1 and v2 crx files are removed.
-  EXPECT_FALSE(base::PathExists(v1_crx_path));
-  EXPECT_FALSE(base::PathExists(v2_crx_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_FALSE(base::PathExists(v1_crx_path));
+    EXPECT_FALSE(base::PathExists(v2_crx_path));
+  }
   EXPECT_FALSE(GetCachedCrx(kTestLocalFsKioskApp, &v2_crx_path, &version));
 }
 
diff --git a/chrome/browser/chromeos/arc/enterprise/arc_cert_store_bridge_browsertest.cc b/chrome/browser/chromeos/arc/enterprise/arc_cert_store_bridge_browsertest.cc
index a0ffc787..5ad6c9c 100644
--- a/chrome/browser/chromeos/arc/enterprise/arc_cert_store_bridge_browsertest.cc
+++ b/chrome/browser/chromeos/arc/enterprise/arc_cert_store_bridge_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/json/json_writer.h"
 #include "base/run_loop.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/arc/arc_service_launcher.h"
 #include "chrome/browser/chromeos/arc/enterprise/arc_cert_store_bridge.h"
 #include "chrome/browser/chromeos/platform_keys/key_permissions.h"
@@ -270,6 +271,7 @@
 
   void SetUpTestClientCerts(const base::Closure& done_callback,
                             net::NSSCertDatabase* cert_db) {
+    base::ScopedAllowBlockingForTesting allow_io;
     net::ImportSensitiveKeyFromFile(net::GetTestCertsDirectory(),
                                     "client_1.pk8",
                                     cert_db->GetPrivateSlot().get());
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
index e38de9b9..f6b3fd1 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
+++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -4,42 +4,24 @@
 
 #include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
 
-#include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "base/optional.h"
 #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h"
 #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service_factory.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/generated_resources.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/browser/browser_context.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/l10n/time_format.h"
-#include "ui/message_center/public/cpp/notification.h"
 
 namespace chromeos {
 
 namespace {
 
-constexpr base::TimeDelta kWarningNotificationTimeout =
-    base::TimeDelta::FromMinutes(5);
-constexpr base::TimeDelta kExitNotificationTimeout =
-    base::TimeDelta::FromMinutes(1);
-
-// The notification id. All the time limit notifications share the same id so
-// that a subsequent notification can replace the previous one.
-constexpr char kTimeLimitNotificationId[] = "time-limit-notification";
-
-// The notifier id representing the app.
-constexpr char kTimeLimitNotifierId[] = "family-link";
-
 // Dictionary keys for prefs::kScreenTimeLastState.
 constexpr char kScreenStateLocked[] = "locked";
 constexpr char kScreenStateCurrentPolicyType[] = "active_policy";
@@ -61,7 +43,8 @@
 
 ScreenTimeController::ScreenTimeController(content::BrowserContext* context)
     : context_(context),
-      pref_service_(Profile::FromBrowserContext(context)->GetPrefs()) {
+      pref_service_(Profile::FromBrowserContext(context)->GetPrefs()),
+      time_limit_notifier_(context) {
   session_manager::SessionManager::Get()->AddObserver(this);
   system::TimezoneSettings::GetInstance()->AddObserver(this);
   pref_change_registrar_.Init(pref_service_);
@@ -114,13 +97,13 @@
       ForceScreenLockByPolicy(state.next_unlock_time);
     }
   } else {
-    base::Optional<TimeLimitNotificationType> notification_type;
+    base::Optional<TimeLimitNotifier::LimitType> notification_type;
     switch (state.next_state_active_policy) {
       case usage_time_limit::ActivePolicies::kFixedLimit:
-        notification_type = kBedTime;
+        notification_type = TimeLimitNotifier::LimitType::kBedTime;
         break;
       case usage_time_limit::ActivePolicies::kUsageLimit:
-        notification_type = kScreenTime;
+        notification_type = TimeLimitNotifier::LimitType::kScreenTime;
         break;
       case usage_time_limit::ActivePolicies::kNoActivePolicy:
       case usage_time_limit::ActivePolicies::kOverride:
@@ -131,21 +114,11 @@
 
     if (notification_type.has_value()) {
       // Schedule notification based on the remaining screen time until lock.
+      // TODO(crbug.com/898000): Dismiss a shown notification when it no longer
+      // applies.
       const base::TimeDelta remaining_time = state.next_state_change_time - now;
-      if (remaining_time >= kWarningNotificationTimeout) {
-        warning_notification_timer_.Start(
-            FROM_HERE, remaining_time - kWarningNotificationTimeout,
-            base::BindRepeating(
-                &ScreenTimeController::ShowNotification, base::Unretained(this),
-                notification_type.value(), kWarningNotificationTimeout));
-      }
-      if (remaining_time >= kExitNotificationTimeout) {
-        exit_notification_timer_.Start(
-            FROM_HERE, remaining_time - kExitNotificationTimeout,
-            base::BindRepeating(
-                &ScreenTimeController::ShowNotification, base::Unretained(this),
-                notification_type.value(), kExitNotificationTimeout));
-      }
+      time_limit_notifier_.MaybeScheduleNotifications(notification_type.value(),
+                                                      remaining_time);
     }
   }
 
@@ -190,32 +163,6 @@
       visible ? next_unlock_time : base::Optional<base::Time>());
 }
 
-void ScreenTimeController::ShowNotification(
-    ScreenTimeController::TimeLimitNotificationType type,
-    const base::TimeDelta& time_remaining) {
-  const base::string16 title = l10n_util::GetStringUTF16(
-      type == kScreenTime ? IDS_SCREEN_TIME_NOTIFICATION_TITLE
-                          : IDS_BED_TIME_NOTIFICATION_TITLE);
-  std::unique_ptr<message_center::Notification> notification =
-      message_center::Notification::CreateSystemNotification(
-          message_center::NOTIFICATION_TYPE_SIMPLE, kTimeLimitNotificationId,
-          title,
-          ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
-                                 ui::TimeFormat::LENGTH_LONG, time_remaining),
-          l10n_util::GetStringUTF16(IDS_TIME_LIMIT_NOTIFICATION_DISPLAY_SOURCE),
-          GURL(),
-          message_center::NotifierId(
-              message_center::NotifierId::SYSTEM_COMPONENT,
-              kTimeLimitNotifierId),
-          message_center::RichNotificationData(),
-          new message_center::NotificationDelegate(),
-          ash::kNotificationSupervisedUserIcon,
-          message_center::SystemNotificationWarningLevel::NORMAL);
-  NotificationDisplayService::GetForProfile(
-      Profile::FromBrowserContext(context_))
-      ->Display(NotificationHandler::Type::TRANSIENT, *notification);
-}
-
 void ScreenTimeController::OnPolicyChanged() {
   CheckTimeLimit("OnPolicyChanged");
 }
@@ -227,8 +174,7 @@
 
 void ScreenTimeController::ResetInSessionTimers() {
   VLOG(1) << "Stopping in-session timers";
-  warning_notification_timer_.Stop();
-  exit_notification_timer_.Stop();
+  time_limit_notifier_.UnscheduleNotifications();
 }
 
 void ScreenTimeController::SaveCurrentStateToPref(
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.h b/chrome/browser/chromeos/child_accounts/screen_time_controller.h
index cea35890..a9f00e1 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.h
+++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.h
@@ -7,6 +7,7 @@
 
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/chromeos/child_accounts/time_limit_notifier.h"
 #include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -40,11 +41,6 @@
   base::TimeDelta GetScreenTimeDuration();
 
  private:
-  // The types of time limit notifications. |SCREEN_TIME| is used when the
-  // the screen time limit is about to be used up, and |BED_TIME| is used when
-  // the bed time is approaching.
-  enum TimeLimitNotificationType { kScreenTime, kBedTime };
-
   // Call time limit processor for new state.
   void CheckTimeLimit(const std::string& source);
 
@@ -62,10 +58,6 @@
   //                     when |visible| is true.
   void UpdateTimeLimitsMessage(bool visible, base::Time next_unlock_time);
 
-  // Show a notification indicating the remaining screen time.
-  void ShowNotification(ScreenTimeController::TimeLimitNotificationType type,
-                        const base::TimeDelta& time_remaining);
-
   // Called when the policy of time limits changes.
   void OnPolicyChanged();
 
@@ -89,14 +81,12 @@
   content::BrowserContext* context_;
   PrefService* pref_service_;
 
-  // Called to show warning and exit notifications.
-  base::OneShotTimer warning_notification_timer_;
-  base::OneShotTimer exit_notification_timer_;
-
-  // Timers that are called when lock screen state change event happens, ie,
-  // bedtime is over or the usage limit ends.
+  // Timer scheduled for when the next lock screen state change event is
+  // expected to happen, e.g. when bedtime is over or the usage limit ends.
   base::OneShotTimer next_state_timer_;
-  base::OneShotTimer reset_screen_time_timer_;
+
+  // Used to set up timers when a time limit is approaching.
+  TimeLimitNotifier time_limit_notifier_;
 
   PrefChangeRegistrar pref_change_registrar_;
 
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc b/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc
new file mode 100644
index 0000000..377b9b9
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc
@@ -0,0 +1,107 @@
+// 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/chromeos/child_accounts/time_limit_notifier.h"
+
+#include <memory>
+
+#include "ash/public/cpp/vector_icons/vector_icons.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/notifications/notification_display_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_context.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/time_format.h"
+#include "ui/message_center/public/cpp/notification.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+
+namespace {
+
+constexpr base::TimeDelta kWarningNotificationTimeout =
+    base::TimeDelta::FromMinutes(5);
+constexpr base::TimeDelta kExitNotificationTimeout =
+    base::TimeDelta::FromMinutes(1);
+
+// The notification id. All the time limit notifications share the same id so
+// that a subsequent notification can replace the previous one.
+constexpr char kTimeLimitNotificationId[] = "time-limit-notification";
+
+// The notifier id representing the app.
+constexpr char kTimeLimitNotifierId[] = "family-link";
+
+void ShowNotification(TimeLimitNotifier::LimitType limit_type,
+                      base::TimeDelta time_remaining,
+                      content::BrowserContext* context) {
+  const base::string16 title = l10n_util::GetStringUTF16(
+      limit_type == TimeLimitNotifier::LimitType::kScreenTime
+          ? IDS_SCREEN_TIME_NOTIFICATION_TITLE
+          : IDS_BED_TIME_NOTIFICATION_TITLE);
+  std::unique_ptr<message_center::Notification> notification =
+      message_center::Notification::CreateSystemNotification(
+          message_center::NOTIFICATION_TYPE_SIMPLE, kTimeLimitNotificationId,
+          title,
+          ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
+                                 ui::TimeFormat::LENGTH_LONG, time_remaining),
+          l10n_util::GetStringUTF16(IDS_TIME_LIMIT_NOTIFICATION_DISPLAY_SOURCE),
+          GURL(),
+          message_center::NotifierId(
+              message_center::NotifierId::SYSTEM_COMPONENT,
+              kTimeLimitNotifierId),
+          message_center::RichNotificationData(),
+          base::MakeRefCounted<message_center::NotificationDelegate>(),
+          ash::kNotificationSupervisedUserIcon,
+          message_center::SystemNotificationWarningLevel::NORMAL);
+  NotificationDisplayService::GetForProfile(
+      Profile::FromBrowserContext(context))
+      ->Display(NotificationHandler::Type::TRANSIENT, *notification);
+}
+
+}  // namespace
+
+TimeLimitNotifier::TimeLimitNotifier(content::BrowserContext* context)
+    : TimeLimitNotifier(context, nullptr /* task_runner */) {}
+
+TimeLimitNotifier::~TimeLimitNotifier() = default;
+
+void TimeLimitNotifier::MaybeScheduleNotifications(
+    LimitType limit_type,
+    base::TimeDelta remaining_time) {
+  // Stop any previously set timers.
+  UnscheduleNotifications();
+
+  if (remaining_time >= kWarningNotificationTimeout) {
+    warning_notification_timer_.Start(
+        FROM_HERE, remaining_time - kWarningNotificationTimeout,
+        base::BindOnce(&ShowNotification, limit_type,
+                       kWarningNotificationTimeout, context_));
+  }
+  if (remaining_time >= kExitNotificationTimeout) {
+    exit_notification_timer_.Start(
+        FROM_HERE, remaining_time - kExitNotificationTimeout,
+        base::BindOnce(&ShowNotification, limit_type, kExitNotificationTimeout,
+                       context_));
+  }
+}
+
+void TimeLimitNotifier::UnscheduleNotifications() {
+  // TODO(crbug.com/897975): Stop() should be sufficient, but doesn't have the
+  // expected effect in tests.
+  warning_notification_timer_.AbandonAndStop();
+  exit_notification_timer_.AbandonAndStop();
+}
+
+TimeLimitNotifier::TimeLimitNotifier(
+    content::BrowserContext* context,
+    scoped_refptr<base::SequencedTaskRunner> task_runner)
+    : context_(context) {
+  if (task_runner.get()) {
+    warning_notification_timer_.SetTaskRunner(task_runner);
+    exit_notification_timer_.SetTaskRunner(task_runner);
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier.h b/chrome/browser/chromeos/child_accounts/time_limit_notifier.h
new file mode 100644
index 0000000..cde75c2d
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_notifier.h
@@ -0,0 +1,59 @@
+// 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 CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
+#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace chromeos {
+
+// Schedules warning notifications for screen time usage or bed time limits.
+class TimeLimitNotifier {
+ public:
+  // The types of time limits to notify for. kScreenTime is used when the
+  // the screen time limit is about to be used up, and kBedTime is used when
+  // the bed time is approaching.
+  enum class LimitType { kScreenTime, kBedTime };
+
+  explicit TimeLimitNotifier(content::BrowserContext* context);
+  ~TimeLimitNotifier();
+
+  // Schedules warning and/or exit notifications based on the time remaining.
+  void MaybeScheduleNotifications(LimitType limit_type,
+                                  base::TimeDelta remaining_time);
+
+  // Cancels any scheduled notification timers.
+  void UnscheduleNotifications();
+
+ private:
+  friend class TimeLimitNotifierTest;
+
+  // For tests, sets up the notification timers using the given task runner.
+  TimeLimitNotifier(content::BrowserContext* context,
+                    scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+  content::BrowserContext* const context_;
+
+  // Called to show warning and exit notifications.
+  base::OneShotTimer warning_notification_timer_;
+  base::OneShotTimer exit_notification_timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimeLimitNotifier);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_NOTIFIER_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier_unittest.cc b/chrome/browser/chromeos/child_accounts/time_limit_notifier_unittest.cc
new file mode 100644
index 0000000..2b201790
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limit_notifier_unittest.cc
@@ -0,0 +1,150 @@
+// 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/chromeos/child_accounts/time_limit_notifier.h"
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/time/time.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+class TimeLimitNotifierTest : public testing::Test {
+ public:
+  TimeLimitNotifierTest()
+      : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()),
+        notification_tester_(&profile_),
+        notifier_(&profile_, task_runner_) {}
+  ~TimeLimitNotifierTest() override = default;
+
+ protected:
+  bool HasNotification() {
+    return notification_tester_.GetNotification("time-limit-notification")
+        .has_value();
+  }
+
+  void RemoveNotification() {
+    notification_tester_.RemoveAllNotifications(
+        NotificationHandler::Type::TRANSIENT, true /* by_user */);
+  }
+
+  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+  content::TestBrowserThreadBundle bundle_;
+  TestingProfile profile_;
+  NotificationDisplayServiceTester notification_tester_;
+  TimeLimitNotifier notifier_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TimeLimitNotifierTest);
+};
+
+TEST_F(TimeLimitNotifierTest, ShowNotifications) {
+  notifier_.MaybeScheduleNotifications(
+      TimeLimitNotifier::LimitType::kScreenTime,
+      base::TimeDelta::FromMinutes(20));
+
+  // Fast forward a bit, but not far enough to show a notification.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(10));
+  EXPECT_FALSE(HasNotification());
+
+  // Fast forward to the 5-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(5));
+  EXPECT_TRUE(HasNotification());
+
+  // Fast forward to the 1-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(4));
+  EXPECT_TRUE(HasNotification());
+}
+
+TEST_F(TimeLimitNotifierTest, DismissNotification) {
+  notifier_.MaybeScheduleNotifications(TimeLimitNotifier::LimitType::kBedTime,
+                                       base::TimeDelta::FromMinutes(10));
+
+  // Fast forward to the 5-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(5));
+  EXPECT_TRUE(HasNotification());
+  RemoveNotification();
+
+  // Fast forward one minute; the same notification is not reshown.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(1));
+  EXPECT_FALSE(HasNotification());
+
+  // Fast forward to the 1-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(3));
+  EXPECT_TRUE(HasNotification());
+}
+
+TEST_F(TimeLimitNotifierTest, OnlyExitNotification) {
+  notifier_.MaybeScheduleNotifications(
+      TimeLimitNotifier::LimitType::kScreenTime,
+      base::TimeDelta::FromMinutes(3));
+
+  // Fast forward a bit, but not far enough to show a notification.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(1));
+  EXPECT_FALSE(HasNotification());
+
+  // Fast forward to the 1-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(1));
+  EXPECT_TRUE(HasNotification());
+  RemoveNotification();
+
+  // Only one notification was shown.
+  task_runner_->FastForwardUntilNoTasksRemain();
+  EXPECT_FALSE(HasNotification());
+}
+
+TEST_F(TimeLimitNotifierTest, NoNotifications) {
+  notifier_.MaybeScheduleNotifications(TimeLimitNotifier::LimitType::kBedTime,
+                                       base::TimeDelta::FromSeconds(30));
+
+  task_runner_->FastForwardUntilNoTasksRemain();
+  EXPECT_FALSE(HasNotification());
+}
+
+TEST_F(TimeLimitNotifierTest, UnscheduleNotifications) {
+  notifier_.MaybeScheduleNotifications(
+      TimeLimitNotifier::LimitType::kScreenTime,
+      base::TimeDelta::FromMinutes(10));
+
+  // Fast forward to the 5-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(5));
+  EXPECT_TRUE(HasNotification());
+  RemoveNotification();
+
+  // Stop the timers.
+  notifier_.UnscheduleNotifications();
+  task_runner_->FastForwardUntilNoTasksRemain();
+  EXPECT_FALSE(HasNotification());
+}
+
+TEST_F(TimeLimitNotifierTest, RescheduleNotifications) {
+  notifier_.MaybeScheduleNotifications(
+      TimeLimitNotifier::LimitType::kScreenTime,
+      base::TimeDelta::FromMinutes(20));
+
+  // Update the notifier with a new limit.
+  notifier_.MaybeScheduleNotifications(
+      TimeLimitNotifier::LimitType::kScreenTime,
+      base::TimeDelta::FromMinutes(30));
+
+  // Fast forward a bit, but not far enough to show a notification.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(20));
+  EXPECT_FALSE(HasNotification());
+
+  // Fast forward to the 5-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(5));
+  EXPECT_TRUE(HasNotification());
+  RemoveNotification();
+
+  // Fast forward to the 1-minute warning time.
+  task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(4));
+  EXPECT_TRUE(HasNotification());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path.cc b/chrome/browser/chromeos/crostini/crostini_share_path.cc
index 0432f3c..d3e06a6c 100644
--- a/chrome/browser/chromeos/crostini/crostini_share_path.cc
+++ b/chrome/browser/chromeos/crostini/crostini_share_path.cc
@@ -37,6 +37,26 @@
                           response.value().failure_reason());
 }
 
+void OnVmRestartedForSeneschal(
+    Profile* profile,
+    std::string vm_name,
+    const base::FilePath path,
+    base::OnceCallback<void(bool, std::string)> callback,
+    vm_tools::seneschal::SharePathRequest request,
+    crostini::CrostiniResult result) {
+  auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile);
+  base::Optional<vm_tools::concierge::VmInfo> vm_info =
+      crostini_manager->GetVmInfo(std::move(vm_name));
+  if (!vm_info) {
+    std::move(callback).Run(false, "VM could not be started");
+    return;
+  }
+  request.set_handle(vm_info->seneschal_server_handle());
+  chromeos::DBusThreadManager::Get()->GetSeneschalClient()->SharePath(
+      request, base::BindOnce(&OnSeneschalSharePathResponse, std::move(path),
+                              std::move(callback)));
+}
+
 void CallSeneschalSharePath(
     Profile* profile,
     std::string vm_name,
@@ -129,19 +149,23 @@
     shared_paths->Append(std::make_unique<base::Value>(path.value()));
   }
 
-  // VM must be running.
-  // TODO(joelhockey): Start VM if not currently running.
+  request.mutable_shared_path()->set_path(relative_path.value());
+  request.mutable_shared_path()->set_writable(true);
+
+  // Restart VM if not currently running.
+  auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile);
   base::Optional<vm_tools::concierge::VmInfo> vm_info =
-      crostini::CrostiniManager::GetForProfile(profile)->GetVmInfo(
-          std::move(vm_name));
+      crostini_manager->GetVmInfo(vm_name);
   if (!vm_info) {
-    std::move(callback).Run(false, "VM not running");
+    crostini_manager->RestartCrostini(
+        vm_name, crostini::kCrostiniDefaultContainerName,
+        base::BindOnce(&OnVmRestartedForSeneschal, profile, std::move(vm_name),
+                       std::move(path), std::move(callback),
+                       std::move(request)));
     return;
   }
 
   request.set_handle(vm_info->seneschal_server_handle());
-  request.mutable_shared_path()->set_path(relative_path.value());
-  request.mutable_shared_path()->set_writable(true);
   chromeos::DBusThreadManager::Get()->GetSeneschalClient()->SharePath(
       request, base::BindOnce(&OnSeneschalSharePathResponse, std::move(path),
                               std::move(callback)));
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
index 0d6b0d9..ab7f17d4 100644
--- a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
-#include "base/sys_info.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
@@ -30,49 +29,28 @@
 
 namespace crostini {
 
-const char kLsbRelease[] =
-    "CHROMEOS_RELEASE_NAME=Chrome OS\n"
-    "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
-
 class CrostiniSharePathTest : public testing::Test {
  public:
-  void SharePathSuccessStartTerminaVmCallback(CrostiniResult result) {
-    EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
-    EXPECT_EQ(result, CrostiniResult::SUCCESS);
-
-    SharePath(profile(), "success", share_path_, true,
-              base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                             base::Unretained(this), true, true,
-                             &vm_tools::seneschal::SharePathRequest::DOWNLOADS,
-                             "path", true, "", run_loop()->QuitClosure()));
-  }
-
-  void SharePathErrorSeneschalStartTerminaVmCallback(CrostiniResult result) {
-    EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
-    EXPECT_EQ(result, CrostiniResult::SUCCESS);
-
-    SharePath(profile(), "error-seneschal", share_path_, true,
-              base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                             base::Unretained(this), true, true,
-                             &vm_tools::seneschal::SharePathRequest::DOWNLOADS,
-                             "path", false, "test failure",
-                             run_loop()->QuitClosure()));
-  }
+  const bool PERSIST_YES = true;
+  const bool PERSIST_NO = false;
+  enum class Persist { NO, YES };
+  enum class SeneschalClientCalled { NO, YES };
+  enum class Success { NO, YES };
 
   void SharePathCallback(
-      bool expected_persist,
-      bool expected_seneschal_client_called,
+      Persist expected_persist,
+      SeneschalClientCalled expected_seneschal_client_called,
       const vm_tools::seneschal::SharePathRequest::StorageLocation*
           expected_seneschal_storage_location,
       std::string expected_seneschal_path,
-      bool expected_success,
+      Success expected_success,
       std::string expected_failure_reason,
       base::OnceClosure closure,
       bool success,
       std::string failure_reason) {
     const base::ListValue* prefs =
         profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths);
-    if (expected_persist) {
+    if (expected_persist == Persist::YES) {
       EXPECT_EQ(prefs->GetSize(), 1U);
       std::string share_path;
       prefs->GetString(0, &share_path);
@@ -81,14 +59,14 @@
       EXPECT_EQ(prefs->GetSize(), 0U);
     }
     EXPECT_EQ(fake_seneschal_client_->share_path_called(),
-              expected_seneschal_client_called);
-    if (expected_seneschal_client_called) {
+              expected_seneschal_client_called == SeneschalClientCalled::YES);
+    if (expected_seneschal_client_called == SeneschalClientCalled::YES) {
       EXPECT_EQ(fake_seneschal_client_->last_request().storage_location(),
                 *expected_seneschal_storage_location);
       EXPECT_EQ(fake_seneschal_client_->last_request().shared_path().path(),
                 expected_seneschal_path);
     }
-    EXPECT_EQ(success, expected_success);
+    EXPECT_EQ(success, expected_success == Success::YES);
     EXPECT_EQ(failure_reason, expected_failure_reason);
     std::move(closure).Run();
   }
@@ -131,13 +109,6 @@
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         chromeos::switches::kCrostiniFiles);
 
-    // Fake that this is a real ChromeOS system in order to use TestingProfile
-    // /tmp path for Downloads rather than the current Linux user $HOME.
-    // SetChromeOSVersionInfoForTest() must not be called until D-Bus is
-    // initialized with fake clients, and then it must be cleared in TearDown()
-    // before D-Bus is re-initialized for the next test.
-    base::SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, base::Time());
-
     // Setup for DriveFS.
     features_.InitAndEnableFeature(chromeos::features::kDriveFs);
     user_manager.AddUser(AccountId::FromUserEmailGaiaId(
@@ -161,9 +132,6 @@
   void TearDown() override {
     run_loop_.reset();
     profile_.reset();
-    // Clear SetChromeOSVersionInfoForTest() so D-Bus will use fake clients
-    // again in the next test.
-    base::SysInfo::SetChromeOSVersionInfoForTest("", base::Time());
   }
 
  protected:
@@ -189,114 +157,117 @@
   DISALLOW_COPY_AND_ASSIGN(CrostiniSharePathTest);
 };
 
-TEST_F(CrostiniSharePathTest, Success) {
-  vm_tools::concierge::StartVmResponse start_vm_response;
-  start_vm_response.set_status(vm_tools::concierge::VM_STATUS_RUNNING);
-  start_vm_response.mutable_vm_info()->set_seneschal_server_handle(123);
-  fake_concierge_client_->set_start_vm_response(start_vm_response);
-
-  CrostiniManager::GetForProfile(profile())->StartTerminaVm(
-      "success", share_path_,
-      base::BindOnce(
-          &CrostiniSharePathTest::SharePathSuccessStartTerminaVmCallback,
-          base::Unretained(this)));
-  run_loop()->Run();
-}
-
 TEST_F(CrostiniSharePathTest, SuccessDownloadsRoot) {
-  SharePath(profile(), "vm-running", downloads_, false,
+  SharePath(profile(), "vm-running", downloads_, PERSIST_NO,
             base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                           base::Unretained(this), false, true,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::YES,
                            &vm_tools::seneschal::SharePathRequest::DOWNLOADS,
-                           "", true, "", run_loop()->QuitClosure()));
+                           "", Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SuccessNoPersist) {
-  SharePath(profile(), "vm-running", share_path_, false,
-            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                           base::Unretained(this), false, true,
-                           &vm_tools::seneschal::SharePathRequest::DOWNLOADS,
-                           "path", true, "", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", share_path_, PERSIST_NO,
+            base::BindOnce(
+                &CrostiniSharePathTest::SharePathCallback,
+                base::Unretained(this), Persist::NO, SeneschalClientCalled::YES,
+                &vm_tools::seneschal::SharePathRequest::DOWNLOADS, "path",
+                Success::YES, "", run_loop()->QuitClosure()));
+  run_loop()->Run();
+}
+
+TEST_F(CrostiniSharePathTest, SuccessPersist) {
+  SharePath(
+      profile(), "vm-running", share_path_, PERSIST_YES,
+      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                     base::Unretained(this), Persist::YES,
+                     SeneschalClientCalled::YES,
+                     &vm_tools::seneschal::SharePathRequest::DOWNLOADS, "path",
+                     Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SuccessDriveFsMyDrive) {
-  SharePath(
-      profile(), "vm-running", drivefs_.Append("root").Append("my"), false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, true,
-                     &vm_tools::seneschal::SharePathRequest::DRIVEFS_MY_DRIVE,
-                     "my", true, "", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", drivefs_.Append("root").Append("my"),
+            PERSIST_NO,
+            base::BindOnce(
+                &CrostiniSharePathTest::SharePathCallback,
+                base::Unretained(this), Persist::NO, SeneschalClientCalled::YES,
+                &vm_tools::seneschal::SharePathRequest::DRIVEFS_MY_DRIVE, "my",
+                Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SuccessDriveFsMyDriveRoot) {
-  SharePath(
-      profile(), "vm-running", drivefs_.Append("root"), false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, true,
-                     &vm_tools::seneschal::SharePathRequest::DRIVEFS_MY_DRIVE,
-                     "", true, "", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", drivefs_.Append("root"), PERSIST_NO,
+            base::BindOnce(
+                &CrostiniSharePathTest::SharePathCallback,
+                base::Unretained(this), Persist::NO, SeneschalClientCalled::YES,
+                &vm_tools::seneschal::SharePathRequest::DRIVEFS_MY_DRIVE, "",
+                Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, FailDriveFsRoot) {
-  SharePath(
-      profile(), "vm-running", drivefs_, false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, false, nullptr, "", false,
-                     "Path is not allowed", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", drivefs_, PERSIST_NO,
+            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                           "Path is not allowed", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SuccessDriveFsTeamDrives) {
   SharePath(profile(), "vm-running",
-            drivefs_.Append("team_drives").Append("team"), false,
+            drivefs_.Append("team_drives").Append("team"), PERSIST_NO,
             base::BindOnce(
                 &CrostiniSharePathTest::SharePathCallback,
-                base::Unretained(this), false, true,
+                base::Unretained(this), Persist::NO, SeneschalClientCalled::YES,
                 &vm_tools::seneschal::SharePathRequest::DRIVEFS_TEAM_DRIVES,
-                "team", true, "", run_loop()->QuitClosure()));
+                "team", Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SuccessDriveFsComputers) {
-  SharePath(
-      profile(), "vm-running", drivefs_.Append("Computers").Append("pc"), false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, true,
-                     &vm_tools::seneschal::SharePathRequest::DRIVEFS_COMPUTERS,
-                     "pc", true, "", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", drivefs_.Append("Computers").Append("pc"),
+            PERSIST_NO,
+            base::BindOnce(
+                &CrostiniSharePathTest::SharePathCallback,
+                base::Unretained(this), Persist::NO, SeneschalClientCalled::YES,
+                &vm_tools::seneschal::SharePathRequest::DRIVEFS_COMPUTERS, "pc",
+                Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, FailDriveFsTrash) {
-  SharePath(
-      profile(), "vm-running", drivefs_.Append(".Trash").Append("in-the-trash"),
-      false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, false, nullptr, "", false,
-                     "Path is not allowed", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running",
+            drivefs_.Append(".Trash").Append("in-the-trash"), PERSIST_NO,
+            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                           "Path is not allowed", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SuccessRemovable) {
   SharePath(profile(), "vm-running", base::FilePath("/media/removable/MyUSB"),
-            false,
-            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                           base::Unretained(this), false, true,
-                           &vm_tools::seneschal::SharePathRequest::REMOVABLE,
-                           "MyUSB", true, "", run_loop()->QuitClosure()));
+            PERSIST_NO,
+            base::BindOnce(
+                &CrostiniSharePathTest::SharePathCallback,
+                base::Unretained(this), Persist::NO, SeneschalClientCalled::YES,
+                &vm_tools::seneschal::SharePathRequest::REMOVABLE, "MyUSB",
+                Success::YES, "", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, FailRemovableRoot) {
-  SharePath(
-      profile(), "vm-running", base::FilePath("/media/removable"), false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, false, nullptr, "", false,
-                     "Path is not allowed", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", base::FilePath("/media/removable"),
+            PERSIST_NO,
+            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                           "Path is not allowed", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
@@ -311,49 +282,68 @@
   share_path_response.set_failure_reason("test failure");
   fake_seneschal_client_->set_share_path_response(share_path_response);
 
-  CrostiniManager::GetForProfile(profile())->StartTerminaVm(
-      "error-seneschal", share_path_,
-      base::BindOnce(
-          &CrostiniSharePathTest::SharePathErrorSeneschalStartTerminaVmCallback,
-          base::Unretained(this)));
+  SharePath(
+      profile(), "error-seneschal", share_path_, PERSIST_YES,
+      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                     base::Unretained(this), Persist::YES,
+                     SeneschalClientCalled::YES,
+                     &vm_tools::seneschal::SharePathRequest::DOWNLOADS, "path",
+                     Success::NO, "test failure", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SharePathErrorPathNotAbsolute) {
   const base::FilePath path("not/absolute/dir");
-  SharePath(
-      profile(), "vm-running", path, true,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, false, nullptr, "", false,
-                     "Path must be absolute", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", path, PERSIST_YES,
+            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                           "Path must be absolute", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SharePathErrorReferencesParent) {
   const base::FilePath path("/path/../references/parent");
-  SharePath(
-      profile(), "vm-running", path, false,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, false, nullptr, "", false,
-                     "Path must be absolute", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", path, PERSIST_NO,
+            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                           "Path must be absolute", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
 TEST_F(CrostiniSharePathTest, SharePathErrorNotUnderDownloads) {
   const base::FilePath path("/not/under/downloads");
-  SharePath(
-      profile(), "vm-running", path, true,
-      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                     base::Unretained(this), false, false, nullptr, "", false,
-                     "Path is not allowed", run_loop()->QuitClosure()));
+  SharePath(profile(), "vm-running", path, PERSIST_YES,
+            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                           base::Unretained(this), Persist::NO,
+                           SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                           "Path is not allowed", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
-TEST_F(CrostiniSharePathTest, SharePathErrorVmNotRunning) {
-  SharePath(profile(), "error-vm-not-running", share_path_, true,
-            base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
-                           base::Unretained(this), true, false, nullptr, "",
-                           false, "VM not running", run_loop()->QuitClosure()));
+TEST_F(CrostiniSharePathTest, SharePathVmToBeRestarted) {
+  SharePath(
+      profile(), "vm-to-be-started", share_path_, PERSIST_YES,
+      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                     base::Unretained(this), Persist::YES,
+                     SeneschalClientCalled::YES,
+                     &vm_tools::seneschal::SharePathRequest::DOWNLOADS, "path",
+                     Success::YES, "", run_loop()->QuitClosure()));
+  run_loop()->Run();
+}
+
+TEST_F(CrostiniSharePathTest, SharePathErrorVmCouldNotBeStarted) {
+  vm_tools::concierge::StartVmResponse start_vm_response;
+  start_vm_response.set_status(vm_tools::concierge::VM_STATUS_FAILURE);
+  fake_concierge_client_->set_start_vm_response(start_vm_response);
+
+  SharePath(
+      profile(), "error-vm-could-not-be-started", share_path_, PERSIST_YES,
+      base::BindOnce(&CrostiniSharePathTest::SharePathCallback,
+                     base::Unretained(this), Persist::YES,
+                     SeneschalClientCalled::NO, nullptr, "", Success::NO,
+                     "VM could not be started", run_loop()->QuitClosure()));
   run_loop()->Run();
 }
 
diff --git a/chrome/browser/chromeos/display/quirks_browsertest.cc b/chrome/browser/chromeos/display/quirks_browsertest.cc
index 86d214d..8ba7f08 100644
--- a/chrome/browser/chromeos/display/quirks_browsertest.cc
+++ b/chrome/browser/chromeos/display/quirks_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/quirks/quirks_manager.h"
 #include "content/public/test/test_utils.h"
@@ -111,10 +112,13 @@
   base::FilePath path = GetPathForIccFile(0x0000aaaa);
   EXPECT_EQ(icc_path_, path);
   EXPECT_EQ(file_existed_, false);
-  EXPECT_TRUE(base::PathExists(path));
-  char data[32];
-  ReadFile(path, data, sizeof(data));
-  EXPECT_EQ(0, memcmp(data, kFakeIccData, sizeof(kFakeIccData)));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(path));
+    char data[32];
+    ReadFile(path, data, sizeof(data));
+    EXPECT_EQ(0, memcmp(data, kFakeIccData, sizeof(kFakeIccData)));
+  }
 
   // Retest same file, this time expect it to already exist.
   TestQuirksClient(0x0000aaaa, true);
@@ -125,7 +129,10 @@
   TestQuirksClient(0x1111bbbb, false);
   EXPECT_EQ(icc_path_, base::FilePath());
   EXPECT_EQ(file_existed_, false);
-  EXPECT_FALSE(base::PathExists(GetPathForIccFile(0x1111bbbb)));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_FALSE(base::PathExists(GetPathForIccFile(0x1111bbbb)));
+  }
 }
 
 }  // namespace quirks
diff --git a/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc b/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
index 929ea53..1c87847 100644
--- a/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
+++ b/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/threading/thread_restrictions.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"
@@ -110,7 +111,10 @@
     const base::FilePath& file) {
   base::FilePath path = ui_test_utils::GetTestFilePath(dir, file);
   std::string library_content;
-  ASSERT_TRUE(base::ReadFileToString(path, &library_content)) << path.value();
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::ReadFileToString(path, &library_content)) << path.value();
+  }
   utf8_content_.append(library_content);
   utf8_content_.append(";\n");
 }
@@ -170,7 +174,10 @@
       base::FilePath(kVirtualKeyboardExtensionTestDir),
       base::FilePath(FILE_PATH_LITERAL("end_to_end_test.js")));
   std::string script;
-  ASSERT_TRUE(base::ReadFileToString(path, &script));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::ReadFileToString(path, &script));
+  }
   EXPECT_TRUE(content::ExecuteScript(keyboard_wc, script));
   // Verify 'a' appeared on test page.
   bool success = false;
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
index 82126aa..b3e41b3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
@@ -266,7 +266,10 @@
       FileBrowserHandlerExtensionTest::TestSelectFileFunctionFactory));
 
   // Selected path should still not exist.
-  ASSERT_FALSE(base::PathExists(selected_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_FALSE(base::PathExists(selected_path));
+  }
 
   const Extension* extension = LoadExtension(
       test_data_dir_.AppendASCII("file_browser/filehandler_create"));
@@ -283,7 +286,10 @@
 
   // Selected path should have been created by the test extension after the
   // extension function call.
-  ASSERT_TRUE(base::PathExists(selected_path));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::PathExists(selected_path));
+  }
 
   // Let's check that the file has the expected content.
   const std::string kExpectedContents = "hello from test extension.";
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
index 44df503f..ae034452 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -166,10 +166,13 @@
   const char kLocalMountPointName[] = "local";
   const char kTestFileContent[] = "The five boxing wizards jumped quickly";
 
-  ASSERT_TRUE(base::CreateDirectory(root.AppendASCII("test_dir")));
-  ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
-      root.AppendASCII("test_dir").AppendASCII("test_file.txt"),
-      kTestFileContent));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::CreateDirectory(root.AppendASCII("test_dir")));
+    ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
+        root.AppendASCII("test_dir").AppendASCII("test_file.txt"),
+        kTestFileContent));
+  }
 
   ASSERT_TRUE(
       content::BrowserContext::GetMountPoints(profile)->RegisterFileSystem(
@@ -200,6 +203,7 @@
 
   void SetUpOnMainThread() override {
     extensions::ExtensionApiTest::SetUpOnMainThread();
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 
     testing_profile_ = std::make_unique<TestingProfile>();
     event_router_ =
@@ -385,6 +389,7 @@
         .WillOnce(Invoke(this, &FileManagerPrivateApiTest::SshfsMount));
   }
 
+  base::ScopedTempDir temp_dir_;
   chromeos::disks::MockDiskMountManager* disk_mount_manager_mock_;
   DiskMountManager::DiskMap volumes_;
   DiskMountManager::MountPointMap mount_points_;
@@ -520,23 +525,20 @@
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, ContentChecksum) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  AddLocalFileSystem(browser()->profile(), temp_dir.GetPath());
+  AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
 
   ASSERT_TRUE(RunComponentExtensionTest("file_browser/content_checksum_test"));
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Recent) {
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath downloads_dir = temp_dir.GetPath();
+  const base::FilePath downloads_dir = temp_dir_.GetPath();
 
   ASSERT_TRUE(file_manager::VolumeManager::Get(browser()->profile())
                   ->RegisterDownloadsDirectoryForTesting(downloads_dir));
 
   // Create an empty file.
   {
+    base::ScopedAllowBlockingForTesting allow_io;
     base::File file(downloads_dir.Append("all-justice.jpg"),
                     base::File::FLAG_CREATE | base::File::FLAG_WRITE);
     ASSERT_TRUE(file.IsValid());
@@ -560,21 +562,21 @@
   ExpectCrostiniMount();
 
   // Add 'testing' volume with 'test_dir', create 'share_dir' in Downloads.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  AddLocalFileSystem(browser()->profile(), temp_dir.GetPath());
+  AddLocalFileSystem(browser()->profile(), temp_dir_.GetPath());
   base::FilePath downloads;
   ASSERT_TRUE(
       storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
           file_manager::util::GetDownloadsMountPointName(browser()->profile()),
           &downloads));
-  ASSERT_TRUE(base::CreateDirectory(downloads.AppendASCII("share_dir")));
-
   // Setup prefs crostini.shared_paths.
   base::FilePath shared1 = downloads.AppendASCII("shared1");
   base::FilePath shared2 = downloads.AppendASCII("shared2");
-  ASSERT_TRUE(base::CreateDirectory(shared1));
-  ASSERT_TRUE(base::CreateDirectory(shared2));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::CreateDirectory(downloads.AppendASCII("share_dir")));
+    ASSERT_TRUE(base::CreateDirectory(shared1));
+    ASSERT_TRUE(base::CreateDirectory(shared2));
+  }
   base::ListValue shared_paths;
   shared_paths.AppendString(shared1.value());
   shared_paths.AppendString(shared2.value());
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 584697d..6ab6f46 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -907,6 +908,7 @@
   set_test_case_name("driveMigratePinnedFile");
   StartTest();
 
+  base::ScopedAllowBlockingForTesting allow_io;
   EXPECT_TRUE(base::IsDirectoryEmpty(GetDriveDataDirectory()));
 }
 
@@ -914,18 +916,25 @@
   set_test_case_name("PRE_driveRecoverDirtyFiles");
   StartTest();
 
-  // Create a non-dirty file in the cache.
-  base::WriteFile(GetDriveDataDirectory().Append("files/foo"), "data", 4);
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+
+    // Create a non-dirty file in the cache.
+    base::WriteFile(GetDriveDataDirectory().Append("files/foo"), "data", 4);
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(DriveFsFilesAppBrowserTest, RecoverDirtyFiles) {
   set_test_case_name("driveRecoverDirtyFiles");
   StartTest();
 
+  base::ScopedAllowBlockingForTesting allow_io;
   EXPECT_TRUE(base::IsDirectoryEmpty(GetDriveDataDirectory()));
 }
 
 IN_PROC_BROWSER_TEST_F(DriveFsFilesAppBrowserTest, LaunchWithoutOldDriveData) {
+  base::ScopedAllowBlockingForTesting allow_io;
+
   // After starting up, GCache/v1 should still be empty.
   EXPECT_TRUE(base::IsDirectoryEmpty(GetDriveDataDirectory()));
 }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index 47a1c34..7ac5b36 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -375,6 +375,7 @@
     if (root_initialized_)
       return true;
     root_ = profile->GetPath().Append(name_);
+    base::ScopedAllowBlockingForTesting allow_blocking;
     root_initialized_ = base::CreateDirectory(root_);
     return root_initialized_;
   }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc
index 62840e6..714c227 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/file_manager/file_manager_jstest_base.h"
 
 #include "base/path_service.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -19,7 +20,10 @@
   base::FilePath root_path;
   ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
   base::FilePath full_path = root_path.Append(base_path_).Append(file);
-  ASSERT_TRUE(base::PathExists(full_path)) << full_path.value();
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::PathExists(full_path)) << full_path.value();
+  }
   RunTestImpl(net::FilePathToFileURL(full_path));
 }
 
diff --git a/chrome/browser/chromeos/login/active_directory_test_helper.cc b/chrome/browser/chromeos/login/active_directory_test_helper.cc
index 7b187c6..d94115e 100644
--- a/chrome/browser/chromeos/login/active_directory_test_helper.cc
+++ b/chrome/browser/chromeos/login/active_directory_test_helper.cc
@@ -10,6 +10,7 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/chromeos_paths.h"
 #include "chromeos/dbus/auth_policy_client.h"
@@ -85,6 +86,8 @@
 void OverridePaths() {
   base::FilePath user_data_dir;
   ASSERT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
+
+  base::ScopedAllowBlockingForTesting allow_io;
   RegisterStubPathOverrides(user_data_dir);
 }
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc
index 86bcac6..e0d3d12 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 
 namespace chromeos {
@@ -14,6 +15,7 @@
 
 bool SetupDummyOfflinePolicyDir(const std::string& account_id,
                                 base::ScopedTempDir* temp_dir) {
+  base::ScopedAllowBlockingForTesting allow_io;
   if (!temp_dir->CreateUniqueTempDir()) {
     LOG(ERROR) << "Failed to create unique tempdir";
     return false;
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index ea5ffcc7..d855854 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h"
@@ -159,6 +160,7 @@
 
   // Should be called once.
   void Wait() {
+    base::ScopedAllowBlockingForTesting allow_io;
     loop_.Run();
     config_watcher_.reset();
     creds_watcher_.reset();
@@ -168,6 +170,7 @@
   void MaybeStartWatch(std::unique_ptr<base::FilePathWatcher>* watcher,
                        const base::FilePath& path,
                        bool files_must_exist) {
+    base::ScopedAllowBlockingForTesting allow_io;
     (*watcher)->Watch(path, false /* recursive */, watch_callback_);
     if (!files_must_exist && base::PathExists(path)) {
       watch_callback_.Run(path, false /* error */);
@@ -179,6 +182,7 @@
 
   base::RepeatingCallback<void(const base::FilePath& path, bool error)>
       watch_callback_;
+
   std::unique_ptr<base::FilePathWatcher> config_watcher_;
   std::unique_ptr<base::FilePathWatcher> creds_watcher_;
 };
@@ -899,6 +903,7 @@
   }
 
   void CheckKerberosFiles(bool enable_dns_cname_lookup) {
+    base::ScopedAllowBlockingForTesting allow_io;
     std::string file_contents;
     EXPECT_TRUE(base::ReadFileToString(
         base::FilePath(GetKerberosConfigFileName()), &file_contents));
diff --git a/chrome/browser/chromeos/login/resource_loader_browsertest.cc b/chrome/browser/chromeos/login/resource_loader_browsertest.cc
index 87d09ae..2acad190 100644
--- a/chrome/browser/chromeos/login/resource_loader_browsertest.cc
+++ b/chrome/browser/chromeos/login/resource_loader_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/path_service.h"
 #include "base/strings/string_piece.h"
+#include "base/threading/thread_restrictions.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"
@@ -27,6 +28,7 @@
 namespace {
 
 GURL CreateResource(const std::string& content, const std::string& file_ext) {
+  base::ScopedAllowBlockingForTesting allow_io;
   base::FilePath path;
   EXPECT_TRUE(base::CreateTemporaryFile(&path));
   EXPECT_EQ(static_cast<int>(content.size()),
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index 78eddc5..272a4a7 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -25,6 +25,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
@@ -210,11 +211,13 @@
 }
 
 void FakeSamlIdp::SetLoginHTMLTemplate(const std::string& template_file) {
+  base::ScopedAllowBlockingForTesting allow_io;
   EXPECT_TRUE(base::ReadFileToString(html_template_dir_.Append(template_file),
                                      &login_html_template_));
 }
 
 void FakeSamlIdp::SetLoginAuthHTMLTemplate(const std::string& template_file) {
+  base::ScopedAllowBlockingForTesting allow_io;
   EXPECT_TRUE(base::ReadFileToString(html_template_dir_.Append(template_file),
                                      &login_auth_html_template_));
 }
diff --git a/chrome/browser/chromeos/login/screens/multidevice_setup_screen.cc b/chrome/browser/chromeos/login/screens/multidevice_setup_screen.cc
index f6b3d77..385c82a3 100644
--- a/chrome/browser/chromeos/login/screens/multidevice_setup_screen.cc
+++ b/chrome/browser/chromeos/login/screens/multidevice_setup_screen.cc
@@ -6,6 +6,7 @@
 
 #include "base/feature_list.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
 #include "chrome/browser/chromeos/login/screens/multidevice_setup_screen_view.h"
 #include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/chromeos/multidevice_setup/oobe_completion_tracker_factory.h"
@@ -18,7 +19,8 @@
 
 namespace {
 
-constexpr const char kFinishedUserAction[] = "setup-finished";
+constexpr const char kAcceptedSetupUserAction[] = "setup-accepted";
+constexpr const char kDeclinedSetupUserAction[] = "setup-declined";
 
 }  // namespace
 
@@ -84,12 +86,23 @@
 }
 
 void MultiDeviceSetupScreen::OnUserAction(const std::string& action_id) {
-  if (action_id == kFinishedUserAction) {
+  if (action_id == kAcceptedSetupUserAction) {
+    RecordMultiDeviceSetupOOBEUserChoiceHistogram(
+        MultiDeviceSetupOOBEUserChoice::kAccepted);
     ExitScreen();
-    return;
+  } else if (action_id == kDeclinedSetupUserAction) {
+    RecordMultiDeviceSetupOOBEUserChoiceHistogram(
+        MultiDeviceSetupOOBEUserChoice::kDeclined);
+    ExitScreen();
+  } else {
+    BaseScreen::OnUserAction(action_id);
+    NOTREACHED();
   }
+}
 
-  BaseScreen::OnUserAction(action_id);
+void MultiDeviceSetupScreen::RecordMultiDeviceSetupOOBEUserChoiceHistogram(
+    MultiDeviceSetupOOBEUserChoice value) {
+  UMA_HISTOGRAM_ENUMERATION("MultiDeviceSetup.OOBE.UserChoice", value);
 }
 
 void MultiDeviceSetupScreen::ExitScreen() {
diff --git a/chrome/browser/chromeos/login/screens/multidevice_setup_screen.h b/chrome/browser/chromeos/login/screens/multidevice_setup_screen.h
index be5ee43..f3654329d 100644
--- a/chrome/browser/chromeos/login/screens/multidevice_setup_screen.h
+++ b/chrome/browser/chromeos/login/screens/multidevice_setup_screen.h
@@ -27,6 +27,21 @@
   void OnUserAction(const std::string& action_id) override;
 
  private:
+  friend class MultiDeviceSetupScreenTest;
+
+  // This enum is tied directly to a UMA enum defined in
+  // //tools/metrics/histograms/enums.xml, and should always reflect it (do not
+  // change one without changing the other).  Entries should be never modified
+  // or deleted.  Only additions possible.
+  enum class MultiDeviceSetupOOBEUserChoice {
+    kAccepted = 0,
+    kDeclined = 1,
+    kMaxValue = kDeclined
+  };
+
+  static void RecordMultiDeviceSetupOOBEUserChoiceHistogram(
+      MultiDeviceSetupOOBEUserChoice value);
+
   // Exits the screen.
   void ExitScreen();
 
diff --git a/chrome/browser/chromeos/login/screens/multidevice_setup_screen_unittest.cc b/chrome/browser/chromeos/login/screens/multidevice_setup_screen_unittest.cc
new file mode 100644
index 0000000..0c5bd04b
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/multidevice_setup_screen_unittest.cc
@@ -0,0 +1,86 @@
+// 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/chromeos/login/screens/multidevice_setup_screen.h"
+
+#include <memory>
+
+#include "base/test/metrics/histogram_tester.h"
+#include "chrome/browser/chromeos/login/screens/mock_base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/multidevice_setup_screen_view.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+class FakeMultiDeviceSetupScreenView : public MultiDeviceSetupScreenView {
+ public:
+  FakeMultiDeviceSetupScreenView() = default;
+  ~FakeMultiDeviceSetupScreenView() override = default;
+
+  // MultiDeviceSetupScreenView:
+  void Bind(MultiDeviceSetupScreen* screen) override {}
+  void Show() override {}
+  void Hide() override {}
+};
+
+}  // namespace
+
+class MultiDeviceSetupScreenTest : public testing::Test {
+ public:
+  MultiDeviceSetupScreenTest() = default;
+  ~MultiDeviceSetupScreenTest() override = default;
+
+  // testing::Test:
+  void SetUp() override {
+    multi_device_setup_screen_ = std::make_unique<MultiDeviceSetupScreen>(
+        &mock_base_screen_delegate_, &fake_multi_device_setup_screen_view_);
+  }
+
+  void TearDown() override {}
+
+  std::unique_ptr<MultiDeviceSetupScreen> multi_device_setup_screen_;
+
+  void VerifyUserChoicePaths() {
+    histogram_tester_.ExpectTotalCount("MultiDeviceSetup.OOBE.UserChoice", 0);
+
+    multi_device_setup_screen_->OnUserAction("setup-accepted");
+
+    histogram_tester_.ExpectBucketCount<
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice>(
+        "MultiDeviceSetup.OOBE.UserChoice",
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice::kAccepted, 1);
+    histogram_tester_.ExpectBucketCount<
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice>(
+        "MultiDeviceSetup.OOBE.UserChoice",
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice::kDeclined, 0);
+
+    multi_device_setup_screen_->OnUserAction("setup-declined");
+
+    histogram_tester_.ExpectBucketCount<
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice>(
+        "MultiDeviceSetup.OOBE.UserChoice",
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice::kAccepted, 1);
+    histogram_tester_.ExpectBucketCount<
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice>(
+        "MultiDeviceSetup.OOBE.UserChoice",
+        MultiDeviceSetupScreen::MultiDeviceSetupOOBEUserChoice::kDeclined, 1);
+  }
+
+ private:
+  base::HistogramTester histogram_tester_;
+
+  // Accessory objects needed by MultiDeviceSetupScreen
+  MockBaseScreenDelegate mock_base_screen_delegate_;
+  FakeMultiDeviceSetupScreenView fake_multi_device_setup_screen_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupScreenTest);
+};
+
+TEST_F(MultiDeviceSetupScreenTest, VerifyUserChoicePaths) {
+  VerifyUserChoicePaths();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc
index 6a45bf9..4765eee 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.cc
+++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -137,8 +137,9 @@
 
   ContextEditor context_editor = GetContextEditor();
 
-  bool restart_required = !base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kFirstExecAfterBoot);
+  bool restart_required = user_manager::UserManager::Get()->IsUserLoggedIn() ||
+                          !base::CommandLine::ForCurrentProcess()->HasSwitch(
+                              switches::kFirstExecAfterBoot);
   if (restart_required) {
     context_editor.SetInteger(kContextKeyScreenState, STATE_RESTART_REQUIRED);
     dialog_type = reset::DIALOG_SHORTCUT_RESTART_REQUIRED;
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
index f34e63e..326e4b6 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
@@ -160,9 +160,12 @@
     std::string profile_image_data;
     base::FilePath test_data_dir;
     EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
-    EXPECT_TRUE(
-        ReadFileToString(test_data_dir.Append("chromeos").Append("avatar1.jpg"),
-                         &profile_image_data));
+    {
+      base::ScopedAllowBlockingForTesting allow_io;
+      EXPECT_TRUE(ReadFileToString(
+          test_data_dir.Append("chromeos").Append("avatar1.jpg"),
+          &profile_image_data));
+    }
     std::unique_ptr<net::test_server::BasicHttpResponse> response =
         std::make_unique<net::test_server::BasicHttpResponse>();
     response->set_content_type("image/jpeg");
@@ -505,6 +508,7 @@
   // The saved image should have transparent pixels (i.e. not opaque).
   EXPECT_FALSE(SkBitmap::ComputeIsOpaque(*new_saved_image->bitmap()));
 
+  base::ScopedAllowBlockingForTesting allow_io;
   // The old user image file in JPEG should be deleted. Only the PNG version
   // should stay.
   EXPECT_FALSE(base::PathExists(GetUserImagePath(test_account_id1_, "jpg")));
@@ -664,6 +668,7 @@
   }
 
   std::string ConstructPolicy(const std::string& relative_path) {
+    base::ScopedAllowBlockingForTesting allow_io;
     std::string image_data;
     if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
                                 &image_data)) {
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.cc
index 402e96c..01dace79 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.cc
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.cc
@@ -11,6 +11,7 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/image/image_skia.h"
@@ -52,7 +53,10 @@
 
 std::unique_ptr<gfx::ImageSkia> ImageLoader::Load() {
   std::string image_data;
-  ReadFileToString(path_, &image_data);
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ReadFileToString(path_, &image_data);
+  }
   const ImageDecoder::ImageCodec codec =
       (path_.Extension() == FILE_PATH_LITERAL(".jpg")
            ? ImageDecoder::ROBUST_JPEG_CODEC
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
index bd7e033..cab32fa 100644
--- a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -19,6 +19,7 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
@@ -258,6 +259,7 @@
   }
 
   std::string ConstructPolicy(const std::string& relative_path) const {
+    base::ScopedAllowBlockingForTesting allow_io;
     std::string image_data;
     if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
                                 &image_data)) {
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 1de6b520f..69217e46 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -431,6 +432,7 @@
 
     // Import a second client cert signed by another CA than client_1 into the
     // system wide key slot.
+    base::ScopedAllowBlockingForTesting allow_io;
     client_cert_ = net::ImportClientCertAndKeyFromFile(
         net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8",
         test_system_slot_->slot());
@@ -463,7 +465,10 @@
   void SetIntermediateAuthorityInDeviceOncPolicy(
       const base::FilePath& authority_file_path) {
     std::string x509_contents;
-    ASSERT_TRUE(base::ReadFileToString(authority_file_path, &x509_contents));
+    {
+      base::ScopedAllowBlockingForTesting allow_io;
+      ASSERT_TRUE(base::ReadFileToString(authority_file_path, &x509_contents));
+    }
     base::DictionaryValue onc_dict =
         BuildDeviceOncDictForUntrustedAuthority(x509_contents);
 
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 306bbc7..6706930 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -36,6 +36,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -770,6 +771,11 @@
 
   content::WebContents* contents_;
 
+  // These are member variables so they're guaranteed that the destructors
+  // (which may delete a directory) run in a scope where file IO is allowed.
+  base::ScopedTempDir temp_dir_;
+  base::ScopedTempDir cache_dir_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
 };
@@ -1137,17 +1143,23 @@
 
   // Pre-populate the device local account's extension cache with a hosted app
   // and an extension.
-  EXPECT_TRUE(base::CreateDirectory(
-      GetExtensionCacheDirectoryForAccountID(kAccountId1)));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(base::CreateDirectory(
+        GetExtensionCacheDirectoryForAccountID(kAccountId1)));
+  }
   base::FilePath test_dir;
   ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   const base::FilePath cached_hosted_app =
       GetCacheCRXFile(kAccountId1, kHostedAppID, kHostedAppVersion);
-  EXPECT_TRUE(CopyFile(test_dir.Append(kHostedAppCRXPath),
-                       cached_hosted_app));
-  EXPECT_TRUE(CopyFile(
-      test_dir.Append(kGoodExtensionCRXPath),
-      GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(
+        CopyFile(test_dir.Append(kHostedAppCRXPath), cached_hosted_app));
+    EXPECT_TRUE(CopyFile(
+        test_dir.Append(kGoodExtensionCRXPath),
+        GetCacheCRXFile(kAccountId1, kGoodExtensionID, kGoodExtensionVersion)));
+  }
 
   // Specify policy to force-install the hosted app.
   em::StringList* forcelist = device_local_account_policy_.payload()
@@ -1190,7 +1202,10 @@
   EXPECT_FALSE(extension_service->GetExtensionById(kGoodExtensionID, true));
 
   // Verify that the app is still in the account's extension cache.
-  EXPECT_TRUE(PathExists(cached_hosted_app));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(PathExists(cached_hosted_app));
+  }
 
   // Verify that the extension was removed from the account's extension cache.
   DeviceLocalAccountPolicyBroker* broker =
@@ -1221,6 +1236,7 @@
 static void CreateFile(const base::FilePath& file,
                 size_t size,
                 const base::Time& timestamp) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
   std::string data(size, 0);
   EXPECT_EQ(base::WriteFile(file, data.data(), data.size()), int(size));
   EXPECT_TRUE(base::TouchFile(file, timestamp, timestamp));
@@ -1242,10 +1258,13 @@
                  testing_update_manifest_provider));
   embedded_test_server()->StartAcceptingConnections();
   // Create and initialize local cache.
-  base::ScopedTempDir cache_dir;
-  EXPECT_TRUE(cache_dir.CreateUniqueTempDir());
-  const base::FilePath impl_path = cache_dir.GetPath();
-  EXPECT_TRUE(base::CreateDirectory(impl_path));
+  base::FilePath impl_path;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(cache_dir_.CreateUniqueTempDir());
+    impl_path = cache_dir_.GetPath();
+    EXPECT_TRUE(base::CreateDirectory(impl_path));
+  }
   CreateFile(impl_path.Append(
                  extensions::LocalExtensionCache::kCacheReadyFlagFileName),
              0, base::Time::Now());
@@ -1257,16 +1276,22 @@
   run_loop->Run();
 
   // Put extension in the local cache.
-  base::ScopedTempDir temp_dir;
-  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath temp_path = temp_dir.GetPath();
-  EXPECT_TRUE(base::CreateDirectory(temp_path));
+  base::FilePath temp_path;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+    temp_path = temp_dir_.GetPath();
+    EXPECT_TRUE(base::CreateDirectory(temp_path));
+  }
   const base::FilePath temp_file =
       GetCacheCRXFilePath(kGoodExtensionID, kGoodExtensionVersion, temp_path);
   base::FilePath test_dir;
   std::string hash;
   ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
-  EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath), temp_file));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(CopyFile(test_dir.Append(kGoodExtensionCRXPath), temp_file));
+  }
   cache_impl.AllowCaching(kGoodExtensionID);
   run_loop.reset(new base::RunLoop);
   cache_impl.PutExtension(kGoodExtensionID, hash, temp_file,
@@ -1277,7 +1302,10 @@
   // Verify that the extension file was added to the local cache.
   const base::FilePath local_file =
       GetCacheCRXFilePath(kGoodExtensionID, kGoodExtensionVersion, impl_path);
-  EXPECT_TRUE(PathExists(local_file));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_TRUE(PathExists(local_file));
+  }
 
   // Specify policy to force-install the hosted app and the extension.
   em::StringList* forcelist = device_local_account_policy_.payload()
@@ -1313,8 +1341,11 @@
   // Verify that the extension was kept in the local cache.
   EXPECT_TRUE(cache_impl.GetExtension(kGoodExtensionID, hash, NULL, NULL));
 
-  // Verify that the extension file was kept in the local cache.
-  EXPECT_TRUE(PathExists(local_file));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    // Verify that the extension file was kept in the local cache.
+    EXPECT_TRUE(PathExists(local_file));
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, ExternalData) {
@@ -1433,9 +1464,12 @@
   base::FilePath test_dir;
   ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   std::string image_data;
-  ASSERT_TRUE(base::ReadFileToString(
-      test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
-      &image_data));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(base::ReadFileToString(
+        test_dir.Append(chromeos::test::kUserAvatarImage1RelativePath),
+        &image_data));
+  }
 
   std::string policy;
   base::JSONWriter::Write(
@@ -2435,8 +2469,11 @@
   base::FilePath test_dir;
   ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
   std::string terms_of_service;
-  ASSERT_TRUE(base::ReadFileToString(
-      test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(base::ReadFileToString(
+        test_dir.Append(kExistentTermsOfServicePath), &terms_of_service));
+  }
   EXPECT_EQ(terms_of_service, content);
   EXPECT_FALSE(error);
   EXPECT_TRUE(accept_enabled);
diff --git a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
index f12f87b..a831a1a 100644
--- a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
+++ b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
@@ -12,6 +12,7 @@
 #include "base/files/file_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/path_service.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/chromeos_paths.h"
@@ -35,6 +36,7 @@
   base::FilePath install_attrs_file;
   ASSERT_TRUE(base::PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES,
                                      &install_attrs_file));
+  base::ScopedAllowBlockingForTesting allow_io;
   ASSERT_EQ(base::checked_cast<int>(install_attrs_blob.size()),
             base::WriteFile(install_attrs_file, install_attrs_blob.c_str(),
                             install_attrs_blob.size()));
@@ -79,6 +81,7 @@
   // the paths are overridden before using them.
   base::FilePath user_data_dir;
   ASSERT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
+  base::ScopedAllowBlockingForTesting allow_io;
   chromeos::RegisterStubPathOverrides(user_data_dir);
 }
 
diff --git a/chrome/browser/chromeos/policy/user_policy_test_helper.cc b/chrome/browser/chromeos/policy/user_policy_test_helper.cc
index abd5a683..c40b7c8 100644
--- a/chrome/browser/chromeos/policy/user_policy_test_helper.cc
+++ b/chrome/browser/chromeos/policy/user_policy_test_helper.cc
@@ -137,6 +137,7 @@
 }
 
 void UserPolicyTestHelper::DeletePolicyFile() {
+  base::ScopedAllowBlockingForTesting allow_io;
   base::DeleteFile(PolicyFilePath(), false);
 }
 
@@ -145,6 +146,8 @@
     const base::DictionaryValue& recommended) {
   const std::string policy = BuildPolicy(
       mandatory, recommended, dm_protocol::kChromeUserPolicyType, account_id_);
+
+  base::ScopedAllowBlockingForTesting allow_io;
   const int bytes_written =
       base::WriteFile(PolicyFilePath(), policy.data(), policy.size());
   ASSERT_EQ(static_cast<int>(policy.size()), bytes_written);
diff --git a/chrome/browser/chromeos/profiles/profile_helper.cc b/chrome/browser/chromeos/profiles/profile_helper.cc
index 4657ae80..b5588626 100644
--- a/chrome/browser/chromeos/profiles/profile_helper.cc
+++ b/chrome/browser/chromeos/profiles/profile_helper.cc
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
 #include "chrome/browser/chromeos/base/file_flusher.h"
@@ -100,6 +101,7 @@
 // static
 Profile* ProfileHelper::GetProfileByUserIdHashForTest(
     const std::string& user_id_hash) {
+  base::ScopedAllowBlockingForTesting allow_io;
   return g_browser_process->profile_manager()->GetProfile(
       ProfileHelper::GetProfilePathByUserIdHash(user_id_hash));
 }
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 7bd008a..94fcac24 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -252,7 +252,6 @@
     "api/metrics_private/chrome_metrics_private_delegate.h",
     "api/module/module.cc",
     "api/module/module.h",
-    "api/networking_private/networking_private_credentials_getter_chromeos.cc",
     "api/networking_private/networking_private_ui_delegate_chromeos.cc",
     "api/networking_private/networking_private_ui_delegate_chromeos.h",
     "api/networking_private/networking_private_ui_delegate_factory_impl.cc",
@@ -1051,9 +1050,6 @@
       "api/networking_cast_private/chrome_networking_cast_private_delegate.h",
       "api/networking_cast_private/networking_cast_private_api.cc",
       "api/networking_cast_private/networking_cast_private_api.h",
-      "api/networking_private/networking_private_credentials_getter.h",
-      "api/networking_private/networking_private_credentials_getter_mac.cc",
-      "api/networking_private/networking_private_credentials_getter_win.cc",
     ]
     deps += [ "//components/wifi" ]
   }
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
index 04c933c..593141f 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/containers/circular_deque.h"
 #include "base/task/post_task.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -343,8 +344,11 @@
   session_manager::SessionManager::Get()->CreateSession(
       AccountId::FromUserEmailGaiaId(kTestUserName, kTestUserGaiaId),
       kTestUserName, false);
-  g_browser_process->profile_manager()->GetProfile(
-      ProfileHelper::Get()->GetProfilePathByUserIdHash(kTestUserName));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    g_browser_process->profile_manager()->GetProfile(
+        ProfileHelper::Get()->GetProfilePathByUserIdHash(kTestUserName));
+  }
   session_manager::SessionManager::Get()->SessionStarted();
   Profile* profile = ProfileManager::GetActiveUserProfile();
   ASSERT_FALSE(
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
index 4a1c24e..909b6d1 100644
--- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
+++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -255,7 +255,10 @@
 
   VLOG(1) << "Sign the digest using the private key.";
   std::string key_pk8;
-  base::ReadFileToString(extension_path.AppendASCII("l1_leaf.pk8"), &key_pk8);
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    base::ReadFileToString(extension_path.AppendASCII("l1_leaf.pk8"), &key_pk8);
+  }
 
   const uint8_t* const key_pk8_begin =
       reinterpret_cast<const uint8_t*>(key_pk8.data());
diff --git a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
index 4bbaaac..27060f8c 100644
--- a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
@@ -15,7 +15,6 @@
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
 #include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -111,62 +110,6 @@
     success_callback.Run(encrypted_data);
 }
 
-// Called when NetworkingPrivateCredentialsGetter completes (from an arbitrary
-// thread). Posts the result to the UI thread.
-void CredentialsGetterCompleted(
-    const NetworkingCastPrivateDelegate::DataCallback& success_callback,
-    const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
-    const std::string& key_data,
-    const std::string& error) {
-  if (!error.empty()) {
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                             base::BindOnce(failure_callback, error));
-  } else {
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                             base::BindOnce(success_callback, key_data));
-  }
-}
-
-// Called from a blocking pool task runner. Returns true if
-// NetworkingPrivateCredentialsGetter is successfully started (which will
-// invoke the appropriate callback when completed), or false if unable
-// to start the getter (credentials or public key decode failed).
-bool RunVerifyAndEncryptCredentials(
-    const std::string& guid,
-    std::unique_ptr<NetworkingCastPrivateDelegate::Credentials> credentials,
-    const NetworkingCastPrivateDelegate::DataCallback& success_callback,
-    const NetworkingCastPrivateDelegate::FailureCallback& failure_callback) {
-  if (DecodeAndVerifyCredentials(*credentials) != VerificationResult::SUCCESS)
-    return false;
-
-  std::string decoded_public_key;
-  if (!base::Base64Decode(credentials->public_key(), &decoded_public_key)) {
-    LOG(ERROR) << "Failed to decode public key";
-    return false;
-  }
-
-  // Start getting credentials. CredentialsGetterCompleted will be called on
-  // completion. On Windows it will be called from a different thread after
-  // |credentials_getter| is deleted.
-  std::unique_ptr<NetworkingPrivateCredentialsGetter> credentials_getter(
-      NetworkingPrivateCredentialsGetter::Create());
-  credentials_getter->Start(guid, decoded_public_key,
-                            base::Bind(&CredentialsGetterCompleted,
-                                       success_callback, failure_callback));
-  return true;
-}
-
-void VerifyAndEncryptCredentialsCompleted(
-    const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
-    bool succeeded) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  // If VerifyAndEncryptCredentials succeeded, then the appropriate callback
-  // will be triggered from CredentialsGetterCompleted.
-  if (succeeded)
-    return;
-  failure_callback.Run(kErrorEncryptionError);
-}
-
 }  // namespace
 
 std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
@@ -197,19 +140,6 @@
                  failure_callback));
 }
 
-void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptCredentials(
-    const std::string& guid,
-    std::unique_ptr<Credentials> credentials,
-    const DataCallback& success_callback,
-    const FailureCallback& failure_callback) {
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
-      base::Bind(&RunVerifyAndEncryptCredentials, guid,
-                 base::Passed(&credentials), success_callback,
-                 failure_callback),
-      base::Bind(&VerifyAndEncryptCredentialsCompleted, failure_callback));
-}
-
 void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptData(
     const std::string& data,
     std::unique_ptr<Credentials> credentials,
diff --git a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
index 1207b5c..9242d0d 100644
--- a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
+++ b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
@@ -30,11 +30,6 @@
   void VerifyDestination(std::unique_ptr<Credentials> credentials,
                          const VerifiedCallback& success_callback,
                          const FailureCallback& failure_callback) override;
-  void VerifyAndEncryptCredentials(
-      const std::string& guid,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& success_callback,
-      const FailureCallback& failure_callback) override;
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
                             const DataCallback& success_callback,
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
index 241bcff..a4601bb 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
@@ -88,41 +88,6 @@
   Respond(Error(error));
 }
 
-NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::
-    ~NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() {}
-
-ExtensionFunction::ResponseAction
-NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Run() {
-  std::unique_ptr<cast_api::VerifyAndEncryptCredentials::Params> params =
-      cast_api::VerifyAndEncryptCredentials::Params::Create(*args_);
-  EXTENSION_FUNCTION_VALIDATE(params);
-
-  NetworkingCastPrivateDelegate* delegate =
-      ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
-  delegate->VerifyAndEncryptCredentials(
-      params->network_guid, AsCastCredentials(params->properties),
-      base::Bind(
-          &NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Success,
-          this),
-      base::Bind(
-          &NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Failure,
-          this));
-
-  // VerifyAndEncryptCredentials might respond synchronously, e.g. in tests.
-  return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Success(
-    const std::string& result) {
-  Respond(ArgumentList(
-      cast_api::VerifyAndEncryptCredentials::Results::Create(result)));
-}
-
-void NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Failure(
-    const std::string& error) {
-  Respond(Error(error));
-}
-
 NetworkingCastPrivateVerifyAndEncryptDataFunction::
     ~NetworkingCastPrivateVerifyAndEncryptDataFunction() {}
 
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
index 749e8588..fd773daa 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
@@ -37,28 +37,6 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateVerifyDestinationFunction);
 };
 
-class NetworkingCastPrivateVerifyAndEncryptCredentialsFunction
-    : public UIThreadExtensionFunction {
- public:
-  NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() {}
-  DECLARE_EXTENSION_FUNCTION(
-      "networking.castPrivate.verifyAndEncryptCredentials",
-      NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTCREDENTIALS);
-
- protected:
-  ~NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() override;
-
-  // ExtensionFunction:
-  ResponseAction Run() override;
-
-  void Success(const std::string& result);
-  void Failure(const std::string& error);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      NetworkingCastPrivateVerifyAndEncryptCredentialsFunction);
-};
-
 class NetworkingCastPrivateVerifyAndEncryptDataFunction
     : public UIThreadExtensionFunction {
  public:
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
index b2f52e0..5dbe11e7 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
@@ -42,15 +42,6 @@
     success_callback.Run(true);
   }
 
-  void VerifyAndEncryptCredentials(
-      const std::string& guid,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& success_callback,
-      const FailureCallback& failure_callback) override {
-    AssertCredentials(*credentials);
-    success_callback.Run("encrypted_credentials");
-  }
-
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
                             const DataCallback& success_callback,
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
index 631d58c..6daad87 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
@@ -291,17 +291,6 @@
     }
   }
 
-  void VerifyAndEncryptCredentials(
-      const std::string& guid,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& success_callback,
-      const FailureCallback& failure_callback) override {
-    if (fail_) {
-      failure_callback.Run(kFailure);
-    } else {
-      success_callback.Run("encrypted_credentials");
-    }
-  }
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
                             const DataCallback& success_callback,
@@ -493,10 +482,6 @@
   EXPECT_TRUE(RunNetworkingSubtest("verifyDestination")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateApiTest, VerifyAndEncryptCredentials) {
-  EXPECT_TRUE(RunNetworkingSubtest("verifyAndEncryptCredentials")) << message_;
-}
-
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateApiTest, VerifyAndEncryptData) {
   EXPECT_TRUE(RunNetworkingSubtest("verifyAndEncryptData")) << message_;
 }
@@ -603,11 +588,6 @@
   EXPECT_FALSE(RunNetworkingSubtest("verifyDestination")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateApiTestFail,
-                       VerifyAndEncryptCredentials) {
-  EXPECT_FALSE(RunNetworkingSubtest("verifyAndEncryptCredentials")) << message_;
-}
-
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateApiTestFail, VerifyAndEncryptData) {
   EXPECT_FALSE(RunNetworkingSubtest("verifyAndEncryptData")) << message_;
 }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 98b183bb..a6d0fd6 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -13,11 +13,11 @@
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
 #include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
 #include "chrome/browser/extensions/api/networking_private/networking_private_ui_delegate_chromeos.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chromeos/chromeos_switches.h"
@@ -114,15 +114,6 @@
     success_callback.Run(true);
   }
 
-  void VerifyAndEncryptCredentials(
-      const std::string& guid,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& success_callback,
-      const FailureCallback& failure_callback) override {
-    AssertCredentials(*credentials);
-    success_callback.Run("encrypted_credentials");
-  }
-
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
                             const DataCallback& success_callback,
@@ -500,6 +491,7 @@
   }
 
   bool SetupCertificates() {
+    base::ScopedAllowBlockingForTesting allow_io;
     net::ScopedCERTCertificateList cert_list =
         net::CreateCERTCertificateListFromFile(
             net::GetTestCertsDirectory(), "client_1_ca.pem",
@@ -836,11 +828,6 @@
   EXPECT_TRUE(RunNetworkingSubtest("verifyDestination")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
-                       VerifyAndEncryptCredentials) {
-  EXPECT_TRUE(RunNetworkingSubtest("verifyAndEncryptCredentials")) << message_;
-}
-
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, VerifyAndEncryptData) {
   EXPECT_TRUE(RunNetworkingSubtest("verifyAndEncryptData")) << message_;
 }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h
deleted file mode 100644
index 23590926..0000000
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CREDENTIALS_GETTER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CREDENTIALS_GETTER_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-
-namespace extensions {
-
-// NetworkingPrivateCredentialsGetter gets plain-text WiFi credentials from the
-// system and encrypts it with public key.
-class NetworkingPrivateCredentialsGetter {
- public:
-  typedef base::Callback<void(const std::string& key_data,
-                              const std::string& error)> CredentialsCallback;
-
-  static NetworkingPrivateCredentialsGetter* Create();
-
-  NetworkingPrivateCredentialsGetter() {}
-
-  virtual ~NetworkingPrivateCredentialsGetter() {}
-
-  // Starts getting credentials. The credentials and, in case of an error, the
-  // error code are returned using |callback|.
-  // The NetworkingPrivateCredentialsGetter implementation should ensure that
-  // the credentials request can be successfully processed even if |this| gets
-  // deleted immediately after calling this method.
-  // Note that there are no guarantees about the thread on which |callback| is
-  // run. The caller should make sure that the result is processed on the right
-  // thread.
-  virtual void Start(const std::string& network_guid,
-                     const std::string& public_key,
-                     const CredentialsCallback& callback) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateCredentialsGetter);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CREDENTIALS_GETTER_H_
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
deleted file mode 100644
index ad78f87..0000000
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-#include "chrome/services/wifi_util_win/public/mojom/wifi_credentials_getter.mojom.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-
-#if !defined(OS_WIN)
-#error This test is OS_WIN only.
-#endif
-
-class NetworkingPrivateCredentialsGetterTest : public InProcessBrowserTest {
- public:
-  NetworkingPrivateCredentialsGetterTest() = default;
-
-  void RunTest(bool use_test_network) {
-    base::RunLoop run_loop;
-    quit_closure_ = run_loop.QuitClosure();
-
-    if (use_test_network)
-      network_ = chrome::mojom::WiFiCredentialsGetter::kWiFiTestNetwork;
-
-    done_called_ = false;
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-        base::Bind(&NetworkingPrivateCredentialsGetterTest::GetCredentials,
-                   base::Unretained(this)));
-    run_loop.Run();
-
-    EXPECT_TRUE(done_called_);
-  }
-
- private:
-  void GetCredentials() {
-    std::unique_ptr<extensions::NetworkingPrivateCredentialsGetter> getter(
-        extensions::NetworkingPrivateCredentialsGetter::Create());
-    getter->Start(
-        network_, "public_key",
-        base::Bind(&NetworkingPrivateCredentialsGetterTest::CredentialsDone,
-                   base::Unretained(this)));
-  }
-
-  void CredentialsDone(const std::string& key_data, const std::string& error) {
-    done_called_ = true;
-
-    if (!network_.empty()) {
-      EXPECT_EQ(network_, key_data);
-      EXPECT_EQ("", error);
-    } else {
-      EXPECT_EQ("", key_data);
-      EXPECT_FALSE(error.empty());
-    }
-
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                             quit_closure_);
-  }
-
-  base::Closure quit_closure_;
-  std::string network_;
-  bool done_called_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateCredentialsGetterTest);
-};
-
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateCredentialsGetterTest,
-                       GetCredentialsSuccess) {
-  RunTest(true);
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateCredentialsGetterTest,
-                       GetCredentialsFailure) {
-  RunTest(false);
-}
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc
deleted file mode 100644
index cf2b101..0000000
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_chromeos.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/macros.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-
-const char kErrorNotImplemented[] = "Error.NotImplemented";
-
-namespace extensions {
-
-class NetworkingPrivateCredentialsGetterChromeos
-    : public NetworkingPrivateCredentialsGetter {
- public:
-  NetworkingPrivateCredentialsGetterChromeos() {}
-
-  void Start(const std::string& network_guid,
-             const std::string& public_key,
-             const CredentialsCallback& callback) override;
-
- private:
-  ~NetworkingPrivateCredentialsGetterChromeos() override;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateCredentialsGetterChromeos);
-};
-
-NetworkingPrivateCredentialsGetterChromeos::
-    ~NetworkingPrivateCredentialsGetterChromeos() {
-}
-
-void NetworkingPrivateCredentialsGetterChromeos::Start(
-    const std::string& network_guid,
-    const std::string& public_key,
-    const CredentialsCallback& callback) {
-  // TODO(sheretov) add credential slurping from sync.
-  callback.Run(std::string(), kErrorNotImplemented);
-}
-
-NetworkingPrivateCredentialsGetter*
-NetworkingPrivateCredentialsGetter::Create() {
-  return new NetworkingPrivateCredentialsGetterChromeos();
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_mac.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_mac.cc
deleted file mode 100644
index 7662976..0000000
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_mac.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-
-#include <Security/Security.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/macros.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
-#include "components/wifi/wifi_service.h"
-#include "content/public/browser/browser_thread.h"
-
-const char kErrorEncryption[] = "Error.Encryption";
-
-using content::BrowserThread;
-
-namespace extensions {
-
-class NetworkingPrivateCredentialsGetterMac
-    : public NetworkingPrivateCredentialsGetter {
- public:
-  explicit NetworkingPrivateCredentialsGetterMac();
-
-  void Start(const std::string& network_guid,
-             const std::string& public_key,
-             const CredentialsCallback& callback) override;
-
- private:
-  ~NetworkingPrivateCredentialsGetterMac() override;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateCredentialsGetterMac);
-};
-
-NetworkingPrivateCredentialsGetterMac::NetworkingPrivateCredentialsGetterMac() {
-}
-
-NetworkingPrivateCredentialsGetterMac::
-    ~NetworkingPrivateCredentialsGetterMac() {}
-
-void NetworkingPrivateCredentialsGetterMac::Start(
-    const std::string& network_guid,
-    const std::string& public_key,
-    const CredentialsCallback& callback) {
-  std::unique_ptr<wifi::WiFiService> wifi_service(wifi::WiFiService::Create());
-  wifi_service->Initialize(NULL);
-  std::string key_data;
-  std::string error;
-  wifi_service->GetKeyFromSystem(network_guid, &key_data, &error);
-
-  if (!error.empty()) {
-    callback.Run("", error);
-    return;
-  }
-
-  std::vector<uint8_t> public_key_data(public_key.begin(), public_key.end());
-  std::vector<uint8_t> ciphertext;
-  if (!networking_private_crypto::EncryptByteString(
-          public_key_data, key_data, &ciphertext)) {
-    callback.Run("", kErrorEncryption);
-    return;
-  }
-
-  std::string base64_encoded_ciphertext;
-  base::Base64Encode(
-      base::StringPiece(reinterpret_cast<const char*>(ciphertext.data()),
-                        ciphertext.size()),
-      &base64_encoded_ciphertext);
-  callback.Run(base64_encoded_ciphertext, "");
-}
-
-NetworkingPrivateCredentialsGetter*
-NetworkingPrivateCredentialsGetter::Create() {
-  return new NetworkingPrivateCredentialsGetterMac();
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc
deleted file mode 100644
index 55fd74e..0000000
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-
-#include <stdint.h>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
-#include "chrome/services/wifi_util_win/public/mojom/constants.mojom.h"
-#include "chrome/services/wifi_util_win/public/mojom/wifi_credentials_getter.mojom.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace {
-
-using extensions::NetworkingPrivateCredentialsGetter;
-
-class CredentialsGetterHostClient {
- public:
-  static CredentialsGetterHostClient* Create(const std::string& public_key) {
-    return new CredentialsGetterHostClient(public_key);
-  }
-
-  void GetWiFiCredentialsOnIOThread(
-      const std::string& network_guid,
-      const NetworkingPrivateCredentialsGetter::CredentialsCallback& callback,
-      std::unique_ptr<service_manager::Connector> connector);
-
- private:
-  explicit CredentialsGetterHostClient(const std::string& public_key)
-      : public_key_(public_key.begin(), public_key.end()) {}
-
-  ~CredentialsGetterHostClient() = default;
-
-  // Credentials result handler.
-  void GetWiFiCredentialsDone(bool success, const std::string& key_data);
-
-  // Report the result to |callback_|.
-  void ReportResult(bool success, const std::string& key_data);
-
-  // Public key used to encrypt the result.
-  std::vector<uint8_t> public_key_;
-
-  // Callback for reporting the encrypted result.
-  NetworkingPrivateCredentialsGetter::CredentialsCallback callback_;
-
-  // Utility process used to get the credentials.
-  chrome::mojom::WiFiCredentialsGetterPtr wifi_credentials_getter_;
-
-  // WiFi network to get the credentials from.
-  std::string wifi_network_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialsGetterHostClient);
-};
-
-void CredentialsGetterHostClient::GetWiFiCredentialsOnIOThread(
-    const std::string& network_guid,
-    const NetworkingPrivateCredentialsGetter::CredentialsCallback& callback,
-    std::unique_ptr<service_manager::Connector> connector) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  DCHECK(!wifi_credentials_getter_);
-  DCHECK(!callback.is_null());
-
-  wifi_network_ = network_guid;
-  callback_ = callback;
-
-  connector->BindInterface(chrome::mojom::kWifiUtilWinServiceName,
-                           &wifi_credentials_getter_);
-
-  wifi_credentials_getter_.set_connection_error_handler(
-      base::Bind(&CredentialsGetterHostClient::GetWiFiCredentialsDone,
-                 base::Unretained(this), false, std::string()));
-  wifi_credentials_getter_->GetWiFiCredentials(
-      wifi_network_,
-      base::Bind(&CredentialsGetterHostClient::GetWiFiCredentialsDone,
-                 base::Unretained(this)));
-}
-
-void CredentialsGetterHostClient::GetWiFiCredentialsDone(
-    bool success,
-    const std::string& key_data) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
-  wifi_credentials_getter_.reset();
-  ReportResult(success, key_data);
-  delete this;
-}
-
-void CredentialsGetterHostClient::ReportResult(bool success,
-                                               const std::string& key_data) {
-  if (!success) {
-    callback_.Run(std::string(), "Get Credentials Failed");
-    return;
-  }
-
-  if (wifi_network_ == chrome::mojom::WiFiCredentialsGetter::kWiFiTestNetwork) {
-    DCHECK_EQ(wifi_network_, key_data);
-    callback_.Run(key_data, std::string());
-    return;
-  }
-
-  std::vector<uint8_t> ciphertext;
-  if (!networking_private_crypto::EncryptByteString(public_key_, key_data,
-                                                    &ciphertext)) {
-    callback_.Run(std::string(), "Encrypt Credentials Failed");
-    return;
-  }
-
-  std::string base64_encoded_key_data;
-  base::Base64Encode(
-      base::StringPiece(reinterpret_cast<const char*>(ciphertext.data()),
-                        ciphertext.size()),
-      &base64_encoded_key_data);
-  callback_.Run(base64_encoded_key_data, std::string());
-}
-
-}  // namespace
-
-namespace extensions {
-
-class NetworkingPrivateCredentialsGetterWin
-    : public NetworkingPrivateCredentialsGetter {
- public:
-  NetworkingPrivateCredentialsGetterWin() = default;
-
-  void Start(const std::string& network_guid,
-             const std::string& public_key,
-             const CredentialsCallback& callback) override {
-    // Bounce to the UI thread to retrieve a service_manager::Connector.
-    base::PostTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::UI},
-        base::Bind(&NetworkingPrivateCredentialsGetterWin::StartOnUIThread,
-                   network_guid, public_key, callback));
-  }
-
- private:
-  ~NetworkingPrivateCredentialsGetterWin() override = default;
-
-  static void StartOnUIThread(const std::string& network_guid,
-                              const std::string& public_key,
-                              const CredentialsCallback& callback) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-    std::unique_ptr<service_manager::Connector> connector =
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone();
-    base::PostTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::IO},
-        base::BindOnce(
-            &NetworkingPrivateCredentialsGetterWin::GetCredentialsOnIOThread,
-            network_guid, public_key, callback, std::move(connector)));
-  }
-
-  static void GetCredentialsOnIOThread(
-      const std::string& network_guid,
-      const std::string& public_key,
-      const CredentialsCallback& callback,
-      std::unique_ptr<service_manager::Connector> connector) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
-    // CredentialsGetterHostClient is self deleting.
-    CredentialsGetterHostClient* client =
-        CredentialsGetterHostClient::Create(public_key);
-    client->GetWiFiCredentialsOnIOThread(network_guid, callback,
-                                         std::move(connector));
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateCredentialsGetterWin);
-};
-
-NetworkingPrivateCredentialsGetter*
-NetworkingPrivateCredentialsGetter::Create() {
-  return new NetworkingPrivateCredentialsGetterWin();
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
index 1fb3a24..1a61a78 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
@@ -58,15 +57,6 @@
     success_callback.Run(true);
   }
 
-  void VerifyAndEncryptCredentials(
-      const std::string& guid,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& success_callback,
-      const FailureCallback& failure_callback) override {
-    AssertCredentials(*credentials);
-    success_callback.Run("encrypted_credentials");
-  }
-
   void VerifyAndEncryptData(const std::string& data,
                             std::unique_ptr<Credentials> credentials,
                             const DataCallback& success_callback,
@@ -256,11 +246,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(NetworkingPrivateServiceClientApiTest,
-                       VerifyAndEncryptCredentials) {
-  EXPECT_TRUE(RunNetworkingSubtest("verifyAndEncryptCredentials")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateServiceClientApiTest,
                        VerifyAndEncryptData) {
   EXPECT_TRUE(RunNetworkingSubtest("verifyAndEncryptData")) << message_;
 }
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 6d44907..3850b4c 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -992,6 +992,7 @@
 
 #if defined(OS_CHROMEOS)
 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, KioskOnlyTest) {
+  base::ScopedAllowBlockingForTesting allow_io;
   // kiosk_only is whitelisted from non-chromeos.
   base::FilePath crx_path =
       test_data_dir_.AppendASCII("kiosk/kiosk_only.crx");
@@ -1009,6 +1010,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, InstallToSharedLocation) {
+  base::ScopedAllowBlockingForTesting allow_io;
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       chromeos::switches::kEnableExtensionAssetsSharing);
   base::ScopedTempDir cache_dir;
@@ -1021,7 +1023,6 @@
       crx_path, 1, extensions::Manifest::EXTERNAL_PREF);
   base::FilePath extension_path = extension->path();
   EXPECT_TRUE(cache_dir.GetPath().IsParent(extension_path));
-  base::ScopedAllowBlockingForTesting allow_io;
   EXPECT_TRUE(base::PathExists(extension_path));
 
   std::string extension_id = extension->id();
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 51a1788..6b95745 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3126,6 +3126,10 @@
 const char kCrostiniFilesDescription[] =
     "Enable Crostini file sharing in Files app.";
 
+const char kCrostiniUsbSupportName[] = "Crostini Usb Support";
+const char kCrostiniUsbSupportDescription[] =
+    "Enable mounting Usb devices in Crostini.";
+
 const char kDisableExplicitDmaFencesName[] = "Disable explicit dma-fences";
 const char kDisableExplicitDmaFencesDescription[] =
     "Always rely on implicit syncrhonization between GPU and display "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 06c8cbcc..2b08bc02 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1906,6 +1906,9 @@
 extern const char kCrostiniFilesName[];
 extern const char kCrostiniFilesDescription[];
 
+extern const char kCrostiniUsbSupportName[];
+extern const char kCrostiniUsbSupportDescription[];
+
 extern const char kDisableExplicitDmaFencesName[];
 extern const char kDisableExplicitDmaFencesDescription[];
 
diff --git a/chrome/browser/net/chrome_network_delegate_browsertest.cc b/chrome/browser/net/chrome_network_delegate_browsertest.cc
index 01493090a..d1f0124 100644
--- a/chrome/browser/net/chrome_network_delegate_browsertest.cc
+++ b/chrome/browser/net/chrome_network_delegate_browsertest.cc
@@ -31,6 +31,14 @@
     ChromeNetworkDelegate::EnableAccessToAllFilesForTesting(false);
   }
 
+  void SetUpOnMainThread() override {
+    base::FilePath temp_dir;
+    ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir));
+    ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDirUnderPath(temp_dir));
+  }
+
+  base::ScopedTempDir scoped_temp_dir_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ChromeNetworkDelegateBrowserTest);
 };
@@ -65,9 +73,7 @@
 
   base::FilePath temp_dir;
   ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir));
-  base::ScopedTempDir scoped_temp_dir;
-  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(temp_dir));
-  base::FilePath symlink = scoped_temp_dir.GetPath().AppendASCII("symlink");
+  base::FilePath symlink = scoped_temp_dir_.GetPath().AppendASCII("symlink");
   ASSERT_TRUE(base::CreateSymbolicLink(test_file, symlink));
   ASSERT_TRUE(
       ChromeNetworkDelegate::IsAccessAllowed(symlink, base::FilePath()));
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
index b3dfb22..8015711 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -642,7 +642,8 @@
     const mojom::PageLoadTiming& timing,
     const mojom::PageLoadMetadata& metadata,
     const mojom::PageLoadFeatures& new_features,
-    const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
+    const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+    const mojom::PageRenderData& render_data) {
   // We may receive notifications from frames that have been navigated away
   // from. We simply ignore them.
   if (GetMainFrame(render_frame_host) != web_contents()->GetMainFrame()) {
@@ -675,7 +676,8 @@
 
   if (committed_load_) {
     committed_load_->metrics_update_dispatcher()->UpdateMetrics(
-        render_frame_host, timing, metadata, new_features, resources);
+        render_frame_host, timing, metadata, new_features, resources,
+        render_data);
   }
 }
 
@@ -683,11 +685,12 @@
     const mojom::PageLoadTimingPtr timing,
     const mojom::PageLoadMetadataPtr metadata,
     const mojom::PageLoadFeaturesPtr new_features,
-    const std::vector<mojom::ResourceDataUpdatePtr> resources) {
+    const std::vector<mojom::ResourceDataUpdatePtr> resources,
+    const mojom::PageRenderDataPtr render_data) {
   content::RenderFrameHost* render_frame_host =
       page_load_metrics_binding_.GetCurrentTargetFrame();
   OnTimingUpdated(render_frame_host, *timing, *metadata, *new_features,
-                  resources);
+                  resources, *render_data);
 }
 
 bool MetricsWebContentsObserver::ShouldTrackNavigation(
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
index 5499f04..d47f0d1 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -151,7 +151,8 @@
       const mojom::PageLoadTiming& timing,
       const mojom::PageLoadMetadata& metadata,
       const mojom::PageLoadFeatures& new_features,
-      const std::vector<mojom::ResourceDataUpdatePtr>& resources);
+      const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+      const mojom::PageRenderData& render_data);
 
   // Informs the observers of the currently committed load that the event
   // corresponding to |event_key| has occurred. This should not be called within
@@ -163,11 +164,11 @@
   friend class content::WebContentsUserData<MetricsWebContentsObserver>;
 
   // page_load_metrics::mojom::PageLoadMetrics implementation.
-  void UpdateTiming(
-      const mojom::PageLoadTimingPtr timing,
-      const mojom::PageLoadMetadataPtr metadata,
-      const mojom::PageLoadFeaturesPtr new_features,
-      const std::vector<mojom::ResourceDataUpdatePtr> resources) override;
+  void UpdateTiming(const mojom::PageLoadTimingPtr timing,
+                    const mojom::PageLoadMetadataPtr metadata,
+                    const mojom::PageLoadFeaturesPtr new_features,
+                    const std::vector<mojom::ResourceDataUpdatePtr> resources,
+                    const mojom::PageRenderDataPtr render_data) override;
 
   void HandleFailedNavigationForTrackedLoad(
       content::NavigationHandle* navigation_handle,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
index 54bae62..3dfda122 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -272,7 +272,8 @@
       content::RenderFrameHost* render_frame_host) {
     observer()->OnTimingUpdated(
         render_frame_host, timing, mojom::PageLoadMetadata(),
-        mojom::PageLoadFeatures(), std::vector<mojom::ResourceDataUpdatePtr>());
+        mojom::PageLoadFeatures(), std::vector<mojom::ResourceDataUpdatePtr>(),
+        mojom::PageRenderData());
   }
 
   void AttachObserver() {
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
index 7c6861e..84b5ea1a 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
@@ -87,9 +87,9 @@
     const mojom::PageLoadTiming& timing,
     const mojom::PageLoadMetadata& metadata,
     const mojom::PageLoadFeatures& new_features) {
-  observer_->OnTimingUpdated(web_contents()->GetMainFrame(), timing, metadata,
-                             new_features,
-                             std::vector<mojom::ResourceDataUpdatePtr>());
+  observer_->OnTimingUpdated(
+      web_contents()->GetMainFrame(), timing, metadata, new_features,
+      std::vector<mojom::ResourceDataUpdatePtr>(), mojom::PageRenderData());
   // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to
   // schedule a buffering timer, then fire it now so metrics are dispatched to
   // observers.
@@ -102,7 +102,8 @@
     const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
   observer_->OnTimingUpdated(web_contents()->GetMainFrame(),
                              mojom::PageLoadTiming(), mojom::PageLoadMetadata(),
-                             mojom::PageLoadFeatures(), resources);
+                             mojom::PageLoadFeatures(), resources,
+                             mojom::PageRenderData());
 }
 
 void PageLoadMetricsObserverTester::SimulateLoadedResource(
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
index e1cda828..08800244 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -502,6 +502,10 @@
   // Called when the event corresponding to |event_key| occurs in this page
   // load.
   virtual void OnEventOccurred(const void* const event_key) {}
+
+  // Called when the final layout jank score for the session is ready to be
+  // reported (immediately before OnComplete).
+  virtual void OnFinalLayoutStabilityUpdate(float jank_score) {}
 };
 
 }  // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
index 68e148b59..3cff675 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -412,7 +412,8 @@
       current_merged_page_timing_(CreatePageLoadTiming()),
       pending_merged_page_timing_(CreatePageLoadTiming()),
       main_frame_metadata_(mojom::PageLoadMetadata::New()),
-      subframe_metadata_(mojom::PageLoadMetadata::New()) {}
+      subframe_metadata_(mojom::PageLoadMetadata::New()),
+      main_frame_render_data_(mojom::PageRenderData::New()) {}
 
 PageLoadMetricsUpdateDispatcher::~PageLoadMetricsUpdateDispatcher() {
   ShutDown();
@@ -466,7 +467,8 @@
     const mojom::PageLoadTiming& new_timing,
     const mojom::PageLoadMetadata& new_metadata,
     const mojom::PageLoadFeatures& new_features,
-    const std::vector<mojom::ResourceDataUpdatePtr>& resources) {
+    const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+    const mojom::PageRenderData& render_data) {
   if (render_frame_host->GetLastCommittedURL().SchemeIs(
           extensions::kExtensionScheme)) {
     // Extensions can inject child frames into a page. We don't want to track
@@ -480,9 +482,11 @@
   if (render_frame_host->GetParent() == nullptr) {
     UpdateMainFrameMetadata(new_metadata);
     UpdateMainFrameTiming(new_timing);
+    UpdateMainFrameRenderData(render_data);
   } else {
     UpdateSubFrameMetadata(new_metadata);
     UpdateSubFrameTiming(render_frame_host, new_timing);
+    // TODO: Handle subframe PageRenderData.
   }
   client_->UpdateFeaturesUsage(new_features);
 }
@@ -624,6 +628,14 @@
   client_->OnMainFrameMetadataChanged();
 }
 
+void PageLoadMetricsUpdateDispatcher::UpdateMainFrameRenderData(
+    const mojom::PageRenderData& render_data) {
+  if (main_frame_render_data_->Equals(render_data))
+    return;
+
+  main_frame_render_data_ = render_data.Clone();
+}
+
 void PageLoadMetricsUpdateDispatcher::MaybeDispatchTimingUpdates(
     bool should_buffer_timing_update_callback) {
   // If we merged a new timing value, then we should buffer updates for
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
index 33debbdf..46453814 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
@@ -120,12 +120,12 @@
       PageLoadMetricsEmbedderInterface* embedder_interface);
   ~PageLoadMetricsUpdateDispatcher();
 
-  void UpdateMetrics(
-      content::RenderFrameHost* render_frame_host,
-      const mojom::PageLoadTiming& new_timing,
-      const mojom::PageLoadMetadata& new_metadata,
-      const mojom::PageLoadFeatures& new_features,
-      const std::vector<mojom::ResourceDataUpdatePtr>& resources);
+  void UpdateMetrics(content::RenderFrameHost* render_frame_host,
+                     const mojom::PageLoadTiming& new_timing,
+                     const mojom::PageLoadMetadata& new_metadata,
+                     const mojom::PageLoadFeatures& new_features,
+                     const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+                     const mojom::PageRenderData& render_data);
 
   // This method is only intended to be called for PageLoadFeatures being
   // recorded directly from the browser process. Features coming from the
@@ -148,6 +148,9 @@
   const mojom::PageLoadMetadata& subframe_metadata() const {
     return *(subframe_metadata_.get());
   }
+  const mojom::PageRenderData& main_frame_render_data() const {
+    return *(main_frame_render_data_.get());
+  }
 
  private:
   using FrameTreeNodeId = int;
@@ -159,6 +162,8 @@
   void UpdateMainFrameMetadata(const mojom::PageLoadMetadata& new_metadata);
   void UpdateSubFrameMetadata(const mojom::PageLoadMetadata& subframe_metadata);
 
+  void UpdateMainFrameRenderData(const mojom::PageRenderData& render_data);
+
   void MaybeDispatchTimingUpdates(bool did_merge_new_timing_value);
   void DispatchTimingUpdates();
 
@@ -193,6 +198,8 @@
   mojom::PageLoadMetadataPtr main_frame_metadata_;
   mojom::PageLoadMetadataPtr subframe_metadata_;
 
+  mojom::PageRenderDataPtr main_frame_render_data_;
+
   // Navigation start offsets for the most recently committed document in each
   // frame.
   std::map<FrameTreeNodeId, base::TimeDelta> subframe_navigation_start_offset_;
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
index 75272a56..4572a02 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.cc
+++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -255,6 +255,9 @@
     if (failed_provisional_load_info_) {
       observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info);
     } else if (did_commit_) {
+      observer->OnFinalLayoutStabilityUpdate(
+          metrics_update_dispatcher_.main_frame_render_data()
+              .layout_jank_score);
       observer->OnComplete(metrics_update_dispatcher_.timing(), info);
     }
   }
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index 736abf9..6ac4edc 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -439,7 +439,10 @@
 
   // Read the initial key.
   std::string initial_key;
-  ASSERT_TRUE(base::ReadFileToString(user_policy_key_file_, &initial_key));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::ReadFileToString(user_policy_key_file_, &initial_key));
+  }
 
   PolicyMap default_policy;
   GetExpectedDefaultPolicy(&default_policy);
@@ -461,7 +464,10 @@
 
   // Verify that the key was rotated.
   std::string rotated_key;
-  ASSERT_TRUE(base::ReadFileToString(user_policy_key_file_, &rotated_key));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::ReadFileToString(user_policy_key_file_, &rotated_key));
+  }
   EXPECT_NE(rotated_key, initial_key);
 
   // Another refresh using the same key won't rotate it again.
@@ -473,7 +479,10 @@
   EXPECT_TRUE(expected.Equals(policy_service->GetPolicies(
       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))));
   std::string current_key;
-  ASSERT_TRUE(base::ReadFileToString(user_policy_key_file_, &current_key));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::ReadFileToString(user_policy_key_file_, &current_key));
+  }
   EXPECT_EQ(rotated_key, current_key);
 }
 #endif
diff --git a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
index a9fe8d7..68cdc80 100644
--- a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
+++ b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
@@ -120,9 +120,18 @@
       this.$$('#next-button').focus();
     },
 
-    /** @private */
-    onExitRequested_: function() {
-      chrome.send('login.MultiDeviceSetupScreen.userActed', ['setup-finished']);
+    /**
+     * @param {!{detail:{didUserCompleteSetup: boolean}}} event
+     * @private
+     */
+    onExitRequested_: function(event) {
+      if (event.detail.didUserCompleteSetup) {
+        chrome.send(
+            'login.MultiDeviceSetupScreen.userActed', ['setup-accepted']);
+      } else {
+        chrome.send(
+            'login.MultiDeviceSetupScreen.userActed', ['setup-declined']);
+      }
     },
 
     /**
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/compressor_archive_minizip_unittest.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/compressor_archive_minizip_unittest.cc
index d07d3316..9f22a4c 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/compressor_archive_minizip_unittest.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/compressor_archive_minizip_unittest.cc
@@ -112,7 +112,7 @@
     return file_offset_;
   }
 
-  std::unique_ptr<std::string> Passphrase() override { return nullptr; }
+  base::Optional<std::string> Passphrase() override { return {}; }
 
   int64_t offset() override { return file_offset_; }
 
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
index 5b32737d..b91b9a16 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
@@ -389,20 +389,20 @@
   // Directories cannot be encrypted with the basic zip encrytion algorithm.
   if (((raw_file_info.flag & 1) != 0) && !is_directory) {
     do {
-      if (password_cache_ == nullptr) {
+      if (!password_cache_) {
         // Save passphrase for upcoming file requests.
         password_cache_ = reader()->Passphrase();
-        // check if |password_cache_| is nullptr in case when user clicks Cancel
-        if (password_cache_ == nullptr) {
+        // check if |password_cache_| is empty in case when user clicks Cancel
+        if (!password_cache_) {
           return false;
         }
       }
 
-      open_result =
-          unzOpenCurrentFilePassword(zip_file_, password_cache_.get()->c_str());
+      open_result = unzOpenCurrentFilePassword(zip_file_,
+                                               password_cache_.value().c_str());
 
       // If password is incorrect then password cache ought to be reseted.
-      if (open_result == UNZ_BADPASSWORD && password_cache_ != nullptr)
+      if (open_result == UNZ_BADPASSWORD)
         password_cache_.reset();
 
     } while (open_result == UNZ_BADPASSWORD);
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h
index be871270..436fd06 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.h
@@ -9,11 +9,11 @@
 #include <memory>
 #include <string>
 
+#include "base/optional.h"
+#include "chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive.h"
 #include "third_party/minizip/src/unzip.h"
 #include "third_party/minizip/src/zip.h"
 
-#include "chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive.h"
-
 // Defines an implementation of VolumeArchive that wraps all minizip
 // operations.
 class VolumeArchiveMinizip : public VolumeArchive {
@@ -149,7 +149,7 @@
   bool decompressed_error_;
 
   // The password cache to access password protected files.
-  std::unique_ptr<std::string> password_cache_;
+  base::Optional<std::string> password_cache_;
 };
 
 #endif  // CHROME_BROWSER_RESOURCES_CHROMEOS_ZIP_ARCHIVER_CPP_VOLUME_ARCHIVE_MINIZIP_H_
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
index effed48..67f68ce 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/md5.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/strings/string_piece.h"
 #include "chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive.h"
@@ -24,6 +25,8 @@
 
 namespace {
 
+constexpr char kEncryptedZipPassphrase[] = "test123";
+
 class TestVolumeReader : public VolumeReader {
  public:
   explicit TestVolumeReader(base::FilePath path)
@@ -40,15 +43,20 @@
     return file_.Seek(whence, offset);
   }
 
-  std::unique_ptr<std::string> Passphrase() override { return nullptr; }
+  base::Optional<std::string> Passphrase() override { return passphrase_; }
 
   int64_t offset() override { return Seek(0, base::File::FROM_CURRENT); }
 
   int64_t archive_size() override { return file_.GetLength(); }
 
+  void set_passphrase(base::Optional<std::string> passphrase) {
+    passphrase_ = std::move(passphrase);
+  }
+
  private:
   base::File file_;
   std::vector<char> buffer_;
+  base::Optional<std::string> passphrase_;
 };
 
 class VolumeArchiveMinizipTest : public testing::Test {
@@ -88,6 +96,13 @@
     {"dir/file3", {56, false, 1407913020, "bffbca4992b32db8ed72bfc2c88e7f11"}},
 };
 
+const std::map<std::string, FileInfo> kEncryptedZipFiles = {
+    {"file1", {15, false, 1407912954, "b4d9b82bb1cd97aa6191843149df18e6"}},
+    {"file2", {33, false, 1407912974, "b864e9456deb246b018c49ef831f7ca7"}},
+    {"dir/", {0, true, 1407913020, nullptr}},
+    {"dir/file3", {56, false, 1407913020, "bffbca4992b32db8ed72bfc2c88e7f11"}},
+};
+
 TEST_F(VolumeArchiveMinizipTest, Basic) {
   std::unique_ptr<TestVolumeReader> reader =
       std::make_unique<TestVolumeReader>(GetTestZipPath("small_zip.zip"));
@@ -185,4 +200,51 @@
   }
 }
 
+TEST_F(VolumeArchiveMinizipTest, Encrypted) {
+  std::unique_ptr<TestVolumeReader> reader =
+      std::make_unique<TestVolumeReader>(GetTestZipPath("encrypted.zip"));
+  reader->set_passphrase(
+      base::make_optional<std::string>(kEncryptedZipPassphrase));
+  VolumeArchiveMinizip archive(std::move(reader));
+  ASSERT_TRUE(archive.Init(""));
+
+  for (auto it : kEncryptedZipFiles) {
+    EXPECT_TRUE(archive.SeekHeader(it.first));
+    std::string file_path;
+    bool is_utf8 = false;
+    int64_t size = -1;
+    bool is_directory = false;
+    time_t mod_time = 0;
+    auto result = archive.GetCurrentFileInfo(&file_path, &is_utf8, &size,
+                                             &is_directory, &mod_time);
+    EXPECT_EQ(result, VolumeArchive::RESULT_SUCCESS);
+    EXPECT_EQ(file_path, it.first);
+    EXPECT_EQ(size, it.second.size);
+    EXPECT_EQ(is_directory, it.second.is_directory);
+    EXPECT_EQ(mod_time, it.second.mod_time);
+
+    if (it.second.is_directory)
+      continue;
+
+    base::MD5Context ctx;
+    base::MD5Init(&ctx);
+    const char* buffer = nullptr;
+    int64_t offset = 0;
+    while (offset < it.second.size) {
+      int64_t read = archive.ReadData(offset, it.second.size - offset, &buffer);
+      ASSERT_GT(read, 0);
+      EXPECT_LE(read, it.second.size - offset);
+      base::MD5Update(&ctx, base::StringPiece(buffer, read));
+      offset += read;
+    }
+    EXPECT_EQ(it.second.size, offset);
+    EXPECT_EQ(0, archive.ReadData(offset, 1, &buffer));
+
+    base::MD5Digest digest;
+    base::MD5Final(&digest, &ctx);
+    std::string md5_sum = base::MD5DigestToBase16(digest);
+    EXPECT_EQ(md5_sum, it.second.md5_sum);
+  }
+}
+
 }  // namespace
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader.h b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader.h
index d091f36..a2b9e14 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader.h
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/files/file.h"
+#include "base/optional.h"
 
 // Defines a reader for archive volumes. This class is used by minizip
 // for custom reads.
@@ -34,9 +35,9 @@
   // http://www.cplusplus.com/reference/cstdio/fseek/
   virtual int64_t Seek(int64_t offset, base::File::Whence whence) = 0;
 
-  // Fetches a passphrase for reading. If the passphrase is not available it
-  // returns nullptr.
-  virtual std::unique_ptr<std::string> Passphrase() = 0;
+  // Fetches a passphrase for reading. If the passphrase is not available, the
+  // returned Optional will have no value.
+  virtual base::Optional<std::string> Passphrase() = 0;
 
   virtual int64_t offset() = 0;
 
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.cc
index 8121bba..90deda14 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.cc
@@ -212,15 +212,14 @@
   request_id_ = request_id;
 }
 
-std::unique_ptr<std::string> VolumeReaderJavaScriptStream::Passphrase() {
-  std::unique_ptr<std::string> result;
+base::Optional<std::string> VolumeReaderJavaScriptStream::Passphrase() {
   // The error is not recoverable. Once passphrase fails to be provided, it is
   // never asked again. Note, that still users are able to retry entering the
   // password, unless they click Cancel.
   {
     base::AutoLock al(shared_state_lock_);
     if (passphrase_error_) {
-      return result;
+      return {};
     }
   }
 
@@ -232,10 +231,10 @@
   // TODO(amistry): Handle spurious wakeups.
   available_passphrase_cond_.Wait();
 
-  if (!passphrase_error_)
-    result.reset(new std::string(available_passphrase_));
+  if (passphrase_error_)
+    return {};
 
-  return result;
+  return base::make_optional<std::string>(available_passphrase_);
 }
 
 void VolumeReaderJavaScriptStream::RequestChunk(int64_t length) {
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.h b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.h
index 557fbef7..db83d1f 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.h
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_reader_javascript_stream.h
@@ -71,7 +71,7 @@
   // See volume_reader.h for description. The method blocks on
   // available_passphrase_cond_. SetPassphraseAndSignal should unblock it from
   // another thread.
-  std::unique_ptr<std::string> Passphrase() override;
+  base::Optional<std::string> Passphrase() override;
 
   int64_t offset() override;
 
diff --git a/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/test-files/encrypted.zip b/chrome/browser/resources/chromeos/zip_archiver/test/data/encrypted.zip
similarity index 100%
rename from chrome/browser/resources/chromeos/zip_archiver/unpacker-test/test-files/encrypted.zip
rename to chrome/browser/resources/chromeos/zip_archiver/test/data/encrypted.zip
Binary files differ
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.js b/chrome/browser/resources/local_ntp/custom_links_edit.js
index dab6e11b..9c634f64 100644
--- a/chrome/browser/resources/local_ntp/custom_links_edit.js
+++ b/chrome/browser/resources/local_ntp/custom_links_edit.js
@@ -57,14 +57,6 @@
 
 
 /**
- * Time in ms to wait for the |doesUrlResolve| callback before automatically
- * closing the dialog. Keep in sync with InstantService.
- * @const {number}
- */
-const DIALOG_TIMEOUT = 2000;
-
-
-/**
  * List of parameters passed by query args.
  * @type {Object}
  */
@@ -104,37 +96,6 @@
 
 
 /**
- * The timeout function for |updateLink| that can be triggered early by the
- * |doesUrlResolve| callback. Only set if we are waiting for the callback.
- * @type {?Object}
- */
-let urlResolvesCallbackHandler;
-
-
-/**
- * Returns a timeout for |updateLink| that can be executed early by the
- * |doesUrlResolve| callback. Otherwise, calls |updateLink| and closes the
- * dialog.
- * @param {string} newUrl The new custom link URL.
- * @param {string} newTitle The new custom link title.
- * @param {number} delay The timeout delay.
- * @return {Object}
- */
-function createUpdateLinkTimeout(newUrl, newTitle, delay) {
-  let timeoutId = window.setTimeout(() => {
-    // Do not update the URL scheme if the dialog times out.
-    updateLink(newUrl, newTitle, true);
-  }, delay);
-  return {
-    trigger: (resolves) => {
-      window.clearTimeout(timeoutId);
-      updateLink(newUrl, newTitle, resolves);
-    }
-  };
-}
-
-
-/**
  * Handler for the 'linkData' message from the host page. Pre-populates the url
  * and title fields with link's data obtained using the rid. Called if we are
  * editing an existing link.
@@ -181,55 +142,22 @@
   let newTitle = '';
 
   const urlValue = $(IDS.URL_FIELD).value;
-  const titleValue = $(IDS.TITLE_FIELD).value;
+  if (urlValue != prepopulatedLink.url) {
+    newUrl = chrome.embeddedSearch.newTabPage.fixupAndValidateUrl(urlValue);
+    // Show error message for invalid urls.
+    if (!newUrl) {
+      showInvalidUrlUntilTextInput();
+      disableSubmitUntilTextInput();
+      return;
+    }
+  }
 
+  const titleValue = $(IDS.TITLE_FIELD).value;
   if (!titleValue)  // Set the URL input as the title if no title is provided.
     newTitle = urlValue;
   else if (titleValue != prepopulatedLink.title)
     newTitle = titleValue;
 
-  // No need to validate if the URL was not changed.
-  if (urlValue == prepopulatedLink.url) {
-    updateLink(newUrl, newTitle, true);
-    return;
-  }
-
-  newUrl = chrome.embeddedSearch.newTabPage.fixupAndValidateUrl(urlValue);
-
-  // Show error message for invalid urls.
-  if (!newUrl) {
-    showInvalidUrlUntilTextInput();
-    disableSubmitUntilTextInput();
-    return;
-  }
-
-  // If the new URL uses the default "https" scheme, we need to check if it can
-  // resolve. Disable submit and wait for the |doesUrlResolve| callback. If it
-  // does not resolve, replace "https" with "http" before calling update.
-  $(IDS.DONE).disabled = true;  // Re-enabled when the dialog closes.
-  // Automatically close the dialog and call update if the callback has not
-  // returned before |DIALOG_TIMEOUT|.
-  urlResolvesCallbackHandler =
-      createUpdateLinkTimeout(newUrl, newTitle, DIALOG_TIMEOUT);
-}
-
-
-/**
- * Calls the EmbeddedSearchAPI to add/update the link. If the new URl does not
- * resolve, updates the default "https" scheme to "http". Closes the dialog.
- * @param {string} newUrl The new custom link URL.
- * @param {string} newTitle The new custom link title.
- * @param {boolean} resolves True if the URL resolves.
- */
-function updateLink(newUrl, newTitle, resolves) {
-  // Clear callback handler.
-  urlResolvesCallbackHandler = null;
-
-  // If the URL does not resolve, use "http" instead of the default "https"
-  // scheme.
-  if (!!newUrl && !resolves && newUrl.startsWith('https'))
-    newUrl = newUrl.replace('https', 'http');
-
   // Update the link only if a field was changed.
   if (!!newUrl || !!newTitle) {
     chrome.embeddedSearch.newTabPage.updateCustomLink(
@@ -312,10 +240,6 @@
     window.setTimeout(() => {
       $(IDS.TITLE_FIELD).select();
     }, 10);
-  } else if (cmd === 'doesUrlResolve') {
-    // Ignore any unexpected callbacks.
-    if (!!urlResolvesCallbackHandler)
-      urlResolvesCallbackHandler.trigger(args.resolves);
   }
 }
 
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index 2a93f798..bf23ecf 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -635,19 +635,6 @@
 
 
 /**
- * Callback for embeddedSearch.newTabPage.ondoesurlresolve. Called when we
- * determine if a custom link URL can resolve. Notifies the edit custom link
- * dialog with the result.
- * @param {boolean} resolves True if the URL can resolve.
- */
-function onDoesUrlResolve(resolves) {
-  $(IDS.CUSTOM_LINKS_EDIT_IFRAME)
-      .contentWindow.postMessage(
-          {cmd: 'doesUrlResolve', resolves: resolves}, '*');
-}
-
-
-/**
  * Shows the Most Visited pop-up notification and triggers a delay to hide it.
  * The message will be set to |msg|.
  * @param {string} msg The notification message.
@@ -1112,7 +1099,6 @@
       ntpApiHandle.onaddcustomlinkdone = onAddCustomLinkDone;
       ntpApiHandle.onupdatecustomlinkdone = onUpdateCustomLinkDone;
       ntpApiHandle.ondeletecustomlinkdone = onDeleteCustomLinkDone;
-      ntpApiHandle.doesurlresolve = onDoesUrlResolve;
     }
 
     if (configData.isCustomBackgroundsEnabled ||
diff --git a/chrome/browser/resources/settings/downloads_page/BUILD.gn b/chrome/browser/resources/settings/downloads_page/BUILD.gn
index a4c1ddd2..422f561 100644
--- a/chrome/browser/resources/settings/downloads_page/BUILD.gn
+++ b/chrome/browser/resources/settings/downloads_page/BUILD.gn
@@ -6,10 +6,8 @@
 
 js_type_check("closure_compile") {
   deps = [
-    ":add_smb_share_dialog",
     ":downloads_browser_proxy",
     ":downloads_page",
-    ":smb_browser_proxy",
     ":smb_shares_page",
   ]
 }
@@ -23,30 +21,15 @@
 
 js_library("smb_shares_page") {
   deps = [
-    ":add_smb_share_dialog",
     "..:route",
+    "//ui/webui/resources/cr_components/chromeos/smb_shares:smb_browser_proxy",
     "//ui/webui/resources/js:web_ui_listener_behavior",
   ]
 }
 
-js_library("add_smb_share_dialog") {
-  deps = [
-    ":smb_browser_proxy",
-    "//ui/webui/resources/js:i18n_behavior",
-    "//ui/webui/resources/js:web_ui_listener_behavior",
-  ]
-}
-
-js_library("smb_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
-}
-
 js_library("downloads_page") {
   deps = [
     ":downloads_browser_proxy",
-    ":smb_browser_proxy",
     "..:page_visibility",
     "..:route",
     "../prefs:prefs_behavior",
diff --git a/chrome/browser/resources/settings/downloads_page/smb_shares_page.html b/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
index 584488a..9a9f5c7e 100644
--- a/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
+++ b/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
@@ -10,7 +11,6 @@
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
-<link rel="import" href="add_smb_share_dialog.html">
 
 <dom-module id="settings-smb-shares-page">
   <template>
@@ -39,8 +39,8 @@
       </paper-button>
     </div>
     <template is="dom-if" if="[[showAddSmbDialog_]]" restamp>
-      <settings-add-smb-share-dialog on-close="onAddSmbDialogClosed_">
-      </settings-add-smb-share-dialog>
+      <add-smb-share-dialog on-close="onAddSmbDialogClosed_">
+      </add-smb-share-dialog>
     </template>
 
     <cr-toast id="errorToast" duration="3000">
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index fe651b8..bf6e6f9 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -585,24 +585,12 @@
                  type="chrome_html"
                  preprocess="true" />
       <if expr="chromeos">
-        <structure name="IDR_SETTINGS_SMB_BROWSER_PROXY_HTML"
-                   file="downloads_page/smb_browser_proxy.html"
-                   type="chrome_html" />
-        <structure name="IDR_SETTINGS_SMB_BROWSER_PROXY_JS"
-                   file="downloads_page/smb_browser_proxy.js"
-                   type="chrome_html" />
         <structure name="IDR_SETTINGS_SMB_SHARES_PAGE_HTML"
                    file="downloads_page/smb_shares_page.html"
                    type="chrome_html" />
         <structure name="IDR_SETTINGS_SMB_SHARES_PAGE_JS"
                    file="downloads_page/smb_shares_page.js"
                    type="chrome_html" />
-        <structure name="IDR_SETTINGS_ADD_SMB_SHARE_DIALOG_HTML"
-                   file="downloads_page/add_smb_share_dialog.html"
-                   type="chrome_html" />
-        <structure name="IDR_SETTINGS_ADD_SMB_SHARE_DIALOG_JS"
-                   file="downloads_page/add_smb_share_dialog.js"
-                   type="chrome_html" />
       </if>
       <structure name="IDR_SETTINGS_I18n_SETUP_HTML"
                  file="i18n_setup.html"
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn
index 9d52f6c..8bfac0ad 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn
@@ -13,6 +13,7 @@
 
 js_library("nux_email") {
   deps = [
+    "../:navigation_behavior",
     "../shared:nux_types",
   ]
 }
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html
index 20ae121..5299633 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html
@@ -11,7 +11,6 @@
 <link rel="import" href="../navigation_behavior.html">
 <link rel="import" href="../shared/bookmark_proxy.html">
 <link rel="import" href="../shared/chooser_shared_css.html">
-<link rel="import" href="../shared/i18n_setup.html">
 <link rel="import" href="../shared/step_indicator.html">
 <link rel="import" href="nux_email_proxy.html">
 
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
index 369cc5d..e5ba7bd 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
@@ -27,11 +27,7 @@
      */
     emailList_: Array,
 
-    /** @private */
-    bookmarkBarWasShown_: {
-      type: Boolean,
-      value: loadTimeData.getBoolean('bookmark_bar_shown'),
-    },
+    bookmarkBarWasShown: Boolean,
 
     /** @private */
     finalized_: Boolean,
@@ -165,7 +161,7 @@
             this.selectedEmailProvider_.bookmarkId = results.id;
           });
     } else {
-      this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown_);
+      this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown);
     }
 
     // Announcements are mutually exclusive, so keeping separate.
@@ -182,7 +178,7 @@
   onNoThanksClicked_: function() {
     this.finalized_ = true;
     this.revertBookmark_();
-    this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown_);
+    this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown);
     this.emailProxy_.recordNoThanks();
     welcome.navigateToNextStep();
   },
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html
index a67e594..bbe60e487 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html
@@ -1,6 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="../navigation_behavior.html">
+<link rel="import" href="../shared/bookmark_proxy.html">
 <link rel="import" href="email_chooser.html">
 
 <dom-module id="nux-email">
@@ -40,4 +42,4 @@
     </div>
   </template>
   <script src="nux_email.js"></script>
-</dom-module>
\ No newline at end of file
+</dom-module>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js
index dbad9df..ff4de6b 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js
@@ -5,8 +5,25 @@
 Polymer({
   is: 'nux-email',
 
+  behaviors: [welcome.NavigationBehavior],
+
   properties: {
     /** @type {nux.stepIndicatorModel} */
     indicatorModel: Object,
   },
+
+  /**
+   * Elements can override onRouteChange to handle route changes.
+   * Overrides function in behavior.
+   * @param {!welcome.Routes} route
+   * @param {number} step
+   */
+  onRouteChange: function(route, step) {
+    if (`step-${step}` == this.id) {
+      nux.BookmarkProxyImpl.getInstance().isBookmarkBarShown().then(
+          bookmarkBarShown => {
+            this.$.emailChooser.bookmarkBarWasShown = bookmarkBarShown;
+          });
+    }
+  },
 });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
index 7f33c22..e1b9f143 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
@@ -133,10 +133,9 @@
     /** @override */
     recordProviderSelected(providerId, length) {
       this.savedProvider_ = providerId;
-      // TODO(hcarmona): get enum's max from loadTimeData instead, since length
-      //     might not be accurate once we start localizing.
       chrome.metricsPrivate.recordEnumerationValue(
-          SELECTION_METRIC_NAME, providerId, length);
+          SELECTION_METRIC_NAME, providerId,
+          loadTimeData.getInteger('email_providers_count'));
     }
 
     /** @override */
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
index b1cfd67..35842df70 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
@@ -34,6 +34,8 @@
      */
     appList_: Array,
 
+    bookmarkBarWasShown: Boolean,
+
     hasAppsSelected: {
       type: Boolean,
       notify: true,
@@ -62,22 +64,20 @@
           // Default select all items.
           app.selected = true;
           this.updateBookmark(app);
-          // Icons only need to be added to the cache once.
-          this.appsProxy_.cacheBookmarkIcon(app.id);
         });
       });
     }
   },
 
-  /**
-   * Returns an array of booleans for each selected app.
-   * @return {!Array<boolean>}
-   */
-  getSelectedAppList() {
-    if (this.appList_)
-      return this.appList_.map(a => a.selected);
-    else
-      return [];
+  /** Called when bookmarks should be removed for all selected apps. */
+  removeAllBookmarks() {
+    this.appList_.forEach(app => {
+      if (app.selected) {
+        app.selected = false;
+        this.updateBookmark(app);
+      }
+    });
+    this.updateHasAppsSelected();
   },
 
   /**
@@ -96,6 +96,8 @@
           result => {
             item.bookmarkId = result.id;
           });
+      // Cache bookmark icon.
+      this.appsProxy_.cacheBookmarkIcon(item.id);
     } else if (!item.selected && item.bookmarkId) {
       this.bookmarkProxy_.removeBookmark(item.bookmarkId);
       item.bookmarkId = null;
@@ -111,7 +113,7 @@
     let item = e.model.item;
     e.model.set('item.selected', !item.selected);
     this.updateBookmark(item);
-    this.hasAppsSelected = this.computeHasAppsSelected_();
+    this.updateHasAppsSelected();
   },
 
   /**
@@ -131,10 +133,12 @@
   },
 
   /**
-   * @return {boolean}
+   * Updates the value of hasAppsSelected.
    * @private
    */
-  computeHasAppsSelected_: function() {
-    return this.appList_ && this.appList_.some(a => a.selected);
+  updateHasAppsSelected: function() {
+    this.hasAppsSelected = this.appList_ && this.appList_.some(a => a.selected);
+    if (!this.hasAppsSelected)
+      this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown);
   },
 });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
index 5652628..52c9d7d 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../navigation_behavior.html">
+<link rel="import" href="../shared/bookmark_proxy.html">
 <link rel="import" href="../shared/step_indicator.html">
 <link rel="import" href="apps_chooser.html">
 <link rel="import" href="nux_google_apps_proxy.html">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js
index 5825bcad..70ccd5e 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js
@@ -22,13 +22,19 @@
    * @param {number} step
    */
   onRouteChange: function(route, step) {
-    if (`step-${step}` == this.id)
+    if (`step-${step}` == this.id) {
+      nux.BookmarkProxyImpl.getInstance().isBookmarkBarShown().then(
+          bookmarkBarShown => {
+            this.$.appChooser.bookmarkBarWasShown = bookmarkBarShown;
+          });
       this.$.appChooser.populateAllBookmarks();
+    }
   },
 
   /** @private */
   onNoThanksClicked_: function() {
     // TODO(hcarmona): Add metrics.
+    this.$.appChooser.removeAllBookmarks();
     welcome.navigateToNextStep();
   },
 
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
index 8d79153..391c8a0bd 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
+++ b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
@@ -145,10 +145,12 @@
                  type="chrome_html" />
       <structure name="IDR_NUX_SET_AS_DEFAULT_HTML"
                  file="set_as_default\nux_set_as_default.html"
-                 type="chrome_html" />
+                 type="chrome_html"
+                 preprocess="true"/>
       <structure name="IDR_NUX_SET_AS_DEFAULT_JS"
                  file="set_as_default\nux_set_as_default.js"
-                 type="chrome_html" />
+                 type="chrome_html"
+                 preprocess="true"/>
       <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_HTML"
                  file="set_as_default\nux_set_as_default_proxy.html"
                  type="chrome_html" />
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
index 9cb42d0..0e62f3f6 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
@@ -15,6 +15,7 @@
     ":nux_set_as_default_proxy",
     "../:navigation_behavior",
     "../shared:nux_types",
+    "//ui/webui/resources/js:load_time_data",
     "//ui/webui/resources/js:web_ui_listener_behavior",
   ]
 }
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
index ed2b4f5..499f1cfb 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -1,13 +1,17 @@
 <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/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../navigation_behavior.html">
-<link rel="import" href="nux_set_as_default_proxy.html">
+<link rel="import" href="../shared/i18n_setup.html">
 <link rel="import" href="../shared/step_indicator.html">
+<link rel="import" href="nux_set_as_default_proxy.html">
+<if expr="is_win">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+</if>
 
 <dom-module id="nux-set-as-default">
   <template>
@@ -57,6 +61,15 @@
         justify-content: space-between;
         margin-top: 64px;
       }
+
+<if expr="is_win">
+      iron-icon[icon='cr:open-in-new'] {
+        height: 20px;
+        margin-left: 6px;
+        margin-right: -10px;
+        width: 20px;
+      }
+</if>
     </style>
     <div class="container">
       <div class="logo"></div>
@@ -70,6 +83,9 @@
         <step-indicator model="[[indicatorModel]]"></step-indicator>
         <paper-button class="action-button" on-click="onSetDefaultClick_">
           $i18n{setDefaultConfirm}
+<if expr="is_win">
+          <iron-icon icon="cr:open-in-new" hidden="[[!isWin10]]"></iron-icon>
+</if>
         </paper-button>
       </div>
     </div>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
index 9971a83..00b565c51 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
@@ -13,6 +13,13 @@
   properties: {
     /** @type {nux.stepIndicatorModel} */
     indicatorModel: Object,
+
+    // <if expr="is_win">
+    isWin10: {
+      type: Boolean,
+      value: loadTimeData.getBoolean('is_win10'),
+    },
+    // </if>
   },
 
   /** @override */
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js
index bc64edfb..d178982 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js
@@ -25,6 +25,9 @@
 
     /** @param {boolean} show */
     toggleBookmarkBar(show) {}
+
+    /** @return {!Promise<boolean>} */
+    isBookmarkBarShown() {}
   }
 
   /** @implements {nux.BookmarkProxy} */
@@ -43,6 +46,11 @@
     toggleBookmarkBar(show) {
       chrome.send('toggleBookmarkBar', [show]);
     }
+
+    /** @override */
+    isBookmarkBarShown() {
+      return cr.sendWithPromise('isBookmarkBarShown');
+    }
   }
 
   cr.addSingletonGetter(BookmarkProxyImpl);
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index 4d85071..7d0cfb7 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -8,17 +8,12 @@
 
 #include "base/bind.h"
 #include "base/files/file_util.h"
-#include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/time.h"
 #include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/background/ntp_background_service.h"
@@ -46,7 +41,6 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/search/search.h"
-#include "components/search/url_validity_checker_impl.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/search_engines/template_url_service_observer.h"
 #include "components/sync_preferences/pref_service_syncable.h"
@@ -56,7 +50,6 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/url_data_source.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/gfx/color_utils.h"
 
 namespace {
@@ -67,10 +60,6 @@
 const char kNtpCustomBackgroundAttributionActionURL[] =
     "attribution_action_url";
 
-// Time in seconds before the UI add/edit custom link dialog automatically
-// closes. Keep in sync with custom_edit_dialog.js.
-const int kCustomLinkDialogTimeoutSeconds = 2;
-
 base::DictionaryValue GetBackgroundInfoAsDict(
     const GURL& background_url,
     const std::string& attribution_line_1,
@@ -351,45 +340,6 @@
   return false;
 }
 
-void InstantService::DoesUrlResolve(
-    const GURL& url,
-    chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback) {
-  if (!features::IsCustomLinksEnabled())
-    return;
-
-  net::NetworkTrafficAnnotationTag traffic_annotation =
-      net::DefineNetworkTrafficAnnotation("ntp_custom_link_checker_request", R"(
-        semantics {
-          sender: "New Tab Page Custom Links"
-          description:
-            "When a user adds/edits a custom link to the New Tab Page without "
-            "specifying the URL scheme, it defaults to HTTPS. This request "
-            "checks if the URL resolves with HTTPS; if not, the URL will "
-            "default to HTTP instead."
-          trigger:
-            "When a user adds/edits a custom link without specifying the URL "
-            "scheme."
-          data: "An HTTP HEAD request to the user specified URL."
-          destination: WEBSITE
-        }
-        policy {
-          cookies_allowed: NO
-          setting:
-            "This feature cannot be independently disabled in settings, but it "
-            "is only activated by direct user action. Note: This will be "
-            "disabled if custom links (chrome://flags#ntp-custom-links) is "
-            "disabled."
-          policy_exception_justification:
-            "Not implemented, considered not useful."
-        })");
-
-  UrlValidityChecker* url_checker = GetUrlValidityChecker();
-  url_checker->DoesUrlResolve(
-      url, traffic_annotation,
-      base::BindOnce(&InstantService::OnDoesUrlResolveComplete,
-                     weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
-}
-
 void InstantService::UpdateThemeInfo() {
   // Initialize |theme_info_| if necessary.
   if (!theme_info_) {
@@ -478,27 +428,6 @@
   instant_io_context_ = NULL;
 }
 
-void InstantService::OnDoesUrlResolveComplete(
-    const GURL& url,
-    chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback,
-    bool resolves,
-    base::TimeDelta duration) {
-  bool timeout = false;
-  if (!resolves) {
-    // Internally update the default "https" scheme to "http" if UI dialog has
-    // already timed out.
-    if (duration >
-        base::TimeDelta::FromSeconds(kCustomLinkDialogTimeoutSeconds)) {
-      GURL::Replacements replacements;
-      replacements.SetSchemeStr(url::kHttpScheme);
-      GURL new_url = url.ReplaceComponents(replacements);
-      UpdateCustomLink(url, new_url, /*new_title=*/std::string());
-      timeout = true;
-    }
-  }
-  std::move(callback).Run(resolves, timeout);
-}
-
 void InstantService::Observe(int type,
                              const content::NotificationSource& source,
                              const content::NotificationDetails& details) {
@@ -818,17 +747,6 @@
       base::BindOnce(IgnoreResult(&base::DeleteFile), path, false));
 }
 
-UrlValidityChecker* InstantService::GetUrlValidityChecker() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (url_checker_for_testing_ != nullptr)
-    return url_checker_for_testing_;
-  static base::NoDestructor<UrlValidityCheckerImpl> checker(
-      g_browser_process->system_network_context_manager()
-          ->GetSharedURLLoaderFactory(),
-      base::DefaultTickClock::GetInstance());
-  return checker.get();
-}
-
 void InstantService::AddValidBackdropUrlForTesting(const GURL& url) const {
   background_service_->AddValidBackdropUrlForTesting(url);
 }
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h
index a5f585be..89752c1 100644
--- a/chrome/browser/search/instant_service.h
+++ b/chrome/browser/search/instant_service.h
@@ -16,14 +16,12 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "build/build_config.h"
-#include "chrome/common/search.mojom.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/ntp_tiles/most_visited_sites.h"
 #include "components/ntp_tiles/ntp_tile.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_registry_simple.h"
-#include "components/search/url_validity_checker.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "url/gurl.h"
@@ -101,15 +99,6 @@
   // using a non-Google search provider.
   bool ResetCustomLinks();
 
-  // Invoked during the add/update a custom link flow. Creates a request to
-  // check if |url| resolves to an existing page and notifies the frontend of
-  // the result. This will be used to determine if we need to use "http" instead
-  // of the default "https" scheme for the link's URL. Custom links must be
-  // enabled.
-  void DoesUrlResolve(
-      const GURL& url,
-      chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback);
-
   // Invoked by the InstantController to update theme information for NTP.
   //
   // TODO(kmadhusu): Invoking this from InstantController shouldn't be
@@ -141,11 +130,6 @@
 
   void AddValidBackdropUrlForTesting(const GURL& url) const;
 
-  // Used for testing.
-  void SetUrlValidityCheckerForTesting(UrlValidityChecker* url_checker) {
-    url_checker_for_testing_ = url_checker;
-  }
-
  private:
   class SearchProviderObserver;
 
@@ -158,18 +142,6 @@
   // KeyedService:
   void Shutdown() override;
 
-  // Called when the request from |DoesUrlResolve| finishes. Invokes the
-  // associated callback with the request status.
-  //
-  // If the request exceeded the UI dialog timeout and the URL did not resolve,
-  // calls |UpdateCustomLink| to internally update the link's default "https"
-  // scheme to "http".
-  void OnDoesUrlResolveComplete(
-      const GURL& url,
-      chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback,
-      bool resolves,
-      base::TimeDelta duration);
-
   // content::NotificationObserver:
   void Observe(int type,
                const content::NotificationSource& source,
@@ -208,11 +180,6 @@
   // chrome-search://local-ntp/background.jpg
   void SetBackgroundToLocalResource();
 
-  // Returns the owned instance of UrlValidityChecker or
-  // |url_checker_for_testing_| if not null. Should only be called from the UI
-  // thread.
-  UrlValidityChecker* GetUrlValidityChecker();
-
   Profile* const profile_;
 
   // The process ids associated with Instant processes.
@@ -236,9 +203,6 @@
   // Keeps track of any changes in search engine provider. May be null.
   std::unique_ptr<SearchProviderObserver> search_provider_observer_;
 
-  // Test UrlValidityChecker used for testing.
-  UrlValidityChecker* url_checker_for_testing_ = nullptr;
-
   PrefChangeRegistrar pref_change_registrar_;
 
   PrefService* pref_service_;
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc
index 5f85241..8b6ab7e 100644
--- a/chrome/browser/search/instant_service_unittest.cc
+++ b/chrome/browser/search/instant_service_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/files/file_util.h"
 #include "base/path_service.h"
-#include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/search/background/ntp_background_service.h"
 #include "chrome/browser/search/instant_unittest_base.h"
@@ -20,43 +19,12 @@
 #include "components/ntp_tiles/constants.h"
 #include "components/ntp_tiles/ntp_tile.h"
 #include "components/ntp_tiles/section_type.h"
-#include "components/search/url_validity_checker.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using testing::StrictMock;
-using testing::_;
-
 using InstantServiceTest = InstantUnitTestBase;
 
-namespace {
-
-ACTION_TEMPLATE(InvokeCallbackArgument,
-                HAS_1_TEMPLATE_PARAMS(int, k),
-                AND_2_VALUE_PARAMS(p0, p1)) {
-  return std::move(std::get<k>(args)).Run(p0, p1);
-}
-
-class MockUrlValidityChecker : public UrlValidityChecker {
- public:
-  MockUrlValidityChecker() {}
-  ~MockUrlValidityChecker() override {}
-
-  void DoesUrlResolve(const GURL& url,
-                      net::NetworkTrafficAnnotationTag traffic_annotation,
-                      UrlValidityCheckerCallback callback) override {
-    DoDoesUrlResolve(url, traffic_annotation, callback);
-  }
-  MOCK_METHOD3(DoDoesUrlResolve,
-               void(const GURL& url,
-                    net::NetworkTrafficAnnotationTag traffic_annotation,
-                    UrlValidityCheckerCallback& callback));
-};
-
-}  // namespace
-
 class InstantServiceTestCustomLinksEnabled : public InstantServiceTest {
  public:
   InstantServiceTestCustomLinksEnabled() {
@@ -64,13 +32,6 @@
   }
   ~InstantServiceTestCustomLinksEnabled() override {}
 
-  void SetUp() override {
-    InstantServiceTest::SetUp();
-    instant_service_->SetUrlValidityCheckerForTesting(&mock_url_checker_);
-  }
-
-  StrictMock<MockUrlValidityChecker> mock_url_checker_;
-
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 
@@ -137,45 +98,6 @@
   EXPECT_FALSE(instant_service_->ResetCustomLinks());
 }
 
-TEST_F(InstantServiceTestCustomLinksEnabled, DoesUrlResolve_OnSuccess) {
-  const GURL kUrl("https://www.foo.com");
-  base::TimeDelta expected_duration;
-
-  EXPECT_CALL(mock_url_checker_, DoDoesUrlResolve(kUrl, _, _))
-      .WillOnce(InvokeCallbackArgument<2>(true, expected_duration));
-
-  base::MockCallback<base::OnceCallback<void(bool, bool)>> callback;
-  EXPECT_CALL(callback, Run(true, false));
-  instant_service_->DoesUrlResolve(kUrl, callback.Get());
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InstantServiceTestCustomLinksEnabled, DoesUrlResolve_OnFailure) {
-  const GURL kUrl("https://www.foo.com");
-  const int kTimeAdvance = 20;
-  base::TimeDelta expected_duration;
-  base::TimeDelta expected_duration_timeout =
-      base::TimeDelta::FromSeconds(kTimeAdvance);
-
-  EXPECT_CALL(mock_url_checker_, DoDoesUrlResolve(kUrl, _, _))
-      .WillOnce(InvokeCallbackArgument<2>(false, expected_duration));
-
-  base::MockCallback<base::OnceCallback<void(bool, bool)>> callback;
-  EXPECT_CALL(callback, Run(false, false));
-  instant_service_->DoesUrlResolve(kUrl, callback.Get());
-  base::RunLoop().RunUntilIdle();
-
-  // Fake a timeout. Now InstantService should internally update the link and
-  // return true.
-  EXPECT_CALL(mock_url_checker_, DoDoesUrlResolve(kUrl, _, _))
-      .WillOnce(InvokeCallbackArgument<2>(false, expected_duration_timeout));
-
-  base::MockCallback<base::OnceCallback<void(bool, bool)>> callback_timeout;
-  EXPECT_CALL(callback_timeout, Run(false, true));
-  instant_service_->DoesUrlResolve(kUrl, callback_timeout.Get());
-  base::RunLoop().RunUntilIdle();
-}
-
 TEST_F(InstantServiceTestCustomBackgroundsEnabled, SetCustomBackgroundURL) {
   const GURL kUrl("https://www.foo.com");
 
diff --git a/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc
index d43e5fdf..bb73a30 100644
--- a/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/values.h"
 #include "chrome/browser/sync/test/integration/feature_toggler.h"
 #include "chrome/browser/sync/test/integration/preferences_helper.h"
@@ -95,6 +97,30 @@
   EXPECT_FALSE(pref_store->GetValue("testing.my-test-preference", &result));
 }
 
+// Regression test to verify that pagination during GetUpdates() contributes
+// properly to UMA histograms.
+IN_PROC_BROWSER_TEST_P(SingleClientPreferencesSyncTest,
+                       EmitModelTypeEntityChangeToUma) {
+  const int kNumEntities = 17;
+
+  fake_server_->SetMaxGetUpdatesBatchSize(7);
+
+  sync_pb::EntitySpecifics specifics;
+  for (int i = 0; i < kNumEntities; i++) {
+    specifics.mutable_preference()->set_name(base::StringPrintf("pref%d", i));
+    fake_server_->InjectEntity(
+        syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics(
+            specifics.preference().name(), specifics, /*creation_time=*/0,
+            /*last_modified_time=*/0));
+  }
+
+  base::HistogramTester histogram_tester;
+  ASSERT_TRUE(SetupSync());
+  EXPECT_EQ(kNumEntities, histogram_tester.GetBucketCount(
+                              "Sync.ModelTypeEntityChange3.PREFERENCE",
+                              /*REMOTE_INITIAL_UPDATE=*/5));
+}
+
 INSTANTIATE_TEST_CASE_P(USS,
                         SingleClientPreferencesSyncTest,
                         ::testing::Values(false, true));
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
index 3449963..47f1be8 100644
--- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -7,6 +7,7 @@
 #include "base/guid.h"
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
 #include "chrome/browser/sync/test/integration/feature_toggler.h"
 #include "chrome/browser/sync/test/integration/preferences_helper.h"
@@ -51,11 +52,22 @@
   ASSERT_TRUE(StringPrefMatchChecker(prefs::kHomePage).Wait());
   const std::string new_home_page = base::StringPrintf(
       "https://example.com/%s", base::GenerateGUID().c_str());
+
+  base::HistogramTester histogram_tester;
   ChangeStringPref(0, prefs::kHomePage, new_home_page);
   ASSERT_TRUE(StringPrefMatchChecker(prefs::kHomePage).Wait());
   for (int i = 0; i < num_clients(); ++i) {
     ASSERT_EQ(new_home_page, GetPrefs(i)->GetString(prefs::kHomePage));
   }
+
+  EXPECT_EQ(0, histogram_tester.GetBucketCount(
+                   "Sync.ModelTypeEntityChange3.PREFERENCE",
+                   /*REMOTE_INITIAL_UPDATE=*/5));
+  // Client 0 may or may not see its own reflection during the test, but at
+  // least client 1 should have received one update.
+  EXPECT_NE(0, histogram_tester.GetBucketCount(
+                   "Sync.ModelTypeEntityChange3.PREFERENCE",
+                   /*REMOTE_NON_INITIAL_UPDATE=*/4));
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientPreferencesSyncTest, E2E_ENABLED(BooleanPref)) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 461ec530..6ee5ea9 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1777,6 +1777,8 @@
       "views/close_bubble_on_tab_activation_helper.h",
       "views/hats/hats_bubble_view.cc",
       "views/hats/hats_bubble_view.h",
+      "views/profiles/incognito_window_count_view.cc",
+      "views/profiles/incognito_window_count_view.h",
       "webui/discards/discards_ui.cc",
       "webui/discards/discards_ui.h",
       "webui/signin/inline_login_handler.cc",
@@ -2051,8 +2053,6 @@
       "cocoa/touchbar/browser_window_touch_bar_controller.mm",
       "cocoa/touchbar/credit_card_autofill_touch_bar_controller.h",
       "cocoa/touchbar/credit_card_autofill_touch_bar_controller.mm",
-      "cocoa/touchbar/text_suggestions_touch_bar_controller.h",
-      "cocoa/touchbar/text_suggestions_touch_bar_controller.mm",
       "cocoa/touchbar/web_textfield_touch_bar_controller.h",
       "cocoa/touchbar/web_textfield_touch_bar_controller.mm",
       "cocoa/ui_localizer.h",
@@ -3308,6 +3308,8 @@
     sources += [
       "in_product_help/active_tab_tracker.cc",
       "in_product_help/active_tab_tracker.h",
+      "in_product_help/reopen_tab_in_product_help.cc",
+      "in_product_help/reopen_tab_in_product_help.h",
       "in_product_help/reopen_tab_in_product_help_trigger.cc",
       "in_product_help/reopen_tab_in_product_help_trigger.h",
     ]
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
index 6fd6916..c62328f 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/shell.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
@@ -85,8 +86,6 @@
   ChromeScreenshotGrabber* chrome_screenshot_grabber =
       ChromeScreenshotGrabber::Get();
   SetTestObserver(chrome_screenshot_grabber, this);
-  base::ScopedTempDir directory;
-  ASSERT_TRUE(directory.CreateUniqueTempDir());
   EXPECT_TRUE(chrome_screenshot_grabber->CanTakeScreenshot());
 
   chrome_screenshot_grabber->HandleTakeWindowScreenshot(
@@ -102,7 +101,10 @@
   EXPECT_TRUE(display_service_->GetNotification(std::string("screenshot")));
 
   EXPECT_EQ(ui::ScreenshotResult::SUCCESS, screenshot_result_);
-  EXPECT_TRUE(base::PathExists(screenshot_path_));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    EXPECT_TRUE(base::PathExists(screenshot_path_));
+  }
 
   EXPECT_FALSE(IsImageClipboardAvailable());
   ui::ClipboardMonitor::GetInstance()->AddObserver(this);
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window.cc b/chrome/browser/ui/ash/launcher/arc_app_window.cc
index c5791d9..c902b204 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window.cc
@@ -99,8 +99,11 @@
         profile_, extension_misc::EXTENSION_ICON_SMALL, this);
   }
   DCHECK(!image_fetching_);
-  base::AutoReset<bool> auto_image_fetching(&image_fetching_, true);
-  app_icon_loader_->FetchImage(app_shelf_id_.ToString());
+  std::string app_id = app_shelf_id_.ToString();
+  if (app_icon_loader_->CanLoadImageForApp(app_id)) {
+    base::AutoReset<bool> auto_image_fetching(&image_fetching_, true);
+    app_icon_loader_->FetchImage(app_id);
+  }
 }
 
 void ArcAppWindow::SetIcon(const gfx::ImageSkia& icon) {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
index ba73826..8469340 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "ash/public/cpp/app_list/internal_app_id_constants.h"
 #include "ash/public/cpp/app_types.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/public/cpp/window_properties.h"
@@ -35,6 +36,17 @@
 
 constexpr size_t kMaxIconPngSize = 64 * 1024;  // 64 kb
 
+// Generated as ArcAppListPrefs::GetAppIdByPackageName(
+//     "com.google.android.GoogleCameraArc").
+constexpr char kAndroidCameraAppId[] = "goamfaniemdfcajgcmmflhchgkmbngka";
+// Generated as ArcAppListPrefs::GetAppIdByPackageName(
+//     "com.android.camera2").
+constexpr char kAndroidLegacyCameraAppId[] = "obfofkigjfamlldmipdegnjlcpincibc";
+// Generated as ArcAppListPrefs::GetAppIdByPackageName(
+//     "com.android.googlecameramigration").
+constexpr char kAndroidCameraMigrationAppId[] =
+    "ngmkobaiicipbagcngcmilfkhejlnfci";
+
 }  // namespace
 
 // The information about the arc application window which has to be kept
@@ -295,8 +307,17 @@
   DCHECK(!GetAppWindowForTask(task_id));
   const std::string arc_app_id =
       ArcAppListPrefs::GetAppId(package_name, activity_name);
+  std::string app_id_consolidated = arc_app_id;
+
+  // For camera app, always put the internal app icon onto shelf.
+  if (arc_app_id.compare(kAndroidCameraAppId) == 0 ||
+      arc_app_id.compare(kAndroidCameraMigrationAppId) == 0 ||
+      arc_app_id.compare(kAndroidLegacyCameraAppId) == 0) {
+    app_id_consolidated = app_list::kInternalAppIdCamera;
+  }
+
   const arc::ArcAppShelfId arc_app_shelf_id =
-      arc::ArcAppShelfId::FromIntentAndAppId(intent, arc_app_id);
+      arc::ArcAppShelfId::FromIntentAndAppId(intent, app_id_consolidated);
   task_id_to_app_window_info_[task_id] =
       std::make_unique<AppWindowInfo>(arc_app_shelf_id, intent, package_name);
   // Don't create shelf icon for non-primary user.
diff --git a/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc
index 122bcb8..cb53a6e 100644
--- a/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/public/cpp/app_list/internal_app_id_constants.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/public/cpp/window_properties.h"
@@ -27,6 +28,8 @@
 
 namespace {
 
+constexpr char kChromeCameraAppId[] = "hfhhnacclhffhdffklopdkcgdhifgngh";
+
 // Get the ShelfID for a given |app_window|.
 ash::ShelfID GetShelfId(AppWindow* app_window) {
   // Set launch_id default value to an empty string. If showInShelf parameter
@@ -39,7 +42,12 @@
     else
       launch_id = base::StringPrintf("%d", app_window->session_id().id());
   }
-  return ash::ShelfID(app_window->extension_id(), launch_id);
+
+  // For camera app, always put the internal app icon onto shelf.
+  std::string app_id = app_window->extension_id();
+  if (app_id.compare(kChromeCameraAppId) == 0)
+    app_id = app_list::kInternalAppIdCamera;
+  return ash::ShelfID(app_id, launch_id);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h
index 2698a18..415ca1dc 100644
--- a/chrome/browser/ui/browser_dialogs.h
+++ b/chrome/browser/ui/browser_dialogs.h
@@ -282,6 +282,7 @@
   CROSTINI_UPGRADE = 89,
   HATS_BUBBLE = 90,
   CROSTINI_APP_RESTART = 91,
+  INCOGNITO_WINDOW_COUNTER = 92,
   MAX_VALUE
 };
 
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
index e5b4f1f..7ab3a03 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
@@ -5,6 +5,7 @@
 #include "extensions/browser/app_window/native_app_window.h"
 
 #import <Cocoa/Cocoa.h>
+#include <memory>
 
 #import "base/mac/foundation_util.h"
 #import "base/mac/mac_util.h"
@@ -12,6 +13,8 @@
 #import "base/mac/scoped_nsobject.h"
 #import "base/mac/sdk_forward_declarations.h"
 #include "base/macros.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
 #include "chrome/browser/apps/app_shim/test/app_shim_host_manager_test_api_mac.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
@@ -139,19 +142,19 @@
 
 namespace {
 
-class MockAppShimHost : public apps::AppShimHandler::Host {
+class MockAppShimHost : public AppShimHost {
  public:
-  MockAppShimHost() {}
+  MockAppShimHost()
+      : AppShimHost("app", base::FilePath("Profile")), weak_factory_(this) {}
   ~MockAppShimHost() override {}
 
-  MOCK_METHOD1(OnAppLaunchComplete, void(apps::AppShimLaunchResult));
-  MOCK_METHOD0(OnAppClosed, void());
-  MOCK_METHOD0(OnAppHide, void());
   MOCK_METHOD0(OnAppUnhideWithoutActivation, void());
-  MOCK_METHOD1(OnAppRequestUserAttention, void(apps::AppShimAttentionType));
-  MOCK_CONST_METHOD0(GetProfilePath, base::FilePath());
-  MOCK_CONST_METHOD0(GetAppId, std::string());
-  MOCK_CONST_METHOD0(GetViewsBridgeFactoryHost, views::BridgeFactoryHost*());
+  base::WeakPtr<MockAppShimHost> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
+
+ private:
+  base::WeakPtrFactory<MockAppShimHost> weak_factory_;
 };
 
 class MockExtensionAppShimHandler : public apps::ExtensionAppShimHandler {
@@ -176,7 +179,8 @@
   test_api.SetExtensionAppShimHandler(
       std::unique_ptr<apps::ExtensionAppShimHandler>(
           mock));  // Takes ownership.
-  MockAppShimHost mock_host;
+  base::WeakPtr<MockAppShimHost> mock_host =
+      (new MockAppShimHost)->GetWeakPtr();
 
   SetUpAppWithWindows(1);
   extensions::AppWindowRegistry::AppWindowList windows =
@@ -191,24 +195,24 @@
   EXPECT_FALSE([ns_window isVisible]);
 
   // Show notifies the shim to unhide.
-  EXPECT_CALL(mock_host, OnAppUnhideWithoutActivation());
-  EXPECT_CALL(*mock, FindHost(_, _)).WillOnce(Return(&mock_host));
+  EXPECT_CALL(*mock_host, OnAppUnhideWithoutActivation());
+  EXPECT_CALL(*mock, FindHost(_, _)).WillOnce(Return(mock_host.get()));
   app_window->Show(extensions::AppWindow::SHOW_ACTIVE);
   EXPECT_TRUE([ns_window isVisible]);
   testing::Mock::VerifyAndClearExpectations(mock);
-  testing::Mock::VerifyAndClearExpectations(&mock_host);
+  testing::Mock::VerifyAndClearExpectations(mock_host.get());
 
   // HideWithApp
   native_window->HideWithApp();
   EXPECT_FALSE([ns_window isVisible]);
 
   // Activate does the same.
-  EXPECT_CALL(mock_host, OnAppUnhideWithoutActivation());
-  EXPECT_CALL(*mock, FindHost(_, _)).WillOnce(Return(&mock_host));
+  EXPECT_CALL(*mock_host, OnAppUnhideWithoutActivation());
+  EXPECT_CALL(*mock, FindHost(_, _)).WillOnce(Return(mock_host.get()));
   native_window->Activate();
   EXPECT_TRUE([ns_window isVisible]);
   testing::Mock::VerifyAndClearExpectations(mock);
-  testing::Mock::VerifyAndClearExpectations(&mock_host);
+  testing::Mock::VerifyAndClearExpectations(mock_host.get());
 }
 
 // Test that NativeAppWindow and AppWindow fullscreen state is updated when
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
index c81dbbf..711e219d 100644
--- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.mm
@@ -117,7 +117,6 @@
 
 - (void)updateWebContents:(content::WebContents*)contents {
   [defaultTouchBar_ updateWebContents:contents];
-  [webTextfieldTouchBar_ updateWebContents:contents];
   [self invalidateTouchBar];
 }
 
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h
deleted file mode 100644
index 288fb93..0000000
--- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h
+++ /dev/null
@@ -1,78 +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.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TOUCHBAR_TEXT_SUGGESTIONS_TOUCH_BAR_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TOUCHBAR_TEXT_SUGGESTIONS_TOUCH_BAR_CONTROLLER_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include <memory>
-
-#import "base/mac/scoped_nsobject.h"
-#include "chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h"
-#import "ui/base/cocoa/touch_bar_forward_declarations.h"
-
-@class WebTextfieldTouchBarController;
-
-namespace content {
-class WebContents;
-}  // namespace content
-
-namespace gfx {
-class Range;
-}  // namespace gfx
-
-API_AVAILABLE(macos(10.12.2))
-@interface TextSuggestionsTouchBarController
-    : NSObject<NSTouchBarDelegate, NSCandidateListTouchBarItemDelegate>
-
-- (instancetype)initWithWebContents:(content::WebContents*)webContents
-                         controller:(WebTextfieldTouchBarController*)controller;
-
-- (NSTouchBar*)makeTouchBar;
-
-- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
-      makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier;
-
-// Creates a NSCandidateListTouchBarItem that contains text suggestions
-// based on the current text selection.
-- (NSCandidateListTouchBarItem*)makeCandidateListItem;
-
-- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
-     endSelectingCandidateAtIndex:(NSInteger)index;
-
-- (void)updateTextSelection:(const base::string16&)text
-                      range:(const gfx::Range&)range
-                     offset:(size_t)offset;
-
-// Returns a range from start to the end of the word that the cursor is
-// currently in.
-- (NSRange)editingWordRangeFromText:(const base::string16&)text
-                     cursorPosition:(size_t)cursor;
-
-- (void)requestSuggestions;
-
-// Select the range of the editing word and replace it with a suggestion
-// from the touch bar.
-- (void)replaceEditingWordWithSuggestion:(NSString*)text;
-
-@end
-
-@interface TextSuggestionsTouchBarController (ExposedForTesting)
-
-- (void)setWebContents:(content::WebContents*)webContents;
-- (content::WebContents*)webContents;
-- (void)setText:(NSString*)text;
-- (NSString*)text;
-- (void)setSelectionRange:(const gfx::Range&)range;
-- (gfx::Range)selectionRange;
-- (void)setSuggestions:(NSArray*)suggestions;
-- (NSArray*)suggestions;
-- (WebTextfieldTouchBarController*)controller;
-- (void)setShouldIgnoreReplacementSelection:(BOOL)shouldIgnore;
-- (void)setEditingWordRange:(const gfx::Range&)range offset:(size_t)offset;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TOUCHBAR_SUGGESTED_TEXT_TOUCH_BAR_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm
deleted file mode 100644
index 7f3fb1b..0000000
--- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm
+++ /dev/null
@@ -1,322 +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.
-
-#import "chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h"
-
-#include "base/i18n/break_iterator.h"
-#include "base/strings/sys_string_conversions.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#import "ui/base/cocoa/touch_bar_util.h"
-#include "ui/gfx/range/range.h"
-
-namespace {
-// Touch bar identifier.
-NSString* const kTextSuggestionsTouchBarId = @"text-suggestions";
-
-// Touch bar item identifiers.
-NSString* const kTextSuggestionsItemsTouchId = @"TEXT-SUGGESTIONS-ITEMS";
-}  // namespace
-
-namespace text_observer {
-class API_AVAILABLE(macos(10.12.2)) WebContentsTextObserver
-    : public content::WebContentsObserver {
- public:
-  WebContentsTextObserver(content::WebContents* web_contents,
-                          TextSuggestionsTouchBarController* owner)
-      : WebContentsObserver(web_contents), owner_(owner) {}
-
-  void UpdateWebContents(content::WebContents* web_contents) {
-    Observe(web_contents);
-  }
-
-  void DidChangeTextSelection(const base::string16& text,
-                              const gfx::Range& range,
-                              size_t offset) override {
-    [owner_ updateTextSelection:text range:range offset:offset];
-  }
-
-  void DidFinishLoad(content::RenderFrameHost* render_frame_host,
-                     const GURL& validated_url) override {
-    [owner_ updateTextSelection:base::string16() range:gfx::Range() offset:0];
-  }
-
- private:
-  TextSuggestionsTouchBarController* owner_;  // weak
-};
-}  // namespace text_observer
-
-@interface TextSuggestionsTouchBarController () {
-  // An observer for text selection changes.
-  std::unique_ptr<text_observer::WebContentsTextObserver> observer_;
-
-  // The WebContents in which text is being selected and replaced.
-  content::WebContents* webContents_;  // weak
-
-  // The WebTextfieldTouchBarController that invalidates the touch bar.
-  WebTextfieldTouchBarController* controller_;  // weak
-
-  // The text on which suggestions are based.
-  base::scoped_nsobject<NSString> text_;
-
-  // A list of NSTextCheckingResults containing text suggestions for |text_| at
-  // |selectionRange_|.
-  base::scoped_nsobject<NSArray> suggestions_;
-
-  // The currently selected range. If the range has length = 0, it is simply a
-  // cursor position.
-  NSRange selectionRange_;
-
-  // The range of the word that's currently being edited. Used when replacing
-  // the current editing word with a selected suggestion. If length = 0, there
-  // is no word currently being edited and the suggestion will be placed at the
-  // cursor.
-  NSRange editingWordRange_;
-
-  // The location of |editingWordRange_| within the total text, which may be
-  // longer than the text received on text selection update. Used for checking
-  // when to ignore replacement text selections.
-  NSRange offsetEditingWordRange_;
-
-  // When YES, -updateTextSelection:range: should ignore a text selection that
-  // is equal to the editing word range. Set to YES when
-  // -replaceEditingWordWithSuggestion: modifies the current text selection.
-  // Reset to NO when the text selection for replacing the editing word reaches
-  // -updateTextSelection:range:.
-  BOOL shouldIgnoreReplacementSelection_;
-}
-@end
-
-@implementation TextSuggestionsTouchBarController
-
-- (BOOL)isTextfieldFocused {
-  return webContents_ && webContents_->IsFocusedElementEditable();
-}
-
-- (instancetype)initWithWebContents:(content::WebContents*)webContents
-                         controller:
-                             (WebTextfieldTouchBarController*)controller {
-  if ((self = [super init])) {
-    webContents_ = webContents;
-    controller_ = controller;
-    observer_.reset(
-        new text_observer::WebContentsTextObserver(webContents_, self));
-    shouldIgnoreReplacementSelection_ = NO;
-  }
-
-  return self;
-}
-
-- (NSTouchBar*)makeTouchBar {
-  if (![self isTextfieldFocused] || ![suggestions_ count])
-    return nil;
-
-  base::scoped_nsobject<NSTouchBar> touchBar([[ui::NSTouchBar() alloc] init]);
-  [touchBar
-      setCustomizationIdentifier:ui::GetTouchBarId(kTextSuggestionsTouchBarId)];
-  [touchBar setDelegate:self];
-
-  [touchBar setDefaultItemIdentifiers:@[ kTextSuggestionsItemsTouchId ]];
-  return touchBar.autorelease();
-}
-
-- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
-      makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
-  if (![identifier hasSuffix:kTextSuggestionsItemsTouchId])
-    return nil;
-
-  return [self makeCandidateListItem];
-}
-
-- (NSCandidateListTouchBarItem*)makeCandidateListItem {
-  base::scoped_nsobject<NSCandidateListTouchBarItem> candidateListItem(
-      [[NSCandidateListTouchBarItem alloc]
-          initWithIdentifier:kTextSuggestionsItemsTouchId]);
-
-  [candidateListItem setDelegate:self];
-  if (selectionRange_.length)
-    [candidateListItem setCollapsed:YES];
-
-  [candidateListItem setCandidates:suggestions_
-                  forSelectedRange:selectionRange_
-                          inString:text_];
-
-  return candidateListItem.autorelease();
-}
-
-- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
-     endSelectingCandidateAtIndex:(NSInteger)index {
-  if (index == NSNotFound)
-    return;
-
-  if (anItem) {
-    NSTextCheckingResult* selectedResult = anItem.candidates[index];
-    [self replaceEditingWordWithSuggestion:[selectedResult replacementString]];
-  }
-
-  ui::LogTouchBarUMA(ui::TouchBarAction::TEXT_SUGGESTION);
-}
-
-- (void)updateTextSelection:(const base::string16&)text
-                      range:(const gfx::Range&)range
-                     offset:(size_t)offset {
-  if (shouldIgnoreReplacementSelection_ &&
-      range == gfx::Range(offsetEditingWordRange_)) {
-    shouldIgnoreReplacementSelection_ = NO;
-    return;
-  }
-
-  if (![self isTextfieldFocused]) {
-    [controller_ invalidateTouchBar];
-    return;
-  }
-
-  // TODO(crbug.com/880642): It's possible for a range out of the text bounds
-  // to be passed in. Investigate this.
-  if (range.start() - offset > text.length() ||
-      range.end() - offset > text.length()) {
-    text_.reset([[NSString alloc] init]);
-    selectionRange_ = NSMakeRange(0, 0);
-    editingWordRange_ = NSMakeRange(0, 0);
-    offsetEditingWordRange_ = NSMakeRange(0, 0);
-    return;
-  }
-
-  text_.reset([base::SysUTF16ToNSString(text) retain]);
-  selectionRange_ = range.ToNSRange();
-  selectionRange_.location -= offset;
-
-  editingWordRange_ = [self editingWordRangeFromText:text
-                                      cursorPosition:selectionRange_.location];
-
-  offsetEditingWordRange_ = editingWordRange_;
-  offsetEditingWordRange_.location += offset;
-  [self requestSuggestions];
-}
-
-- (NSRange)editingWordRangeFromText:(const base::string16&)text
-                     cursorPosition:(size_t)cursor {
-  // The cursor should not be off the end of the text.
-  DCHECK(cursor <= text.length());
-
-  // Default range is just the cursor position. This is used if BreakIterator
-  // cannot be initialized, there is no text in the textfield, or the cursor is
-  // at the front of a word.
-  size_t location = cursor;
-  size_t length = 0;
-
-  base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD);
-
-  if (iter.Init()) {
-    // Repeat iter.Advance() until end of line is reached or
-    // current iterator position passes cursor position.
-    while (iter.pos() < cursor && iter.Advance()) {
-    }
-
-    // If BreakIterator stopped at the end of a word, the cursor is in/at the
-    // end of a word so the editing word range is [word start, word end].
-    if (iter.IsWord()) {
-      location = iter.prev();
-      length = cursor - iter.prev();
-    }
-  }
-
-  return NSMakeRange(location, length);
-}
-
-- (void)requestSuggestions {
-  NSSpellChecker* spell_checker = [NSSpellChecker sharedSpellChecker];
-  [spell_checker
-      requestCandidatesForSelectedRange:selectionRange_
-                               inString:text_
-                                  types:NSTextCheckingAllSystemTypes
-                                options:nil
-                 inSpellDocumentWithTag:0
-                      completionHandler:^(
-                          NSInteger sequenceNumber,
-                          NSArray<NSTextCheckingResult*>* candidates) {
-                        dispatch_async(dispatch_get_main_queue(), ^{
-                          suggestions_.reset([candidates copy]);
-                          [controller_ invalidateTouchBar];
-                        });
-                      }];
-}
-
-- (void)replaceEditingWordWithSuggestion:(NSString*)text {
-  // If the editing word is not selected in its entirety, modify the selection
-  // to cover the current editing word.
-  if (!NSEqualRanges(editingWordRange_, selectionRange_)) {
-    shouldIgnoreReplacementSelection_ = YES;
-    int start_adjust = editingWordRange_.location - selectionRange_.location;
-    int end_adjust = (editingWordRange_.location + editingWordRange_.length) -
-                     (selectionRange_.location + selectionRange_.length);
-    webContents_->AdjustSelectionByCharacterOffset(start_adjust, end_adjust,
-                                                   false);
-  }
-  webContents_->Replace(base::SysNSStringToUTF16(text));
-}
-
-- (void)setWebContents:(content::WebContents*)webContents {
-  webContents_ = webContents;
-  observer_->UpdateWebContents(webContents);
-
-  if (![self isTextfieldFocused]) {
-    [controller_ invalidateTouchBar];
-    return;
-  }
-
-  const base::string16 text =
-      webContents_->GetTopLevelRenderWidgetHostView()->GetSurroundingText();
-  const gfx::Range range =
-      webContents_->GetTopLevelRenderWidgetHostView()->GetSelectedRange();
-  const size_t offset = webContents_->GetTopLevelRenderWidgetHostView()
-                            ->GetOffsetForSurroundingText();
-
-  [self updateTextSelection:text range:range offset:offset];
-}
-
-- (content::WebContents*)webContents {
-  return webContents_;
-}
-
-- (void)setText:(NSString*)text {
-  text_.reset([text copy]);
-}
-
-- (NSString*)text {
-  return text_;
-}
-
-- (void)setSelectionRange:(const gfx::Range&)range {
-  selectionRange_ = range.ToNSRange();
-}
-
-- (gfx::Range)selectionRange {
-  return gfx::Range(selectionRange_);
-}
-
-- (void)setSuggestions:(NSArray*)suggestions {
-  suggestions_.reset([suggestions copy]);
-}
-
-- (NSArray*)suggestions {
-  return suggestions_;
-}
-
-- (WebTextfieldTouchBarController*)controller {
-  return controller_;
-}
-
-- (void)setShouldIgnoreReplacementSelection:(BOOL)shouldIgnore {
-  shouldIgnoreReplacementSelection_ = shouldIgnore;
-}
-
-- (void)setEditingWordRange:(const gfx::Range&)range offset:(size_t)offset {
-  editingWordRange_ = range.ToNSRange();
-  offsetEditingWordRange_ = NSMakeRange(editingWordRange_.location + offset,
-                                        editingWordRange_.length);
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm
deleted file mode 100644
index bc5949f..0000000
--- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm
+++ /dev/null
@@ -1,327 +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.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "chrome/browser/ui/browser.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h"
-#include "chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h"
-#include "chrome/common/chrome_features.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "ui/base/cocoa/touch_bar_util.h"
-
-API_AVAILABLE(macos(10.12.2))
-@interface MockWebTextfieldTouchBarController : WebTextfieldTouchBarController {
-  // Counter for the number of times invalidateTouchBar is called.
-  int numInvalidations_;
-}
-- (int)numInvalidations;
-
-- (void)resetNumInvalidations;
-
-@end
-
-@implementation MockWebTextfieldTouchBarController
-
-- (void)invalidateTouchBar {
-  numInvalidations_++;
-}
-
-- (int)numInvalidations {
-  return numInvalidations_;
-}
-
-- (void)resetNumInvalidations {
-  numInvalidations_ = 0;
-}
-
-@end
-
-API_AVAILABLE(macos(10.12.2))
-@interface MockTextSuggestionsTouchBarController
-    : TextSuggestionsTouchBarController
-- (NSString*)firstSuggestion;
-@end
-
-@implementation MockTextSuggestionsTouchBarController
-
-- (void)requestSuggestions {
-  [self setSuggestions:@[ [self text] ]];
-  [[self controller] invalidateTouchBar];
-}
-
-- (NSString*)firstSuggestion {
-  return [self suggestions][0];
-}
-
-@end
-
-namespace {
-
-class TextSuggestionsTouchBarControllerTest : public InProcessBrowserTest {
- public:
-  void SetUp() override {
-    InProcessBrowserTest::SetUp();
-    feature_list_.InitAndEnableFeature(features::kTextSuggestionsTouchBar);
-  }
-
-  void SetUpOnMainThread() override {
-    if (@available(macOS 10.12.2, *)) {
-      web_textfield_controller_.reset(
-          [[MockWebTextfieldTouchBarController alloc] init]);
-      [web_textfield_controller_ resetNumInvalidations];
-      touch_bar_controller_.reset([[MockTextSuggestionsTouchBarController alloc]
-          initWithWebContents:GetActiveWebContents()
-                   controller:web_textfield_controller_]);
-    }
-  }
-
-  void FocusTextfield() {
-    content::WindowedNotificationObserver focus_observer(
-        content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
-        content::NotificationService::AllSources());
-    ui_test_utils::NavigateToURL(
-        browser(),
-        GURL("data:text/html;charset=utf-8,<input type=\"text\" autofocus>"));
-    focus_observer.Wait();
-  }
-
-  void UnfocusTextfield() {
-    ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
-  }
-
-  content::WebContents* GetActiveWebContents() {
-    return browser()->tab_strip_model()->GetActiveWebContents();
-  }
-
-  API_AVAILABLE(macos(10.12.2))
-  base::scoped_nsobject<MockWebTextfieldTouchBarController>
-      web_textfield_controller_;
-
-  API_AVAILABLE(macos(10.12.2))
-  base::scoped_nsobject<MockTextSuggestionsTouchBarController>
-      touch_bar_controller_;
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Tests to check if the touch bar shows up properly.
-IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest, MakeTouchBar) {
-  if (@available(macOS 10.12.2, *)) {
-    NSString* const kTextSuggestionsTouchBarId = @"text-suggestions";
-    NSArray* const kSuggestions = @[ @"text" ];
-
-    // Touch bar shouldn't appear if the focused element is not a textfield.
-    UnfocusTextfield();
-    [touch_bar_controller_ setSuggestions:kSuggestions];
-    EXPECT_FALSE([touch_bar_controller_ makeTouchBar]);
-
-    // Touch bar shouldn't appear if there are no suggestions.
-    FocusTextfield();
-    [touch_bar_controller_ setSuggestions:[NSArray array]];
-    EXPECT_FALSE([touch_bar_controller_ makeTouchBar]);
-
-    // Touch bar should appear if textfield is focused and there are
-    // suggestions.
-    [touch_bar_controller_ setSuggestions:kSuggestions];
-    NSTouchBar* touch_bar = [touch_bar_controller_ makeTouchBar];
-    EXPECT_TRUE(touch_bar);
-    EXPECT_TRUE([[touch_bar customizationIdentifier]
-        isEqual:ui::GetTouchBarId(kTextSuggestionsTouchBarId)]);
-  }
-}
-
-// Tests that a change in text selection is handled properly.
-IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest,
-                       UpdateTextSelection) {
-  if (@available(macOS 10.12.2, *)) {
-    NSString* const kText = @"text";
-    NSString* const kEmptyText = @"";
-    const gfx::Range kRange = gfx::Range(0, 4);
-    const gfx::Range kEmptyRange = gfx::Range();
-
-    // If not in a textfield,
-    //  1. Textfield text should not be saved.
-    //  2. Selected range should not be saved.
-    //  3. Touch bar should be invalidated (if on MacOS 10.12.2 or later).
-    UnfocusTextfield();
-    [touch_bar_controller_ setText:kEmptyText];
-    [touch_bar_controller_ setSelectionRange:kEmptyRange];
-    [web_textfield_controller_ resetNumInvalidations];
-
-    [touch_bar_controller_ updateTextSelection:base::SysNSStringToUTF16(kText)
-                                         range:kRange
-                                        offset:0];
-    EXPECT_STREQ(kEmptyText.UTF8String,
-                 [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(kEmptyRange, [touch_bar_controller_ selectionRange]);
-    EXPECT_EQ(1, [web_textfield_controller_ numInvalidations]);
-
-    // If in a textfield and on MacOS 10.12.2 or later,
-    //   1. Textfield text should be saved.
-    //   2. Selected range should be saved.
-    //   3. Suggestions should be generated based on text selection.
-    //   4. Touch bar should be invalidated.
-    FocusTextfield();
-    [touch_bar_controller_ setText:kEmptyText];
-    [touch_bar_controller_ setSelectionRange:kEmptyRange];
-    [web_textfield_controller_ resetNumInvalidations];
-
-    [touch_bar_controller_ updateTextSelection:base::SysNSStringToUTF16(kText)
-                                         range:kRange
-                                        offset:0];
-    EXPECT_STREQ(kText.UTF8String, [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(kRange, [touch_bar_controller_ selectionRange]);
-    EXPECT_STREQ(kText.UTF8String,
-                 [touch_bar_controller_ firstSuggestion].UTF8String);
-    EXPECT_EQ(1, [web_textfield_controller_ numInvalidations]);
-  }
-}
-
-// Tests that a range outside of the text bounds will set the selection range
-// to empty.
-IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest,
-                       RangeOutOfTextBounds) {
-  if (@available(macOS 10.12.2, *)) {
-    FocusTextfield();
-    [touch_bar_controller_ setText:@""];
-    [touch_bar_controller_ setSelectionRange:gfx::Range()];
-
-    [touch_bar_controller_
-        updateTextSelection:base::string16(base::ASCIIToUTF16("text"))
-                      range:gfx::Range(4, 5)
-                     offset:0];
-    EXPECT_STREQ("", [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]);
-
-    [touch_bar_controller_
-        updateTextSelection:base::string16(base::ASCIIToUTF16("text"))
-                      range:gfx::Range(2, 5)
-                     offset:0];
-    EXPECT_STREQ("", [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]);
-  }
-}
-
-// Tests that a change in WebContents is handled properly.
-IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest, SetWebContents) {
-  if (@available(macOS 10.12.2, *)) {
-    NSString* const kText = @"text";
-    const gfx::Range kRange = gfx::Range(1, 1);
-
-    FocusTextfield();
-
-    // A null-pointer should not break the controller.
-    [touch_bar_controller_ setWebContents:nullptr];
-    EXPECT_FALSE([touch_bar_controller_ webContents]);
-
-    [touch_bar_controller_ setText:kText];
-    [touch_bar_controller_ setSelectionRange:kRange];
-
-    // The text selection should change on MacOS 10.12.2 and later if the
-    // WebContents pointer is not null.
-    [touch_bar_controller_ setWebContents:GetActiveWebContents()];
-    EXPECT_EQ(GetActiveWebContents(), [touch_bar_controller_ webContents]);
-    EXPECT_STRNE(kText.UTF8String, [touch_bar_controller_ text].UTF8String);
-    EXPECT_NE(kRange, [touch_bar_controller_ selectionRange]);
-  }
-}
-
-// Tests that the selection created when replacing the editing word with a
-// suggestion is ignored.
-IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest,
-                       IgnoreReplacementSelection) {
-  if (@available(macOS 10.12.2, *)) {
-    NSString* const kText = @"text";
-    const base::string16 kEmptyText = base::string16();
-    const gfx::Range kRange = gfx::Range(0, 4);
-    const gfx::Range kEmptyRange = gfx::Range();
-
-    FocusTextfield();
-    [touch_bar_controller_ setText:kText];
-    [touch_bar_controller_ setSelectionRange:kRange];
-
-    // If ignoreReplacementSelection is YES and new selection range is equal to
-    // editing word range, ignore text selection update.
-    [touch_bar_controller_ setShouldIgnoreReplacementSelection:YES];
-    [touch_bar_controller_ setEditingWordRange:kEmptyRange offset:0];
-    [touch_bar_controller_ updateTextSelection:kEmptyText
-                                         range:kEmptyRange
-                                        offset:0];
-    EXPECT_STREQ(kText.UTF8String, [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(kRange, [touch_bar_controller_ selectionRange]);
-
-    // If ignoreReplacementSelection is YES but new selection range is not equal
-    // to editing word range, do not ignore text selection update.
-    [touch_bar_controller_ setShouldIgnoreReplacementSelection:YES];
-    [touch_bar_controller_ setEditingWordRange:kRange offset:0];
-    [touch_bar_controller_ updateTextSelection:kEmptyText
-                                         range:kEmptyRange
-                                        offset:0];
-    EXPECT_STREQ("", [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]);
-
-    [touch_bar_controller_ setText:kText];
-    [touch_bar_controller_ setSelectionRange:kRange];
-
-    // If ignoreReplacementSelection is NO and new selection range is equal to
-    // editing word range, do not ignore text selection update.
-    [touch_bar_controller_ setShouldIgnoreReplacementSelection:NO];
-    [touch_bar_controller_ setEditingWordRange:kEmptyRange offset:0];
-    [touch_bar_controller_ updateTextSelection:kEmptyText
-                                         range:kEmptyRange
-                                        offset:0];
-    EXPECT_STREQ("", [touch_bar_controller_ text].UTF8String);
-    EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]);
-  }
-}
-
-// Tests that offsets are properly handled.
-IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest, Offset) {
-  if (@available(macOS 10.12.2, *)) {
-    const base::string16 kText =
-        base::string16(base::ASCIIToUTF16("hello world"));
-    const gfx::Range kRange = gfx::Range(3, 3);
-    const size_t kOffset = 1;
-    const gfx::Range kOffsetRange =
-        gfx::Range(kRange.start() - kOffset, kRange.end() - kOffset);
-
-    FocusTextfield();
-    [touch_bar_controller_ setSelectionRange:gfx::Range()];
-
-    // |selectionRange_| should include offset.
-    [touch_bar_controller_ updateTextSelection:kText
-                                         range:kRange
-                                        offset:kOffset];
-    if (@available(macOS 10.12.2, *))
-      EXPECT_EQ(kOffsetRange, [touch_bar_controller_ selectionRange]);
-    else
-      EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]);
-
-    // The check for ignoring text selection updates should still work with
-    // offsets.
-    [touch_bar_controller_ setShouldIgnoreReplacementSelection:YES];
-    [touch_bar_controller_ updateTextSelection:kText
-                                         range:gfx::Range(1, 7)
-                                        offset:kOffset];
-    if (@available(macOS 10.12.2, *))
-      EXPECT_EQ(gfx::Range(0, 6), [touch_bar_controller_ selectionRange]);
-    else
-      EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]);
-  }
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm
deleted file mode 100644
index feb982f..0000000
--- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm
+++ /dev/null
@@ -1,155 +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.
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
-#import "chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "ui/base/cocoa/touch_bar_util.h"
-#include "ui/gfx/range/range.h"
-
-const base::string16 kEmptyText(base::ASCIIToUTF16(""));
-const base::string16 kWord(base::ASCIIToUTF16("hello"));
-const base::string16 kWordWithTrailingWhitespace(base::ASCIIToUTF16("hello "));
-const base::string16 kWordWithLeadingWhitespace(base::ASCIIToUTF16(" hello"));
-const base::string16 kMultipleWords(base::ASCIIToUTF16("hello world"));
-const base::string16 kWhitespace(base::ASCIIToUTF16("     "));
-
-class TextSuggestionsTouchBarControllerTest : public CocoaTest {
- public:
-  void SetUp() override {
-    CocoaTest::SetUp();
-    if (@available(macOS 10.12.2, *))
-      controller_.reset([[TextSuggestionsTouchBarController alloc] init]);
-  }
-
-  gfx::Range GetEditingWordRange(const base::string16& text, size_t cursor)
-      API_AVAILABLE(macos(10.12.2)) {
-    NSRange range =
-        [controller_.get() editingWordRangeFromText:text cursorPosition:cursor];
-    return gfx::Range(range);
-  }
-
-  API_AVAILABLE(macos(10.12.2))
-  base::scoped_nsobject<TextSuggestionsTouchBarController> controller_;
-};
-
-// Tests that the NSCandidateListTouchBarItem collapses properly.
-TEST_F(TextSuggestionsTouchBarControllerTest, CollapsedCandidateList) {
-  if (@available(macOS 10.12.2, *)) {
-    [controller_ setSelectionRange:gfx::Range()];
-    EXPECT_FALSE([[controller_ makeCandidateListItem] isCollapsed]);
-
-    [controller_ setSelectionRange:gfx::Range(0, 1)];
-    EXPECT_TRUE([[controller_ makeCandidateListItem] isCollapsed]);
-  }
-}
-
-// Tests that the editing word range is simply the cursor position if there
-// is no text.
-TEST_F(TextSuggestionsTouchBarControllerTest, EmptyTextEditingWordRange) {
-  if (@available(macOS 10.12.2, *))
-    EXPECT_EQ(gfx::Range(0, 0), GetEditingWordRange(kEmptyText, 0));
-}
-
-// Tests that the editing word range contains the full word as the cursor
-// moves through a word without breaks.
-TEST_F(TextSuggestionsTouchBarControllerTest, WordEditingWordRange) {
-  if (@available(macOS 10.12.2, *)) {
-    EXPECT_EQ(gfx::Range(0, 0), GetEditingWordRange(kWord, 0));
-    EXPECT_EQ(gfx::Range(0, 1), GetEditingWordRange(kWord, 1));
-    EXPECT_EQ(gfx::Range(0, 2), GetEditingWordRange(kWord, 2));
-    EXPECT_EQ(gfx::Range(0, 3), GetEditingWordRange(kWord, 3));
-    EXPECT_EQ(gfx::Range(0, 4), GetEditingWordRange(kWord, 4));
-  }
-}
-
-// Tests that the editing word range is properly calculated as the cursor moves
-// through non-word characters.
-TEST_F(TextSuggestionsTouchBarControllerTest, WhitespaceEditingWordRange) {
-  if (@available(macOS 10.12.2, *)) {
-    EXPECT_EQ(gfx::Range(0, 0), GetEditingWordRange(kWhitespace, 0));
-    EXPECT_EQ(gfx::Range(1, 1), GetEditingWordRange(kWhitespace, 1));
-    EXPECT_EQ(gfx::Range(2, 2), GetEditingWordRange(kWhitespace, 2));
-    EXPECT_EQ(gfx::Range(3, 3), GetEditingWordRange(kWhitespace, 3));
-    EXPECT_EQ(gfx::Range(4, 4), GetEditingWordRange(kWhitespace, 4));
-    EXPECT_EQ(gfx::Range(5, 5), GetEditingWordRange(kWhitespace, 5));
-  }
-}
-
-// Tests that the editing word range changes properly as the cursor moves
-// from word to non-word characters.
-TEST_F(TextSuggestionsTouchBarControllerTest,
-       TrailingWhitespaceEditingWordRange) {
-  if (@available(macOS 10.12.2, *)) {
-    EXPECT_EQ(gfx::Range(0, 0),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 0));
-    EXPECT_EQ(gfx::Range(0, 1),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 1));
-    EXPECT_EQ(gfx::Range(0, 2),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 2));
-    EXPECT_EQ(gfx::Range(0, 3),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 3));
-    EXPECT_EQ(gfx::Range(0, 4),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 4));
-    EXPECT_EQ(gfx::Range(0, 5),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 5));
-    EXPECT_EQ(gfx::Range(6, 6),
-              GetEditingWordRange(kWordWithTrailingWhitespace, 6));
-  }
-}
-
-// Tests that the editing word range changes properly as the cursor moves
-// from non-word to word characters.
-TEST_F(TextSuggestionsTouchBarControllerTest,
-       LeadingWhitespaceEditingWordRange) {
-  if (@available(macOS 10.12.2, *)) {
-    EXPECT_EQ(gfx::Range(0, 0),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 0));
-    EXPECT_EQ(gfx::Range(1, 1),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 1));
-    EXPECT_EQ(gfx::Range(1, 2),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 2));
-    EXPECT_EQ(gfx::Range(1, 3),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 3));
-    EXPECT_EQ(gfx::Range(1, 4),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 4));
-    EXPECT_EQ(gfx::Range(1, 5),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 5));
-    EXPECT_EQ(gfx::Range(1, 6),
-              GetEditingWordRange(kWordWithLeadingWhitespace, 6));
-  }
-}
-
-// Tests that the editing word range is properly calculated as the cursor moves
-// from word to non-word and back to word characters.
-TEST_F(TextSuggestionsTouchBarControllerTest, MultipleWordsEditingWordRange) {
-  if (@available(macOS 10.12.2, *)) {
-    EXPECT_EQ(gfx::Range(0, 0), GetEditingWordRange(kMultipleWords, 0));
-    EXPECT_EQ(gfx::Range(0, 1), GetEditingWordRange(kMultipleWords, 1));
-    EXPECT_EQ(gfx::Range(0, 2), GetEditingWordRange(kMultipleWords, 2));
-    EXPECT_EQ(gfx::Range(0, 3), GetEditingWordRange(kMultipleWords, 3));
-    EXPECT_EQ(gfx::Range(0, 4), GetEditingWordRange(kMultipleWords, 4));
-    EXPECT_EQ(gfx::Range(0, 5), GetEditingWordRange(kMultipleWords, 5));
-    EXPECT_EQ(gfx::Range(6, 6), GetEditingWordRange(kMultipleWords, 6));
-    EXPECT_EQ(gfx::Range(6, 7), GetEditingWordRange(kMultipleWords, 7));
-    EXPECT_EQ(gfx::Range(6, 8), GetEditingWordRange(kMultipleWords, 8));
-    EXPECT_EQ(gfx::Range(6, 9), GetEditingWordRange(kMultipleWords, 9));
-    EXPECT_EQ(gfx::Range(6, 10), GetEditingWordRange(kMultipleWords, 10));
-    EXPECT_EQ(gfx::Range(6, 11), GetEditingWordRange(kMultipleWords, 11));
-  }
-}
-
-// Tests that touch bar usage is properly logged.
-TEST_F(TextSuggestionsTouchBarControllerTest, TouchBarMetrics) {
-  if (@available(macOS 10.12.2, *)) {
-    base::HistogramTester histogram_tester;
-    [controller_ candidateListTouchBarItem:nil endSelectingCandidateAtIndex:1];
-    histogram_tester.ExpectBucketCount("TouchBar.Default.Metrics",
-                                       ui::TouchBarAction::TEXT_SUGGESTION, 1);
-  }
-}
diff --git a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h
index 7619b86d..f062e5332 100644
--- a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h
+++ b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.h
@@ -14,7 +14,6 @@
 
 @class BrowserWindowTouchBarController;
 @class CreditCardAutofillTouchBarController;
-@class TextSuggestionsTouchBarController;
 
 namespace autofill {
 class AutofillPopupController;
@@ -31,8 +30,6 @@
   BrowserWindowTouchBarController* controller_;  // weak.
   base::scoped_nsobject<CreditCardAutofillTouchBarController>
       autofillTouchBarController_;
-  base::scoped_nsobject<TextSuggestionsTouchBarController>
-      textSuggestionsTouchBarController_;
 }
 
 + (WebTextfieldTouchBarController*)controllerForWindow:(NSWindow*)window;
@@ -45,8 +42,6 @@
 
 - (void)hideCreditCardAutofillTouchBar;
 
-- (void)updateWebContents:(content::WebContents*)contents;
-
 - (void)invalidateTouchBar;
 
 // Creates and returns a touch bar.
diff --git a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
index c3a3d23f..9f98730a 100644
--- a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
@@ -10,13 +10,10 @@
 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
 #import "chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h"
 #import "chrome/browser/ui/cocoa/touchbar/credit_card_autofill_touch_bar_controller.h"
-#import "chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.h"
 #include "chrome/browser/ui/views/frame/browser_frame_mac.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/common/chrome_features.h"
 #include "content/public/browser/web_contents.h"
 #import "ui/base/cocoa/touch_bar_util.h"
-#include "ui/base/ui_base_features.h"
 
 @implementation WebTextfieldTouchBarController
 
@@ -35,14 +32,6 @@
     (BrowserWindowTouchBarController*)controller {
   if ((self = [super init])) {
     controller_ = controller;
-
-    if (base::FeatureList::IsEnabled(features::kTextSuggestionsTouchBar) ||
-        base::FeatureList::IsEnabled(features::kExperimentalUi)) {
-      textSuggestionsTouchBarController_.reset(
-          [[TextSuggestionsTouchBarController alloc]
-              initWithWebContents:[controller_ webContents]
-                       controller:self]);
-    }
   }
 
   return self;
@@ -66,10 +55,6 @@
   [self invalidateTouchBar];
 }
 
-- (void)updateWebContents:(content::WebContents*)contents {
-  [textSuggestionsTouchBarController_ setWebContents:contents];
-}
-
 - (void)invalidateTouchBar {
   [controller_ invalidateTouchBar];
 }
@@ -77,10 +62,6 @@
 - (NSTouchBar*)makeTouchBar {
   if (autofillTouchBarController_)
     return [autofillTouchBarController_ makeTouchBar];
-
-  if (textSuggestionsTouchBarController_)
-    return [textSuggestionsTouchBarController_ makeTouchBar];
-
   return nil;
 }
 
diff --git a/chrome/browser/ui/in_product_help/reopen_tab_in_product_help.cc b/chrome/browser/ui/in_product_help/reopen_tab_in_product_help.cc
new file mode 100644
index 0000000..78b965f
--- /dev/null
+++ b/chrome/browser/ui/in_product_help/reopen_tab_in_product_help.cc
@@ -0,0 +1,86 @@
+// 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/ui/in_product_help/reopen_tab_in_product_help.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/tracker.h"
+
+namespace in_product_help {
+
+ReopenTabInProductHelp::ReopenTabInProductHelp(Profile* profile,
+                                               const base::TickClock* clock)
+    : profile_(profile),
+      clock_(clock),
+      active_tab_tracker_(
+          clock_,
+          base::BindRepeating(&ReopenTabInProductHelp::OnActiveTabClosed,
+                              base::Unretained(this))),
+      trigger_(GetTracker(), clock_) {
+  // We want to track all created and destroyed browsers, and also add all
+  // currently living browsers.
+  BrowserList::AddObserver(this);
+  for (Browser* browser : *BrowserList::GetInstance()) {
+    active_tab_tracker_.AddTabStripModel(browser->tab_strip_model());
+  }
+
+  // |base::Unretained| is safe here since this is a member.
+  trigger_.SetShowHelpCallback(base::BindRepeating(
+      &ReopenTabInProductHelp::OnShowHelp, base::Unretained(this)));
+}
+
+ReopenTabInProductHelp::~ReopenTabInProductHelp() {
+  BrowserList::RemoveObserver(this);
+  for (Browser* browser : *BrowserList::GetInstance()) {
+    active_tab_tracker_.RemoveTabStripModel(browser->tab_strip_model());
+  }
+}
+
+void ReopenTabInProductHelp::NewTabOpened() {
+  trigger_.NewTabOpened();
+}
+
+void ReopenTabInProductHelp::OmniboxFocused() {
+  trigger_.OmniboxFocused();
+}
+
+void ReopenTabInProductHelp::TabReopened() {
+  GetTracker()->NotifyEvent(feature_engagement::events::kTabReopened);
+}
+
+void ReopenTabInProductHelp::OnActiveTabClosed(
+    TabStripModel* tab_strip_model,
+    base::TimeDelta active_duration) {
+  trigger_.ActiveTabClosed(active_duration);
+}
+
+void ReopenTabInProductHelp::OnShowHelp() {
+  // Here, we would get the last active browser and trigger our IPH in it. For
+  // now, we just say IPH was immediately dismissed. TODO(collinbaker):
+  // implement call into views-side to display IPH.
+  trigger_.HelpDismissed();
+}
+
+void ReopenTabInProductHelp::OnBrowserAdded(Browser* browser) {
+  active_tab_tracker_.AddTabStripModel(browser->tab_strip_model());
+}
+
+void ReopenTabInProductHelp::OnBrowserRemoved(Browser* browser) {
+  active_tab_tracker_.RemoveTabStripModel(browser->tab_strip_model());
+}
+
+feature_engagement::Tracker* ReopenTabInProductHelp::GetTracker() {
+  return feature_engagement::TrackerFactory::GetForBrowserContext(profile_);
+}
+
+}  // namespace in_product_help
diff --git a/chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h b/chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h
new file mode 100644
index 0000000..ff83f19
--- /dev/null
+++ b/chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h
@@ -0,0 +1,77 @@
+// 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 CHROME_BROWSER_UI_IN_PRODUCT_HELP_REOPEN_TAB_IN_PRODUCT_HELP_H_
+#define CHROME_BROWSER_UI_IN_PRODUCT_HELP_REOPEN_TAB_IN_PRODUCT_HELP_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/time/tick_clock.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/in_product_help/active_tab_tracker.h"
+#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_trigger.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace base {
+class TickClock;
+}
+
+namespace feature_engagement {
+class Tracker;
+}
+
+class TabStripModel;
+
+namespace in_product_help {
+
+// Listens for the triggering conditions for the reopen tab in-product help and
+// starts the IPH flow at the appropriate time. This is a |Profile|-keyed
+// service since we track interactions per user profile. Hooks throughout the
+// browser UI code will fetch this service and notify it of interesting user
+// actions.
+class ReopenTabInProductHelp : public BrowserListObserver, public KeyedService {
+ public:
+  ReopenTabInProductHelp(Profile* profile, const base::TickClock* clock);
+  ~ReopenTabInProductHelp() override;
+
+  // Should be called when the user opens a blank new tab.
+  void NewTabOpened();
+  // Should be called when the user focuses on the omnibox. Possibly triggers
+  // IPH.
+  void OmniboxFocused();
+  // Should be called when the user reopens a previously closed tab, either
+  // through CTRL+SHIFT+T or through the recent tabs menu.
+  void TabReopened();
+
+ private:
+  // BrowserListObserver:
+  void OnBrowserAdded(Browser* browser) override;
+  void OnBrowserRemoved(Browser* browser) override;
+
+  feature_engagement::Tracker* GetTracker();
+
+  // Callback passed to the |ActiveTabTracker|.
+  void OnActiveTabClosed(TabStripModel* tab_strip_model,
+                         base::TimeDelta active_duration);
+
+  // Callback passed to |ReopenTabInProductHelpTrigger|.
+  void OnShowHelp();
+
+  Profile* const profile_;
+  const base::TickClock* const clock_;
+
+  // Tracks active tab durations and notifies us when an active tab is closed.
+  ActiveTabTracker active_tab_tracker_;
+  // Manages the triggering logic for this IPH. This object calls into the IPH
+  // backend.
+  ReopenTabInProductHelpTrigger trigger_;
+
+  DISALLOW_COPY_AND_ASSIGN(ReopenTabInProductHelp);
+};
+
+}  // namespace in_product_help
+
+#endif  // CHROME_BROWSER_UI_IN_PRODUCT_HELP_REOPEN_TAB_IN_PRODUCT_HELP_H_
diff --git a/chrome/browser/ui/in_product_help/reopen_tab_in_product_help_unittest.cc b/chrome/browser/ui/in_product_help/reopen_tab_in_product_help_unittest.cc
new file mode 100644
index 0000000..02c9b92
--- /dev/null
+++ b/chrome/browser/ui/in_product_help/reopen_tab_in_product_help_unittest.cc
@@ -0,0 +1,83 @@
+// 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 <memory>
+#include <utility>
+
+#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h"
+
+#include "base/test/simple_test_tick_clock.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_trigger.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "components/feature_engagement/test/mock_tracker.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::Invoke;
+using ::testing::Return;
+
+using MockTracker = ::testing::NiceMock<feature_engagement::test::MockTracker>;
+
+namespace in_product_help {
+
+class ReopenTabInProductHelpTest : public BrowserWithTestWindowTest {
+ protected:
+  // We want to use |MockTracker| instead of |Tracker|, so we must override its
+  // factory.
+  TestingProfile::TestingFactories GetTestingFactories() override {
+    return {{feature_engagement::TrackerFactory::GetInstance(),
+             base::BindRepeating(CreateTracker)}};
+  }
+
+  MockTracker* GetMockTracker() {
+    return static_cast<MockTracker*>(
+        feature_engagement::TrackerFactory::GetForBrowserContext(profile()));
+  }
+
+  base::SimpleTestTickClock* clock() { return &clock_; }
+
+ private:
+  // Factory function for our |MockTracker|
+  static std::unique_ptr<KeyedService> CreateTracker(
+      content::BrowserContext* context) {
+    return std::make_unique<MockTracker>();
+  }
+
+  base::SimpleTestTickClock clock_;
+};
+
+TEST_F(ReopenTabInProductHelpTest, TriggersIPH) {
+  ReopenTabInProductHelp reopen_tab_iph(profile(), clock());
+
+  auto* mock_tracker = GetMockTracker();
+  EXPECT_CALL(*mock_tracker, ShouldTriggerHelpUI(_))
+      .Times(1)
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_tracker, Dismissed(_)).Times(1);
+
+  AddTab(browser(), GURL("chrome://blank"));
+  AddTab(browser(), GURL("chrome://blank"));
+  BrowserList::SetLastActive(browser());
+
+  clock()->Advance(ReopenTabInProductHelpTrigger::kTabMinimumActiveDuration);
+
+  auto* tab_strip_model = browser()->tab_strip_model();
+  tab_strip_model->ToggleSelectionAt(0);
+  ASSERT_TRUE(tab_strip_model->IsTabSelected(0));
+  tab_strip_model->CloseSelectedTabs();
+
+  reopen_tab_iph.NewTabOpened();
+  reopen_tab_iph.OmniboxFocused();
+}
+
+}  // namespace in_product_help
diff --git a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc
index 730e43c..e16693e 100644
--- a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc
+++ b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.cc
@@ -37,6 +37,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/range/range.h"
 #include "ui/gfx/text_utils.h"
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc
index d3aa603..3d3b725 100644
--- a/chrome/browser/ui/search/search_ipc_router.cc
+++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -247,17 +247,6 @@
   delegate_->OnResetCustomLinks();
 }
 
-void SearchIPCRouter::DoesUrlResolve(int page_seq_no,
-                                     const GURL& url,
-                                     DoesUrlResolveCallback callback) {
-  if (page_seq_no == commit_counter_ &&
-      policy_->ShouldProcessDoesUrlResolve()) {
-    delegate_->OnDoesUrlResolve(url, std::move(callback));
-  } else {
-    std::move(callback).Run(/*resolves=*/true, /*timeout=*/false);
-  }
-}
-
 void SearchIPCRouter::LogEvent(int page_seq_no,
                                NTPLoggingEventType event,
                                base::TimeDelta time) {
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h
index 220c755..7ea3d810 100644
--- a/chrome/browser/ui/search/search_ipc_router.h
+++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -73,11 +73,6 @@
     // use Most Visited sites instead.
     virtual void OnResetCustomLinks() = 0;
 
-    // Called when the EmbeddedSearch wants to check if |url| resolves to an
-    // existing page.
-    virtual void OnDoesUrlResolve(const GURL& url,
-                                  DoesUrlResolveCallback callback) = 0;
-
     // Called to signal that an event has occurred on the New Tab Page at a
     // particular time since navigation start.
     virtual void OnLogEvent(NTPLoggingEventType event,
@@ -140,7 +135,6 @@
     virtual bool ShouldProcessDeleteCustomLink() = 0;
     virtual bool ShouldProcessUndoCustomLinkAction() = 0;
     virtual bool ShouldProcessResetCustomLinks() = 0;
-    virtual bool ShouldProcessDoesUrlResolve() = 0;
     virtual bool ShouldProcessLogEvent() = 0;
     virtual bool ShouldProcessPasteIntoOmnibox(bool is_active_tab) = 0;
     virtual bool ShouldProcessChromeIdentityCheck() = 0;
@@ -214,9 +208,6 @@
                         DeleteCustomLinkCallback callback) override;
   void UndoCustomLinkAction(int page_seq_no) override;
   void ResetCustomLinks(int page_seq_no) override;
-  void DoesUrlResolve(int page_seq_no,
-                      const GURL& url,
-                      DoesUrlResolveCallback callback) override;
   void LogEvent(int page_seq_no,
                 NTPLoggingEventType event,
                 base::TimeDelta time) override;
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
index b82060d..bbf7ac4 100644
--- a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
+++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
@@ -58,10 +58,6 @@
   return !is_incognito_ && search::IsInstantNTP(web_contents_);
 }
 
-bool SearchIPCRouterPolicyImpl::ShouldProcessDoesUrlResolve() {
-  return !is_incognito_ && search::IsInstantNTP(web_contents_);
-}
-
 bool SearchIPCRouterPolicyImpl::ShouldProcessLogEvent() {
   return !is_incognito_ && search::IsInstantNTP(web_contents_);
 }
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.h b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
index 7af6adec..c25bac9f 100644
--- a/chrome/browser/ui/search/search_ipc_router_policy_impl.h
+++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
@@ -36,7 +36,6 @@
   bool ShouldProcessDeleteCustomLink() override;
   bool ShouldProcessUndoCustomLinkAction() override;
   bool ShouldProcessResetCustomLinks() override;
-  bool ShouldProcessDoesUrlResolve() override;
   bool ShouldProcessLogEvent() override;
   bool ShouldProcessPasteIntoOmnibox(bool is_active_tab) override;
   bool ShouldProcessChromeIdentityCheck() override;
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index 2def16df..4ee11c18 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -70,10 +70,6 @@
   MOCK_METHOD1(OnDeleteCustomLink, bool(const GURL& url));
   MOCK_METHOD0(OnUndoCustomLinkAction, void());
   MOCK_METHOD0(OnResetCustomLinks, void());
-  MOCK_METHOD2(
-      OnDoesUrlResolve,
-      void(const GURL& url,
-           chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback));
   MOCK_METHOD2(OnLogEvent, void(NTPLoggingEventType event,
                                 base::TimeDelta time));
   MOCK_METHOD1(OnLogMostVisitedImpression,
@@ -105,7 +101,6 @@
   MOCK_METHOD0(ShouldProcessDeleteCustomLink, bool());
   MOCK_METHOD0(ShouldProcessUndoCustomLinkAction, bool());
   MOCK_METHOD0(ShouldProcessResetCustomLinks, bool());
-  MOCK_METHOD0(ShouldProcessDoesUrlResolve, bool());
   MOCK_METHOD0(ShouldProcessLogEvent, bool());
   MOCK_METHOD1(ShouldProcessPasteIntoOmnibox, bool(bool));
   MOCK_METHOD0(ShouldProcessChromeIdentityCheck, bool());
@@ -639,38 +634,6 @@
   GetSearchIPCRouter().ResetCustomLinks(GetSearchIPCRouterSeqNo());
 }
 
-TEST_F(SearchIPCRouterTest, ProcessDoesUrlResolve) {
-  NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar"));
-  SetupMockDelegateAndPolicy();
-  MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy();
-  GURL url("www.foo.com");
-  EXPECT_CALL(*mock_delegate(), OnDoesUrlResolve(url, _)).Times(1);
-  EXPECT_CALL(*policy, ShouldProcessDoesUrlResolve())
-      .Times(1)
-      .WillOnce(Return(true));
-
-  base::MockCallback<SearchIPCRouter::DoesUrlResolveCallback> callback;
-  EXPECT_CALL(callback, Run(_, _)).Times(0);
-  GetSearchIPCRouter().DoesUrlResolve(GetSearchIPCRouterSeqNo(), url,
-                                      callback.Get());
-}
-
-TEST_F(SearchIPCRouterTest, IgnoreDoesUrlResolveMsg) {
-  NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar"));
-  SetupMockDelegateAndPolicy();
-  MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy();
-  GURL url("www.foo.com");
-  EXPECT_CALL(*mock_delegate(), OnDoesUrlResolve(url, _)).Times(0);
-  EXPECT_CALL(*policy, ShouldProcessDoesUrlResolve())
-      .Times(1)
-      .WillOnce(Return(false));
-
-  base::MockCallback<SearchIPCRouter::DoesUrlResolveCallback> callback;
-  EXPECT_CALL(callback, Run(true, false));
-  GetSearchIPCRouter().DoesUrlResolve(GetSearchIPCRouterSeqNo(), url,
-                                      callback.Get());
-}
-
 TEST_F(SearchIPCRouterTest, ProcessPasteAndOpenDropdownMsg) {
   NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl));
   SetupMockDelegateAndPolicy();
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 4c73a9e..9841f94 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -320,16 +320,6 @@
     instant_service_->ResetCustomLinks();
 }
 
-void SearchTabHelper::OnDoesUrlResolve(
-    const GURL& url,
-    chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback) {
-  DCHECK(!url.is_empty());
-  if (instant_service_)
-    instant_service_->DoesUrlResolve(url, std::move(callback));
-  else
-    std::move(callback).Run(/*resolves=*/true, /*timeout=*/false);
-}
-
 void SearchTabHelper::OnLogEvent(NTPLoggingEventType event,
                                  base::TimeDelta time) {
   NTPUserDataLogger::GetOrCreateFromWebContents(web_contents())
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index aadab8ab..4805461 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -107,9 +107,6 @@
   bool OnDeleteCustomLink(const GURL& url) override;
   void OnUndoCustomLinkAction() override;
   void OnResetCustomLinks() override;
-  void OnDoesUrlResolve(
-      const GURL& url,
-      chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback) override;
   void OnLogEvent(NTPLoggingEventType event, base::TimeDelta time) override;
   void OnLogMostVisitedImpression(
       const ntp_tiles::NTPTileImpression& impression) override;
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index 43c89c07..404e4448 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -66,10 +66,6 @@
   MOCK_METHOD1(OnDeleteCustomLink, bool(const GURL& url));
   MOCK_METHOD0(OnUndoCustomLinkAction, void());
   MOCK_METHOD0(OnResetCustomLinks, void());
-  MOCK_METHOD2(
-      OnDoesUrlResolve,
-      void(const GURL& url,
-           chrome::mojom::EmbeddedSearch::DoesUrlResolveCallback callback));
   MOCK_METHOD2(OnLogEvent, void(NTPLoggingEventType event,
                                 base::TimeDelta time));
   MOCK_METHOD1(OnLogMostVisitedImpression,
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 9507163..bacbe888 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -291,29 +291,6 @@
       views::EMPHASIS_MAXIMUM, size());
 }
 
-SkColor LocationBarView::GetSecurityChipColor(
-    security_state::SecurityLevel security_level) const {
-  // Only used in ChromeOS.
-  if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT)
-    return GetColor(OmniboxPart::LOCATION_BAR_TEXT_DIMMED);
-
-  OmniboxPartState state = OmniboxPartState::CHIP_DEFAULT;
-  if (security_level == security_state::EV_SECURE ||
-      security_level == security_state::SECURE) {
-    state = OmniboxPartState::CHIP_SECURE;
-  } else if (security_level == security_state::DANGEROUS) {
-    state = OmniboxPartState::CHIP_DANGEROUS;
-  }
-
-  return GetOmniboxColor(OmniboxPart::LOCATION_BAR_SECURITY_CHIP, tint(),
-                         state);
-}
-
-SkColor LocationBarView::GetIconInkDropColor() const {
-  return GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_TextfieldDefaultColor);
-}
-
 std::unique_ptr<views::Background> LocationBarView::CreateRoundRectBackground(
     SkColor background_color,
     SkColor stroke_color,
@@ -353,36 +330,6 @@
   omnibox_view_->SelectAll(true);
 }
 
-bool LocationBarView::ShowPageInfoDialog(WebContents* contents) {
-  DCHECK(contents);
-  content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
-  if (!entry)
-    return false;
-
-  SecurityStateTabHelper* helper =
-      SecurityStateTabHelper::FromWebContents(contents);
-  DCHECK(helper);
-  security_state::SecurityInfo security_info;
-  helper->GetSecurityInfo(&security_info);
-
-  DCHECK(GetWidget());
-  views::BubbleDialogDelegateView* bubble =
-      PageInfoBubbleView::CreatePageInfoBubble(
-          this, gfx::Rect(), GetWidget()->GetNativeWindow(), profile(),
-          contents, entry->GetVirtualURL(), security_info);
-  bubble->SetHighlightedButton(location_icon_view());
-  bubble->GetWidget()->Show();
-
-  // When the user opens the page info bubble, we also expose the full URL,
-  // temporarily disabling Steady State Elisions and Query in Omnibox.
-  // We are currently gating this behavior on the Query in Omnibox flag, since
-  // it's still under active experimentation.
-  if (base::FeatureList::IsEnabled(omnibox::kQueryInOmnibox))
-    omnibox_view()->model()->Unelide(true /* exit_query_in_omnibox */);
-
-  return true;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // LocationBarView, public LocationBar implementation:
 
@@ -434,10 +381,8 @@
   int leading_width = 0;
   if (ShouldShowKeywordBubble()) {
     // The selected keyword view can collapse completely.
-  } else if (ShouldShowLocationIconText()) {
-    leading_width =
-        location_icon_view_->GetMinimumSizeForLabelText(GetLocationIconText())
-            .width();
+  } else if (location_icon_view_->ShouldShowText()) {
+    leading_width = location_icon_view_->GetMinimumLabelTextWidth();
   } else {
     leading_width = GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING) +
                     location_icon_view_->GetMinimumSize().width();
@@ -528,7 +473,6 @@
   // label/chip.
   const double kLeadingDecorationMaxFraction = 0.5;
 
-  location_icon_view_->SetLabel(base::string16());
   if (ShouldShowKeywordBubble()) {
     location_icon_view_->SetVisible(false);
     leading_decorations.AddDecoration(vertical_padding, location_height, false,
@@ -548,8 +492,7 @@
         selected_keyword_view_->ResetImage();
       }
     }
-  } else if (ShouldShowLocationIconText()) {
-    location_icon_view_->SetLabel(GetLocationIconText());
+  } else if (location_icon_view_->ShouldShowText()) {
     leading_decorations.AddDecoration(vertical_padding, location_height, false,
                                       kLeadingDecorationMaxFraction,
                                       edge_padding, location_icon_view_);
@@ -651,7 +594,7 @@
     return;
 
   RefreshBackground();
-  RefreshLocationIcon();
+  location_icon_view_->Update();
   RefreshClearAllButtonIcon();
   SchedulePaint();
 }
@@ -665,6 +608,7 @@
   RefreshContentSettingViews();
 
   RefreshPageActionIconViews();
+  location_icon_view_->Update();
 
   if (star_view_) {
     // TODO(calamity): Refactor Update to use PageActionIconView::Refresh.
@@ -676,11 +620,7 @@
   else
     omnibox_view_->Update();
 
-  location_icon_view_->SetTextVisibility(
-      ShouldShowLocationIconText(),
-      !contents && ShouldAnimateLocationIconTextVisibilityChange());
   OnChanged();  // NOTE: Calls Layout().
-  last_update_security_level_ = GetToolbarModel()->GetSecurityLevel(false);
 }
 
 void LocationBarView::ResetTabState(WebContents* contents) {
@@ -728,7 +668,7 @@
 // LocationBarView, public ContentSettingImageView::Delegate implementation:
 
 SkColor LocationBarView::GetContentSettingInkDropColor() const {
-  return GetIconInkDropColor();
+  return GetLocationIconInkDropColor();
 }
 
 content::WebContents* LocationBarView::GetContentSettingWebContents() {
@@ -744,7 +684,7 @@
 // LocationBarView, public PageActionIconView::Delegate implementation:
 
 SkColor LocationBarView::GetPageActionInkDropColor() const {
-  return GetIconInkDropColor();
+  return GetLocationIconInkDropColor();
 }
 
 WebContents* LocationBarView::GetWebContentsForPageActionIconView() {
@@ -831,27 +771,6 @@
   SchedulePaint();
 }
 
-void LocationBarView::RefreshLocationIcon() {
-  // Cancel any previous outstanding icon requests, as they are now outdated.
-  icon_fetch_weak_ptr_factory_.InvalidateWeakPtrs();
-
-  security_state::SecurityLevel security_level =
-      GetToolbarModel()->GetSecurityLevel(false);
-
-  gfx::ImageSkia icon = omnibox_view_->GetIcon(
-      GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
-      GetSecurityChipColor(security_level),
-      base::BindOnce(&LocationBarView::OnLocationIconFetched,
-                     icon_fetch_weak_ptr_factory_.GetWeakPtr()));
-
-  location_icon_view_->SetImage(icon);
-  location_icon_view_->Update();
-}
-
-void LocationBarView::OnLocationIconFetched(const gfx::Image& image) {
-  location_icon_view_->SetImage(image.AsImageSkia());
-}
-
 bool LocationBarView::RefreshContentSettingViews() {
   if (extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
           browser_)) {
@@ -938,59 +857,10 @@
   focus_ring_->SetPath(path);
 }
 
-base::string16 LocationBarView::GetLocationIconText() const {
-  if (GetToolbarModel()->GetURL().SchemeIs(content::kChromeUIScheme))
-    return l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
-
-  if (GetToolbarModel()->GetURL().SchemeIs(url::kFileScheme))
-    return l10n_util::GetStringUTF16(IDS_OMNIBOX_FILE);
-
-  if (delegate_->GetWebContents()) {
-    // On ChromeOS, this can be called using web_contents from
-    // SimpleWebViewDialog::GetWebContents() which always returns null.
-    // TODO(crbug.com/680329) Remove the null check and make
-    // SimpleWebViewDialog::GetWebContents return the proper web contents
-    // instead.
-    const base::string16 extension_name =
-        extensions::ui_util::GetEnabledExtensionNameForUrl(
-            GetToolbarModel()->GetURL(),
-            delegate_->GetWebContents()->GetBrowserContext());
-    if (!extension_name.empty())
-      return extension_name;
-  }
-
-  return GetToolbarModel()->GetSecureVerboseText();
-}
-
 bool LocationBarView::ShouldShowKeywordBubble() const {
   return omnibox_view_->model()->is_keyword_selected();
 }
 
-bool LocationBarView::ShouldShowLocationIconText() const {
-  const auto* toolbar_model = GetToolbarModel();
-  if (!toolbar_model->input_in_progress()) {
-    const GURL& url = toolbar_model->GetURL();
-    if (url.SchemeIs(content::kChromeUIScheme) ||
-        url.SchemeIs(extensions::kExtensionScheme) ||
-        url.SchemeIs(url::kFileScheme))
-      return true;
-  }
-
-  return !toolbar_model->GetSecureVerboseText().empty();
-}
-
-bool LocationBarView::ShouldAnimateLocationIconTextVisibilityChange() const {
-  using SecurityLevel = security_state::SecurityLevel;
-  SecurityLevel level = GetToolbarModel()->GetSecurityLevel(false);
-  // Do not animate transitions from HTTP_SHOW_WARNING to DANGEROUS, since the
-  // transition can look confusing/messy.
-  if (level == SecurityLevel::DANGEROUS &&
-      last_update_security_level_ == SecurityLevel::HTTP_SHOW_WARNING)
-    return false;
-  return level == SecurityLevel::DANGEROUS ||
-         level == SecurityLevel::HTTP_SHOW_WARNING;
-}
-
 OmniboxPopupView* LocationBarView::GetOmniboxPopupView() {
   DCHECK(IsInitialized());
   return omnibox_view_->model()->popup_model()->view();
@@ -1241,8 +1111,7 @@
 // LocationBarView, private OmniboxEditController implementation:
 
 void LocationBarView::OnChanged() {
-  RefreshLocationIcon();
-  location_icon_view_->set_show_tooltip(!GetOmniboxView()->IsEditingOrEmpty());
+  location_icon_view_->Update();
   clear_all_button_->SetVisible(GetToolbarModel()->input_in_progress() &&
                                 !omnibox_view_->text().empty() &&
                                 IsVirtualKeyboardVisible(GetWidget()));
@@ -1316,7 +1185,100 @@
     view->SetFontList(font_list);
   if (save_credit_card_icon_view_)
     save_credit_card_icon_view_->SetFontList(font_list);
-  RefreshLocationIcon();
+  location_icon_view_->Update();
   Layout();
   SchedulePaint();
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// LocationBarView, LocationBarIconView::Delegate implementation:
+
+bool LocationBarView::IsEditingOrEmpty() {
+  return omnibox_view() && omnibox_view()->IsEditingOrEmpty();
+}
+
+void LocationBarView::OnLocationIconPressed(const ui::MouseEvent& event) {
+  if (event.IsOnlyMiddleMouseButton() &&
+      ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION)) {
+    base::string16 text;
+    ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_SELECTION,
+                                                   &text);
+    text = OmniboxView::SanitizeTextForPaste(text);
+
+    if (!GetOmniboxView()->model()->CanPasteAndGo(text)) {
+      return;
+    }
+
+    GetOmniboxView()->model()->PasteAndGo(text, event.time_stamp());
+  }
+}
+
+void LocationBarView::OnLocationIconDragged(const ui::MouseEvent& event) {
+  GetOmniboxView()->CloseOmniboxPopup();
+}
+
+SkColor LocationBarView::GetSecurityChipColor(
+    security_state::SecurityLevel security_level) const {
+  // Only used in ChromeOS.
+  if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT)
+    return GetColor(OmniboxPart::LOCATION_BAR_TEXT_DIMMED);
+
+  OmniboxPartState state = OmniboxPartState::CHIP_DEFAULT;
+  if (security_level == security_state::EV_SECURE ||
+      security_level == security_state::SECURE) {
+    state = OmniboxPartState::CHIP_SECURE;
+  } else if (security_level == security_state::DANGEROUS) {
+    state = OmniboxPartState::CHIP_DANGEROUS;
+  }
+
+  return GetOmniboxColor(OmniboxPart::LOCATION_BAR_SECURITY_CHIP, tint(),
+                         state);
+}
+
+bool LocationBarView::ShowPageInfoDialog() {
+  WebContents* contents = GetWebContents();
+  if (!contents)
+    return false;
+
+  content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
+  if (!entry)
+    return false;
+
+  SecurityStateTabHelper* helper =
+      SecurityStateTabHelper::FromWebContents(contents);
+  DCHECK(helper);
+  security_state::SecurityInfo security_info;
+  helper->GetSecurityInfo(&security_info);
+
+  DCHECK(GetWidget());
+  views::BubbleDialogDelegateView* bubble =
+      PageInfoBubbleView::CreatePageInfoBubble(
+          this, gfx::Rect(), GetWidget()->GetNativeWindow(), profile(),
+          contents, entry->GetVirtualURL(), security_info);
+  bubble->SetHighlightedButton(location_icon_view());
+  bubble->GetWidget()->Show();
+
+  // When the user opens the page info bubble, we also expose the full URL,
+  // temporarily disabling Steady State Elisions and Query in Omnibox.
+  // We are currently gating this behavior on the Query in Omnibox flag, since
+  // it's still under active experimentation.
+  if (base::FeatureList::IsEnabled(omnibox::kQueryInOmnibox))
+    omnibox_view()->model()->Unelide(true /* exit_query_in_omnibox */);
+
+  return true;
+}
+
+gfx::ImageSkia LocationBarView::GetLocationIcon(
+    LocationIconView::Delegate::IconFetchedCallback on_icon_fetched) const {
+  return omnibox_view() ? omnibox_view()->GetIcon(
+                              GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
+                              GetSecurityChipColor(
+                                  GetToolbarModel()->GetSecurityLevel(false)),
+                              std::move(on_icon_fetched))
+                        : gfx::ImageSkia();
+}
+
+SkColor LocationBarView::GetLocationIconInkDropColor() const {
+  return GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_TextfieldDefaultColor);
+}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index f198fd8..7c1b89bb 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -22,6 +22,7 @@
 #include "chrome/browser/ui/views/dropdown_bar_host_delegate.h"
 #include "chrome/browser/ui/views/extensions/extension_popup.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
+#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "components/prefs/pref_member.h"
@@ -78,6 +79,7 @@
                         public ChromeOmniboxEditController,
                         public DropdownBarHostDelegate,
                         public views::ButtonListener,
+                        public LocationIconView::Delegate,
                         public ContentSettingImageView::Delegate,
                         public PageActionIconView::Delegate,
                         public ui::MaterialDesignControllerObserver {
@@ -126,14 +128,6 @@
   // It's guaranteed to be opaque.
   SkColor GetOpaqueBorderColor(bool incognito) const;
 
-  // Returns the color to be used for the security chip in the context of
-  // |security_level|.
-  SkColor GetSecurityChipColor(
-      security_state::SecurityLevel security_level) const;
-
-  // Returns the color to use for icon ink highlights.
-  SkColor GetIconInkDropColor() const;
-
   // Returns the cached theme color tint for the location bar and results.
   OmniboxTint tint() const { return tint_; }
 
@@ -201,10 +195,6 @@
     return selected_keyword_view_;
   }
 
-  // Show a page info dialog for |web_contents|.
-  // Returns true if a dialog was shown, false otherwise.
-  bool ShowPageInfoDialog(content::WebContents* web_contents);
-
   OmniboxViewViews* omnibox_view() { return omnibox_view_; }
   const OmniboxViewViews* omnibox_view() const { return omnibox_view_; }
 
@@ -264,6 +254,17 @@
 
   Browser* browser() { return browser_; }
 
+  // LocationIconView::Delegate
+  bool IsEditingOrEmpty() override;
+  void OnLocationIconPressed(const ui::MouseEvent& event) override;
+  void OnLocationIconDragged(const ui::MouseEvent& event) override;
+  bool ShowPageInfoDialog() override;
+  SkColor GetSecurityChipColor(
+      security_state::SecurityLevel security_level) const override;
+  gfx::ImageSkia GetLocationIcon(LocationIconView::Delegate::IconFetchedCallback
+                                     on_icon_fetched) const override;
+  SkColor GetLocationIconInkDropColor() const override;
+
  private:
   FRIEND_TEST_ALL_PREFIXES(SecurityIndicatorTest, CheckIndicatorText);
   FRIEND_TEST_ALL_PREFIXES(TouchLocationBarViewBrowserTest,
@@ -287,12 +288,6 @@
   // Updates the background on a theme change, or dropdown state change.
   void RefreshBackground();
 
-  // Updates |location_icon_view_| based on the current state and theme.
-  void RefreshLocationIcon();
-
-  // Handles the arrival of an asynchronously fetched location bar icon.
-  void OnLocationIconFetched(const gfx::Image& image);
-
   // Updates the visibility state of the Content Blocked icons to reflect what
   // is actually blocked on the current page. Returns true if the visibility
   // of at least one of the views in |content_setting_views_| changed.
@@ -308,25 +303,9 @@
   // Updates the focus ring.
   void RefreshFocusRing();
 
-  // Returns text to be placed in the location icon view.
-  // - For secure/insecure pages, returns text describing the URL's security
-  // level.
-  // - For extension URLs, returns the extension name.
-  // - For chrome:// URLs, returns the short product name (e.g. Chrome).
-  // - For file:// URLs, returns the text "File".
-  base::string16 GetLocationIconText() const;
-
   // Returns true if a keyword is selected in the model.
   bool ShouldShowKeywordBubble() const;
 
-  // Returns true if any of the following is true:
-  // - the current page is explicitly secure or insecure.
-  // - the current page URL is a chrome-extension:// URL.
-  bool ShouldShowLocationIconText() const;
-
-  // Returns true if the location icon text should be animated.
-  bool ShouldAnimateLocationIconTextVisibilityChange() const;
-
   // Gets the OmniboxPopupView associated with the model in |omnibox_view_|.
   OmniboxPopupView* GetOmniboxPopupView();
 
@@ -477,11 +456,6 @@
   // PageActionIconContainerView (https://crbug.com/788051), ordered by focus.
   std::vector<PageActionIconView*> page_action_icons_;
 
-  // The security level when the location bar was last updated. Used to decide
-  // whether to animate security level transitions.
-  security_state::SecurityLevel last_update_security_level_ =
-      security_state::NONE;
-
   // The focus ring, if one is in use.
   std::unique_ptr<views::FocusRing> focus_ring_;
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
index 0ba91ff..79cfa92 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
@@ -319,8 +319,9 @@
     helper->GetSecurityInfo(&security_info);
     EXPECT_EQ(c.security_level, security_info.security_level);
     EXPECT_EQ(c.should_show_text,
-              location_bar_view->ShouldShowLocationIconText());
-    EXPECT_EQ(c.indicator_text, location_bar_view->GetLocationIconText());
+              location_bar_view->location_icon_view()->ShouldShowLabel());
+    EXPECT_EQ(c.indicator_text,
+              location_bar_view->location_icon_view()->GetText());
     ResetInterceptor();
   }
 }
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index 41a579f..61774fa 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -4,16 +4,21 @@
 
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 
+#include "chrome/browser/extensions/extension_ui_util.h"
+#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/page_info/page_info_dialog.h"
 #include "chrome/browser/ui/view_ids.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
+#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/toolbar_model.h"
+#include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/constants.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/label.h"
@@ -21,8 +26,8 @@
 using content::WebContents;
 
 LocationIconView::LocationIconView(const gfx::FontList& font_list,
-                                   LocationBarView* location_bar)
-    : IconLabelBubbleView(font_list), location_bar_(location_bar) {
+                                   Delegate* delegate)
+    : IconLabelBubbleView(font_list), delegate_(delegate) {
   label()->SetElideBehavior(gfx::ELIDE_MIDDLE);
   set_id(VIEW_ID_LOCATION_ICON);
   Update();
@@ -37,23 +42,14 @@
 }
 
 bool LocationIconView::OnMousePressed(const ui::MouseEvent& event) {
-  if (event.IsOnlyMiddleMouseButton() &&
-      ui::Clipboard::IsSupportedClipboardType(ui::CLIPBOARD_TYPE_SELECTION)) {
-    base::string16 text;
-    ui::Clipboard::GetForCurrentThread()->ReadText(
-        ui::CLIPBOARD_TYPE_SELECTION, &text);
-    text = OmniboxView::SanitizeTextForPaste(text);
-    OmniboxEditModel* model = location_bar_->GetOmniboxView()->model();
-    if (model->CanPasteAndGo(text))
-      model->PasteAndGo(text, event.time_stamp());
-  }
+  delegate_->OnLocationIconPressed(event);
 
   IconLabelBubbleView::OnMousePressed(event);
   return true;
 }
 
 bool LocationIconView::OnMouseDragged(const ui::MouseEvent& event) {
-  location_bar_->GetOmniboxView()->CloseOmniboxPopup();
+  delegate_->OnLocationIconDragged(event);
   return IconLabelBubbleView::OnMouseDragged(event);
 }
 
@@ -65,8 +61,8 @@
 }
 
 SkColor LocationIconView::GetTextColor() const {
-  return location_bar_->GetSecurityChipColor(
-      location_bar_->GetToolbarModel()->GetSecurityLevel(false));
+  return delegate_->GetSecurityChipColor(
+      delegate_->GetToolbarModel()->GetSecurityLevel(false));
 }
 
 bool LocationIconView::ShouldShowSeparator() const {
@@ -76,36 +72,33 @@
   if (OmniboxFieldTrial::IsJogTextfieldOnPopupEnabled())
     return false;
 
-  return !location_bar_->GetOmniboxView()->IsEditingOrEmpty();
+  return !delegate_->IsEditingOrEmpty();
 }
 
 bool LocationIconView::ShouldShowExtraEndSpace() const {
   if (OmniboxFieldTrial::IsJogTextfieldOnPopupEnabled())
     return false;
 
-  return location_bar_->GetOmniboxView()->IsEditingOrEmpty();
+  return delegate_->IsEditingOrEmpty();
 }
 
 bool LocationIconView::ShowBubble(const ui::Event& event) {
-  auto* contents = location_bar_->GetWebContents();
-  if (!contents)
-    return false;
-  return location_bar_->ShowPageInfoDialog(contents);
+  return delegate_->ShowPageInfoDialog();
 }
 
 SkColor LocationIconView::GetInkDropBaseColor() const {
-  return location_bar_->GetIconInkDropColor();
+  return delegate_->GetLocationIconInkDropColor();
 }
 
 void LocationIconView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
-  if (location_bar_->GetOmniboxView()->IsEditingOrEmpty()) {
+  if (delegate_->IsEditingOrEmpty()) {
     node_data->role = ax::mojom::Role::kImage;
     node_data->SetName(l10n_util::GetStringUTF8(IDS_ACC_SEARCH_ICON));
     return;
   }
 
   security_state::SecurityLevel security_level =
-      location_bar_->GetToolbarModel()->GetSecurityLevel(false);
+      delegate_->GetToolbarModel()->GetSecurityLevel(false);
   if (label()->text().empty() && (security_level == security_state::EV_SECURE ||
                                   security_level == security_state::SECURE)) {
     node_data->AddStringAttribute(
@@ -122,9 +115,10 @@
          PageInfoBubbleView::BUBBLE_NONE;
 }
 
-gfx::Size LocationIconView::GetMinimumSizeForLabelText(
-    const base::string16& text) const {
+int LocationIconView::GetMinimumLabelTextWidth() const {
   int width = 0;
+
+  base::string16 text = GetText();
   if (text == label()->text()) {
     // Optimize this common case by not creating a new label.
     // GetPreferredSize is not dependent on the label's current
@@ -134,12 +128,64 @@
     views::Label label(text, {font_list()});
     width = label.GetPreferredSize().width();
   }
-  return GetMinimumSizeForPreferredSize(GetSizeForLabelWidth(width));
+  return GetMinimumSizeForPreferredSize(GetSizeForLabelWidth(width)).width();
 }
 
-void LocationIconView::SetTextVisibility(bool should_show,
-                                         bool should_animate) {
-  if (!should_animate)
+bool LocationIconView::ShouldShowText() const {
+  const auto* toolbar_model = delegate_->GetToolbarModel();
+
+  if (!toolbar_model->input_in_progress()) {
+    const GURL& url = toolbar_model->GetURL();
+    if (url.SchemeIs(content::kChromeUIScheme) ||
+        url.SchemeIs(extensions::kExtensionScheme) ||
+        url.SchemeIs(url::kFileScheme))
+      return true;
+  }
+
+  return !toolbar_model->GetSecureVerboseText().empty();
+}
+
+base::string16 LocationIconView::GetText() const {
+  if (delegate_->GetToolbarModel()->GetURL().SchemeIs(content::kChromeUIScheme))
+    return l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
+
+  if (delegate_->GetToolbarModel()->GetURL().SchemeIs(url::kFileScheme))
+    return l10n_util::GetStringUTF16(IDS_OMNIBOX_FILE);
+
+  if (delegate_->GetWebContents()) {
+    // On ChromeOS, this can be called using web_contents from
+    // SimpleWebViewDialog::GetWebContents() which always returns null.
+    // TODO(crbug.com/680329) Remove the null check and make
+    // SimpleWebViewDialog::GetWebContents return the proper web contents
+    // instead.
+    const base::string16 extension_name =
+        extensions::ui_util::GetEnabledExtensionNameForUrl(
+            delegate_->GetToolbarModel()->GetURL(),
+            delegate_->GetWebContents()->GetBrowserContext());
+    if (!extension_name.empty())
+      return extension_name;
+  }
+
+  return delegate_->GetToolbarModel()->GetSecureVerboseText();
+}
+
+bool LocationIconView::ShouldAnimateTextVisibilityChange() const {
+  using SecurityLevel = security_state::SecurityLevel;
+  SecurityLevel level = delegate_->GetToolbarModel()->GetSecurityLevel(false);
+  // Do not animate transitions from HTTP_SHOW_WARNING to DANGEROUS, since the
+  // transition can look confusing/messy.
+  if (level == SecurityLevel::DANGEROUS &&
+      last_update_security_level_ == SecurityLevel::HTTP_SHOW_WARNING)
+    return false;
+  return (level == SecurityLevel::DANGEROUS ||
+          level == SecurityLevel::HTTP_SHOW_WARNING);
+}
+
+void LocationIconView::UpdateTextVisibility() {
+  SetLabel(GetText());
+
+  bool should_show = ShouldShowText();
+  if (!ShouldAnimateTextVisibilityChange())
     ResetSlideAnimation(should_show);
   else if (should_show)
     AnimateIn(base::nullopt);
@@ -150,13 +196,34 @@
   OnNativeThemeChanged(GetNativeTheme());
 }
 
+void LocationIconView::UpdateIcon() {
+  // Cancel any previous outstanding icon requests, as they are now outdated.
+  icon_fetch_weak_ptr_factory_.InvalidateWeakPtrs();
+
+  gfx::ImageSkia icon = delegate_->GetLocationIcon(
+      base::BindOnce(&LocationIconView::OnIconFetched,
+                     icon_fetch_weak_ptr_factory_.GetWeakPtr()));
+
+  SetImage(icon);
+}
+
+void LocationIconView::OnIconFetched(const gfx::Image& image) {
+  SetImage(image.AsImageSkia());
+}
+
 void LocationIconView::Update() {
+  UpdateTextVisibility();
+  UpdateIcon();
+
+  bool is_editing_or_empty = delegate_->IsEditingOrEmpty();
+  // The tooltip should be shown if we are not editing or empty.
+  show_tooltip_ = !is_editing_or_empty;
+
   // If the omnibox is empty or editing, the user should not be able to left
   // click on the icon. As such, the icon should not show a highlight or be
   // focusable. Note: using the middle mouse to copy-and-paste should still
   // work on the icon.
-  if (location_bar_->GetOmniboxView() &&
-      location_bar_->GetOmniboxView()->IsEditingOrEmpty()) {
+  if (is_editing_or_empty) {
     SetInkDropMode(InkDropMode::OFF);
     SetFocusBehavior(FocusBehavior::NEVER);
     return;
@@ -169,10 +236,13 @@
 #else
   SetFocusBehavior(FocusBehavior::ALWAYS);
 #endif
+
+  last_update_security_level_ =
+      delegate_->GetToolbarModel()->GetSecurityLevel(false);
 }
 
 bool LocationIconView::IsTriggerableEvent(const ui::Event& event) {
-  if (location_bar_->GetOmniboxView()->IsEditingOrEmpty())
+  if (delegate_->IsEditingOrEmpty())
     return false;
 
   if (event.IsMouseEvent()) {
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.h b/chrome/browser/ui/views/location_bar/location_icon_view.h
index 1d4187e..0106fc0 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -7,8 +7,15 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
+#include "components/omnibox/browser/toolbar_model.h"
 
-class LocationBarView;
+namespace content {
+class WebContents;
+}
+
+namespace security_state {
+enum SecurityLevel;
+}
 
 // Use a LocationIconView to display an icon on the leading side of the edit
 // field. It shows the user's current action (while the user is editing), or the
@@ -16,8 +23,48 @@
 // the URL is a chrome-extension:// URL).
 class LocationIconView : public IconLabelBubbleView {
  public:
-  LocationIconView(const gfx::FontList& font_list,
-                   LocationBarView* location_bar);
+  class Delegate {
+   public:
+    using IconFetchedCallback =
+        base::OnceCallback<void(const gfx::Image& icon)>;
+
+    // Gets the web contents the location icon is for.
+    virtual content::WebContents* GetWebContents() = 0;
+
+    // Determines whether the omnibox (if any) is editing or empty.
+    virtual bool IsEditingOrEmpty() = 0;
+
+    // Called when the location icon is pressed, with the event.
+    virtual void OnLocationIconPressed(const ui::MouseEvent& event) {}
+
+    // Called when the LocationIcon is dragged.
+    virtual void OnLocationIconDragged(const ui::MouseEvent& event) {}
+
+    // Returns the color to be used for the security chip in the context of
+    // |security_level|.
+    virtual SkColor GetSecurityChipColor(
+        security_state::SecurityLevel security_level) const = 0;
+
+    // Shows the PageInfo Dialog. This is called so that the delegate can decide
+    // how and where to show the dialog. Returns true if a dialog was shown,
+    // false otherwise.
+    virtual bool ShowPageInfoDialog() = 0;
+
+    // Gets the ToolbarModel.
+    const virtual ToolbarModel* GetToolbarModel() const = 0;
+
+    // Gets an icon for the location bar icon chip.
+    virtual gfx::ImageSkia GetLocationIcon(
+        IconFetchedCallback on_icon_fetched) const = 0;
+
+    // Gets the color to use for icon ink highlights.
+    virtual SkColor GetLocationIconInkDropColor() const = 0;
+
+   protected:
+    virtual ~Delegate() {}
+  };
+
+  LocationIconView(const gfx::FontList& font_list, Delegate* delagate);
   ~LocationIconView() override;
 
   // IconLabelBubbleView:
@@ -34,27 +81,37 @@
   bool IsBubbleShowing() const override;
   SkColor GetInkDropBaseColor() const override;
 
-  // Whether we should show the tooltip for this icon or not.
-  void set_show_tooltip(bool show_tooltip) { show_tooltip_ = show_tooltip; }
-
-  // Returns what the minimum size would be if the label text were |text|.
-  gfx::Size GetMinimumSizeForLabelText(const base::string16& text) const;
-
-  const gfx::FontList& GetFontList() const { return font_list(); }
-
-  // Sets whether the text should be visible. |should_animate| controls whether
-  // any necessary transition to this state should be animated.
-  void SetTextVisibility(bool should_show, bool should_animate);
+  // Returns what the minimum width for the label text.
+  int GetMinimumLabelTextWidth() const;
 
   // Updates the icon's ink drop mode and focusable behavior.
   void Update();
 
+  // Returns text to be placed in the view.
+  // - For secure/insecure pages, returns text describing the URL's security
+  // level.
+  // - For extension URLs, returns the extension name.
+  // - For chrome:// URLs, returns the short product name (e.g. Chrome).
+  // - For file:// URLs, returns the text "File".
+  base::string16 GetText() const;
+
+  // Determines whether or not text should be shown (e.g Insecure/Secure).
+  // Returns true if any of the following is true:
+  // - the current page is explicitly secure or insecure.
+  // - the current page URL is a chrome-extension:// URL.
+  bool ShouldShowText() const;
+
  protected:
   // IconLabelBubbleView:
   bool IsTriggerableEvent(const ui::Event& event) override;
   double WidthMultiplier() const override;
 
  private:
+  // The security level when the location icon was last updated. Used to decide
+  // whether to animate security level transitions.
+  security_state::SecurityLevel last_update_security_level_ =
+      security_state::NONE;
+
   // Returns what the minimum size would be if the preferred size were |size|.
   gfx::Size GetMinimumSizeForPreferredSize(gfx::Size size) const;
 
@@ -63,7 +120,26 @@
   // True if hovering this view should display a tooltip.
   bool show_tooltip_;
 
-  LocationBarView* location_bar_;
+  Delegate* delegate_;
+
+  // Used to scope the lifetime of asynchronous icon fetch callbacks to the
+  // lifetime of the object. Weak pointers issued by this factory are
+  // invalidated whenever we start a new icon fetch, so don't use this weak
+  // factory for any other purposes.
+  base::WeakPtrFactory<LocationIconView> icon_fetch_weak_ptr_factory_{this};
+
+  // Determines whether or not a text change should be animated.
+  bool ShouldAnimateTextVisibilityChange() const;
+
+  // Updates visibility of the text and determines whether the transition
+  // (if any) should be animated.
+  void UpdateTextVisibility();
+
+  // Updates Icon based on the current state and theme.
+  void UpdateIcon();
+
+  // Handles the arrival of an asynchronously fetched icon.
+  void OnIconFetched(const gfx::Image& image);
 
   DISALLOW_COPY_AND_ASSIGN(LocationIconView);
 };
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
index 60771609..0d36dc1 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -46,7 +46,7 @@
 }
 
 SkColor SelectedKeywordView::GetInkDropBaseColor() const {
-  return location_bar_->GetIconInkDropColor();
+  return location_bar_->GetLocationIconInkDropColor();
 }
 
 gfx::Size SelectedKeywordView::CalculatePreferredSize() const {
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
index b7b4bb6..1ac68bd 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/profiles/incognito_window_count_view.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "services/identity/public/cpp/identity_manager.h"
@@ -152,10 +153,17 @@
   // TODO(bsep): Other toolbar buttons have ToolbarView as a listener and let it
   // call ExecuteCommandWithDisposition on their behalf. Unfortunately, it's not
   // possible to plumb IsKeyEvent through, so this has to be a special case.
-  browser_->window()->ShowAvatarBubbleFromAvatarButton(
-      BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT, signin::ManageAccountsParams(),
-      signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN,
-      event.IsKeyEvent());
+  if (IsIncognitoCounterActive()) {
+    IncognitoWindowCountView::ShowBubble(
+        this, browser_,
+        BrowserList::GetIncognitoSessionsActiveForProfile(profile_));
+  } else {
+    browser_->window()->ShowAvatarBubbleFromAvatarButton(
+        BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT,
+        signin::ManageAccountsParams(),
+        signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN,
+        event.IsKeyEvent());
+  }
 }
 
 void AvatarToolbarButton::OnAvatarErrorChanged() {
diff --git a/chrome/browser/ui/views/profiles/incognito_window_count_view.cc b/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
new file mode 100644
index 0000000..eedaef8
--- /dev/null
+++ b/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
@@ -0,0 +1,106 @@
+// 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/ui/views/profiles/incognito_window_count_view.h"
+
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/fill_layout.h"
+
+// static
+void IncognitoWindowCountView::ShowBubble(views::Button* anchor_button,
+                                          Browser* browser,
+                                          int incognito_window_count) {
+  // The IncognitoWindowCountView is self-owned, it deletes itself when the
+  // widget is closed or the parent browser is destroyed.
+  new IncognitoWindowCountView(anchor_button, browser, incognito_window_count);
+}
+
+IncognitoWindowCountView::IncognitoWindowCountView(views::Button* anchor_button,
+                                                   Browser* browser,
+                                                   int incognito_window_count)
+    : BubbleDialogDelegateView(anchor_button, views::BubbleBorder::TOP_RIGHT),
+      incognito_window_count_(incognito_window_count),
+      browser_(browser),
+      browser_list_observer_(this),
+      weak_ptr_factory_(this) {
+  browser_list_observer_.Add(BrowserList::GetInstance());
+
+  // The lifetime of this bubble is tied to the lifetime of the browser.
+  set_parent_window(
+      platform_util::GetViewForWindow(browser_->window()->GetNativeWindow()));
+
+  views::BubbleDialogDelegateView::CreateBubble(this)->Show();
+  chrome::RecordDialogCreation(
+      chrome::DialogIdentifier::INCOGNITO_WINDOW_COUNTER);
+}
+
+IncognitoWindowCountView::~IncognitoWindowCountView() {}
+
+void IncognitoWindowCountView::OnBrowserRemoved(Browser* browser) {
+  if (browser_ == browser)
+    delete this;
+}
+
+base::string16 IncognitoWindowCountView::GetWindowTitle() const {
+  return l10n_util::GetStringUTF16(IDS_INCOGNITO_WINDOW_COUNTER_TITLE);
+}
+
+int IncognitoWindowCountView::GetDialogButtons() const {
+  return ui::DIALOG_BUTTON_OK;
+}
+
+base::string16 IncognitoWindowCountView::GetDialogButtonLabel(
+    ui::DialogButton button) const {
+  DCHECK_EQ(ui::DIALOG_BUTTON_OK, button);
+  if (ui::DIALOG_BUTTON_OK) {
+    return l10n_util::GetPluralStringFUTF16(
+        IDS_INCOGNITO_WINDOW_COUNTER_CLOSE_BUTTON, incognito_window_count_);
+  }
+  return NULL;
+}
+
+bool IncognitoWindowCountView::ShouldShowCloseButton() const {
+  return true;
+}
+
+bool IncognitoWindowCountView::ShouldShowWindowIcon() const {
+  return true;
+}
+
+gfx::ImageSkia IncognitoWindowCountView::GetWindowIcon() {
+  // TODO(http://crbug.com/896235): Update color and size based on theme and UX
+  // feedback.
+  return gfx::CreateVectorIcon(kIncognitoIcon, 24, gfx::kGoogleGrey050);
+}
+
+bool IncognitoWindowCountView::Close() {
+  // By default, closing the dialog would call Accept(), which would result in
+  // data loss, so we intentionally just do nothing and close the dialog.
+  return true;
+}
+
+bool IncognitoWindowCountView::Accept() {
+  BrowserList::CloseAllBrowsersWithIncognitoProfile(
+      browser_->profile(), base::DoNothing(), base::DoNothing(),
+      false /* skip_beforeunload */);
+  return true;
+}
+
+void IncognitoWindowCountView::Init() {
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+  AddChildView(new views::Label(l10n_util::GetPluralStringFUTF16(
+      IDS_INCOGNITO_WINDOW_COUNTER_MESSAGE, incognito_window_count_)));
+}
diff --git a/chrome/browser/ui/views/profiles/incognito_window_count_view.h b/chrome/browser/ui/views/profiles/incognito_window_count_view.h
new file mode 100644
index 0000000..be550da
--- /dev/null
+++ b/chrome/browser/ui/views/profiles/incognito_window_count_view.h
@@ -0,0 +1,56 @@
+// 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 CHROME_BROWSER_UI_VIEWS_PROFILES_INCOGNITO_WINDOW_COUNT_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_PROFILES_INCOGNITO_WINDOW_COUNT_VIEW_H_
+
+#include "base/macros.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+
+class Browser;
+
+// The implementation for a bubble that allows the user to close all open
+// incognito windows.
+// The IncognitoWindowCountView is self-owned and deletes itself when it is
+// closed or the parent browser is being destroyed.
+class IncognitoWindowCountView : public views::BubbleDialogDelegateView,
+                                 public BrowserListObserver {
+ public:
+  static void ShowBubble(views::Button* anchor_button,
+                         Browser* browser,
+                         int incognito_window_count);
+
+  // BubbleDialogDelegateView:
+  int GetDialogButtons() const override;
+  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
+  bool Accept() override;
+  bool Close() override;
+  base::string16 GetWindowTitle() const override;
+  bool ShouldShowCloseButton() const override;
+  bool ShouldShowWindowIcon() const override;
+  gfx::ImageSkia GetWindowIcon() override;
+  void Init() override;
+
+  // BrowserListObserver:
+  void OnBrowserRemoved(Browser* browser) override;
+
+ private:
+  IncognitoWindowCountView(views::Button* anchor_button,
+                           Browser* browser,
+                           int incognito_window_count);
+
+  ~IncognitoWindowCountView() override;
+
+  int incognito_window_count_;
+  Browser* const browser_;
+
+  ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_;
+  base::WeakPtrFactory<IncognitoWindowCountView> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(IncognitoWindowCountView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_PROFILES_INCOGNITO_WINDOW_COUNT_VIEW_H_
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index 59c6fceb..400a0ca 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
+#include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_test_util.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
@@ -365,9 +366,12 @@
   // Create an empty file to provide the file to open.
   const base::FilePath test_file =
       downloads_dir_.AppendASCII("file_manager_test.html");
-  FILE* fp = base::OpenFile(test_file, "w");
-  ASSERT_TRUE(fp != NULL);
-  ASSERT_TRUE(base::CloseFile(fp));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    FILE* fp = base::OpenFile(test_file, "w");
+    ASSERT_TRUE(fp != NULL);
+    ASSERT_TRUE(base::CloseFile(fp));
+  }
 
   // Open the file dialog, providing a path to the file to open so the dialog
   // will automatically select it.  Ensure the "Open" button is enabled by
diff --git a/chrome/browser/ui/webui/welcome/nux/bookmark_handler.cc b/chrome/browser/ui/webui/welcome/nux/bookmark_handler.cc
index 53d19ff2..e09ec04f 100644
--- a/chrome/browser/ui/webui/welcome/nux/bookmark_handler.cc
+++ b/chrome/browser/ui/webui/welcome/nux/bookmark_handler.cc
@@ -21,6 +21,11 @@
       "toggleBookmarkBar",
       base::BindRepeating(&BookmarkHandler::HandleToggleBookmarkBar,
                           base::Unretained(this)));
+
+  web_ui()->RegisterMessageCallback(
+      "isBookmarkBarShown",
+      base::BindRepeating(&BookmarkHandler::HandleIsBookmarkBarShown,
+                          base::Unretained(this)));
 }
 
 void BookmarkHandler::HandleToggleBookmarkBar(const base::ListValue* args) {
@@ -29,13 +34,16 @@
   prefs_->SetBoolean(bookmarks::prefs::kShowBookmarkBar, show);
 }
 
-void BookmarkHandler::AddSources(content::WebUIDataSource* html_source,
-                                 PrefService* prefs) {
-  // Add constants to loadtime data
-  html_source->AddBoolean(
-      "bookmark_bar_shown",
-      prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
-  html_source->SetJsonPath("strings.js");
+void BookmarkHandler::HandleIsBookmarkBarShown(const base::ListValue* args) {
+  AllowJavascript();
+
+  CHECK_EQ(1U, args->GetSize());
+  const base::Value* callback_id;
+  CHECK(args->Get(0, &callback_id));
+
+  ResolveJavascriptCallback(
+      *callback_id,
+      base::Value(prefs_->GetBoolean(bookmarks::prefs::kShowBookmarkBar)));
 }
 
 }  // namespace nux
diff --git a/chrome/browser/ui/webui/welcome/nux/bookmark_handler.h b/chrome/browser/ui/webui/welcome/nux/bookmark_handler.h
index e803cd5..b9240c9 100644
--- a/chrome/browser/ui/webui/welcome/nux/bookmark_handler.h
+++ b/chrome/browser/ui/webui/welcome/nux/bookmark_handler.h
@@ -11,10 +11,6 @@
 
 class PrefService;
 
-namespace content {
-class WebUIDataSource;
-}  // namespace content
-
 namespace nux {
 
 class BookmarkHandler : public content::WebUIMessageHandler {
@@ -27,10 +23,7 @@
 
   // Callbacks for JS APIs.
   void HandleToggleBookmarkBar(const base::ListValue* args);
-
-  // Adds webui sources.
-  static void AddSources(content::WebUIDataSource* html_source,
-                         PrefService* prefs);
+  void HandleIsBookmarkBarShown(const base::ListValue* args);
 
  private:
   // Weak reference.
diff --git a/chrome/browser/ui/webui/welcome/nux/email_handler.cc b/chrome/browser/ui/webui/welcome/nux/email_handler.cc
index 60e6e53..06103b4 100644
--- a/chrome/browser/ui/webui/welcome/nux/email_handler.cc
+++ b/chrome/browser/ui/webui/welcome/nux/email_handler.cc
@@ -119,6 +119,11 @@
                                IDR_NUX_EMAIL_OUTLOOK_2X);
   html_source->AddResourcePath("email/yahoo_1x.png", IDR_NUX_EMAIL_YAHOO_1X);
   html_source->AddResourcePath("email/yahoo_2x.png", IDR_NUX_EMAIL_YAHOO_2X);
+
+  // Add constants to loadtime data
+  html_source->AddInteger("email_providers_count",
+                          static_cast<int>(EmailProviders::kCount));
+  html_source->SetJsonPath("strings.js");
 }
 
 }  // namespace nux
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.cc b/chrome/browser/ui/webui/welcome/nux_helper.cc
index 6e42b69..27d35d5 100644
--- a/chrome/browser/ui/webui/welcome/nux_helper.cc
+++ b/chrome/browser/ui/webui/welcome/nux_helper.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/webui/welcome/nux_helper.h"
-#include "base/feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/webui/welcome/nux/constants.h"
 #include "chrome/common/pref_names.h"
@@ -12,7 +11,7 @@
 namespace nux {
 // This feature flag is used to force the feature to be turned on for non-win
 // and non-branded builds, like with tests or development on other platforms.
-extern const base::Feature kNuxOnboardingForceEnabled{
+const base::Feature kNuxOnboardingForceEnabled = {
     "NuxOnboardingForceEnabled", base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool IsNuxOnboardingEnabled(Profile* profile) {
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.h b/chrome/browser/ui/webui/welcome/nux_helper.h
index 0e4019c..860ceda4 100644
--- a/chrome/browser/ui/webui/welcome/nux_helper.h
+++ b/chrome/browser/ui/webui/welcome/nux_helper.h
@@ -5,12 +5,15 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_WELCOME_NUX_HELPER_H_
 #define CHROME_BROWSER_UI_WEBUI_WELCOME_NUX_HELPER_H_
 
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "chrome/browser/profiles/profile.h"
 
 class Profile;
 
 namespace nux {
+extern const base::Feature kNuxOnboardingForceEnabled;
+
 bool IsNuxOnboardingEnabled(Profile* profile);
 }  // namespace nux
 
diff --git a/chrome/browser/ui/webui/welcome/welcome_ui.cc b/chrome/browser/ui/webui/welcome/welcome_ui.cc
index eb110871b..d1d9b05 100644
--- a/chrome/browser/ui/webui/welcome/welcome_ui.cc
+++ b/chrome/browser/ui/webui/welcome/welcome_ui.cc
@@ -32,6 +32,10 @@
 #include "net/base/url_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 namespace {
 const bool kIsBranded =
 #if defined(GOOGLE_CHROME_BUILD)
@@ -182,10 +186,14 @@
     html_source->AddResourcePath("images/set_as_default_illustration_2x.png",
                                  IDR_NUX_SET_AS_DEFAULT_ILLUSTRATION_2X);
 
+#if defined(OS_WIN)
+    html_source->AddBoolean(
+        "is_win10", base::win::GetVersion() >= base::win::VERSION_WIN10);
+#endif
+
     // Add the shared bookmark handler for onboarding modules.
     web_ui->AddMessageHandler(
         std::make_unique<nux::BookmarkHandler>(profile->GetPrefs()));
-    nux::BookmarkHandler::AddSources(html_source, profile->GetPrefs());
 
     // Add email provider bookmarking onboarding module.
     web_ui->AddMessageHandler(std::make_unique<nux::EmailHandler>(
diff --git a/chrome/browser/web_applications/bookmark_apps/system_web_app_manager.cc b/chrome/browser/web_applications/bookmark_apps/system_web_app_manager.cc
index 83686b7..e28a200 100644
--- a/chrome/browser/web_applications/bookmark_apps/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/bookmark_apps/system_web_app_manager.cc
@@ -30,12 +30,12 @@
 PendingAppManager::AppInfo CreateAppInfoForSystemApp(const GURL& url) {
   DCHECK_EQ(content::kChromeUIScheme, url.scheme());
   return {
-      url,
-      LaunchContainer::kWindow,
-      InstallSource::kSystemInstalled,
+      url, LaunchContainer::kWindow, InstallSource::kSystemInstalled,
       false /* create_shortcuts */,
       PendingAppManager::AppInfo::kDefaultOverridePreviousUserUninstall,
       true /* bypass_service_worker_check */,
+      // TODO(calamity): Design a less heavy-handed update condition.
+      true /* always_update */,
   };
 }
 
diff --git a/chrome/browser/web_applications/components/pending_app_manager.cc b/chrome/browser/web_applications/components/pending_app_manager.cc
index b4ef37a..3d7dfae1 100644
--- a/chrome/browser/web_applications/components/pending_app_manager.cc
+++ b/chrome/browser/web_applications/components/pending_app_manager.cc
@@ -17,6 +17,7 @@
 const bool PendingAppManager::AppInfo::kDefaultOverridePreviousUserUninstall =
     false;
 const bool PendingAppManager::AppInfo::kDefaultBypassServiceWorkerCheck = false;
+const bool PendingAppManager::AppInfo::kDefaultAlwaysUpdate = false;
 const bool PendingAppManager::AppInfo::kDefaultRequireManifest = false;
 
 PendingAppManager::AppInfo::AppInfo(GURL url,
@@ -25,6 +26,7 @@
                                     bool create_shortcuts,
                                     bool override_previous_user_uninstall,
                                     bool bypass_service_worker_check,
+                                    bool always_update,
                                     bool require_manifest)
     : url(std::move(url)),
       launch_container(launch_container),
@@ -32,6 +34,7 @@
       create_shortcuts(create_shortcuts),
       override_previous_user_uninstall(override_previous_user_uninstall),
       bypass_service_worker_check(bypass_service_worker_check),
+      always_update(always_update),
       require_manifest(require_manifest) {}
 
 PendingAppManager::AppInfo::AppInfo(PendingAppManager::AppInfo&& other) =
diff --git a/chrome/browser/web_applications/components/pending_app_manager.h b/chrome/browser/web_applications/components/pending_app_manager.h
index 885e221..398331e 100644
--- a/chrome/browser/web_applications/components/pending_app_manager.h
+++ b/chrome/browser/web_applications/components/pending_app_manager.h
@@ -40,6 +40,7 @@
     static const bool kDefaultCreateShortcuts;
     static const bool kDefaultOverridePreviousUserUninstall;
     static const bool kDefaultBypassServiceWorkerCheck;
+    static const bool kDefaultAlwaysUpdate;
     static const bool kDefaultRequireManifest;
 
     AppInfo(GURL url,
@@ -49,6 +50,7 @@
             bool override_previous_user_uninstall =
                 kDefaultOverridePreviousUserUninstall,
             bool bypass_service_worker_check = kDefaultBypassServiceWorkerCheck,
+            bool always_update = kDefaultAlwaysUpdate,
             bool require_manifest = kDefaultRequireManifest);
     AppInfo(AppInfo&& other);
     ~AppInfo();
@@ -61,6 +63,9 @@
     const LaunchContainer launch_container;
     const InstallSource install_source;
     const bool create_shortcuts;
+
+    // Whether the app should be reinstalled even if the user has previously
+    // uninstalled it.
     const bool override_previous_user_uninstall;
 
     // This must only be used by pre-installed default or system apps that are
@@ -68,6 +73,9 @@
     // programmatically.
     const bool bypass_service_worker_check;
 
+    // Whether the app should be reinstalled even if it is already installed.
+    const bool always_update;
+
     // This should be used for installing all default apps so that good metadata
     // is ensured.
     const bool require_manifest;
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 aecfb27..f5fe5f5 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
@@ -141,9 +141,6 @@
   timer_ = std::move(timer);
 }
 
-// Returns (as the base::Optional part) whether or not there is already a known
-// extension for the given ID. The bool inside the base::Optional is, when
-// known, whether the extension is installed (true) or uninstalled (false).
 base::Optional<bool> PendingBookmarkAppManager::IsExtensionPresentAndInstalled(
     const std::string& extension_id) {
   if (ExtensionRegistry::Get(profile_)->GetExtensionById(
@@ -169,6 +166,12 @@
 
     const web_app::PendingAppManager::AppInfo& app_info =
         front->task->app_info();
+
+    if (app_info.always_update) {
+      StartInstallationTask(std::move(front));
+      return;
+    }
+
     base::Optional<std::string> extension_id =
         extension_ids_map_.LookupExtensionId(app_info.url);
 
@@ -189,27 +192,31 @@
         }
       }
     }
-
-    current_task_and_callback_ = std::move(front);
-
-    CreateWebContentsIfNecessary();
-    Observe(web_contents_.get());
-
-    content::NavigationController::LoadURLParams load_params(
-        current_task_and_callback_->task->app_info().url);
-    load_params.transition_type = ui::PAGE_TRANSITION_GENERATED;
-    web_contents_->GetController().LoadURLWithParams(load_params);
-    timer_->Start(
-        FROM_HERE,
-        base::TimeDelta::FromSeconds(kSecondsToWaitForWebContentsLoad),
-        base::BindOnce(&PendingBookmarkAppManager::OnWebContentsLoadTimedOut,
-                       weak_ptr_factory_.GetWeakPtr()));
+    StartInstallationTask(std::move(front));
     return;
   }
 
   web_contents_.reset();
 }
 
+void PendingBookmarkAppManager::StartInstallationTask(
+    std::unique_ptr<TaskAndCallback> task) {
+  DCHECK(!current_task_and_callback_);
+  current_task_and_callback_ = std::move(task);
+
+  CreateWebContentsIfNecessary();
+  Observe(web_contents_.get());
+
+  content::NavigationController::LoadURLParams load_params(
+      current_task_and_callback_->task->app_info().url);
+  load_params.transition_type = ui::PAGE_TRANSITION_GENERATED;
+  web_contents_->GetController().LoadURLWithParams(load_params);
+  timer_->Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(kSecondsToWaitForWebContentsLoad),
+      base::BindOnce(&PendingBookmarkAppManager::OnWebContentsLoadTimedOut,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
 void PendingBookmarkAppManager::CreateWebContentsIfNecessary() {
   if (web_contents_)
     return;
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 a8b6ff1..7af5588 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
@@ -62,11 +62,17 @@
  private:
   struct TaskAndCallback;
 
+  // Returns (as the base::Optional part) whether or not there is already a
+  // known extension for the given ID. The bool inside the base::Optional is,
+  // when known, whether the extension is installed (true) or uninstalled
+  // (false).
   base::Optional<bool> IsExtensionPresentAndInstalled(
       const std::string& extension_id);
 
   void MaybeStartNextInstallation();
 
+  void StartInstallationTask(std::unique_ptr<TaskAndCallback> task);
+
   void CreateWebContentsIfNecessary();
 
   void OnInstalled(BookmarkAppInstallationTask::Result result);
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
index 3bb0a191..687bf23 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
@@ -30,24 +30,26 @@
  protected:
   void InstallApp(const GURL& url,
                   bool bypass_service_worker_check = false,
+                  bool always_update = false,
                   bool require_manifest = false) {
     base::RunLoop run_loop;
     web_app::WebAppProvider::Get(browser()->profile())
         ->pending_app_manager()
-        .Install(web_app::PendingAppManager::AppInfo(
-                     url, web_app::LaunchContainer::kWindow,
-                     web_app::InstallSource::kInternal,
-                     false /* create_shortcuts */,  // Avoid creating real
-                                                    // shortcuts in tests.
-                     web_app::PendingAppManager::AppInfo::
-                         kDefaultOverridePreviousUserUninstall,
-                     bypass_service_worker_check, require_manifest),
-                 base::BindLambdaForTesting(
-                     [this, &run_loop](const GURL& provided_url,
-                                       web_app::InstallResultCode code) {
-                       result_code_ = code;
-                       run_loop.QuitClosure().Run();
-                     }));
+        .Install(
+            web_app::PendingAppManager::AppInfo(
+                url, web_app::LaunchContainer::kWindow,
+                web_app::InstallSource::kInternal,
+                false /* create_shortcuts */,  // Avoid creating real
+                                               // shortcuts in tests.
+                web_app::PendingAppManager::AppInfo::
+                    kDefaultOverridePreviousUserUninstall,
+                bypass_service_worker_check, always_update, require_manifest),
+            base::BindLambdaForTesting(
+                [this, &run_loop](const GURL& provided_url,
+                                  web_app::InstallResultCode code) {
+                  result_code_ = code;
+                  run_loop.QuitClosure().Run();
+                }));
     run_loop.Run();
     ASSERT_TRUE(result_code_.has_value());
   }
@@ -122,6 +124,33 @@
   EXPECT_FALSE(app);
 }
 
+IN_PROC_BROWSER_TEST_F(PendingBookmarkAppManagerBrowserTest, AlwaysUpdate) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kDesktopPWAWindowing);
+  ASSERT_TRUE(embedded_test_server()->Start());
+  {
+    GURL url(embedded_test_server()->GetURL(
+        "/banners/"
+        "manifest_test_page.html?manifest=manifest_short_name_only.json"));
+    InstallApp(url, false /* bypass_service_worker_check */,
+               true /* always_update */);
+    const extensions::Extension* app =
+        extensions::util::GetInstalledPwaForUrl(browser()->profile(), url);
+    EXPECT_TRUE(app);
+    EXPECT_EQ("Manifest", app->name());
+  }
+  {
+    GURL url(
+        embedded_test_server()->GetURL("/banners/manifest_test_page.html"));
+    InstallApp(url, false /* bypass_service_worker_check */,
+               true /* always_update */);
+    const extensions::Extension* app =
+        extensions::util::GetInstalledPwaForUrl(browser()->profile(), url);
+    EXPECT_TRUE(app);
+    EXPECT_EQ("Manifest test app", app->name());
+  }
+}
+
 // Test that adding a manifest that points to a chrome:// URL does not actually
 // install a bookmark app that points to a chrome:// URL.
 IN_PROC_BROWSER_TEST_F(PendingBookmarkAppManagerBrowserTest,
@@ -154,7 +183,7 @@
   GURL url(
       embedded_test_server()->GetURL("/banners/no_manifest_test_page.html"));
   InstallApp(url, false /* bypass_service_worker_check */,
-             true /* require_manifest */);
+             false /* always_update */, true /* require_manifest */);
   EXPECT_EQ(web_app::InstallResultCode::kFailedUnknownReason,
             result_code_.value());
   base::Optional<std::string> id =
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 a00d9e2..4645f6a 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
@@ -569,6 +569,46 @@
   EXPECT_EQ(GURL(kFooWebAppUrl), install_callback_url());
 }
 
+TEST_F(PendingBookmarkAppManagerTest, Install_AlwaysUpdate) {
+  auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
+
+  auto get_always_update_info = []() {
+    return web_app::PendingAppManager::AppInfo(
+        GURL(kFooWebAppUrl), web_app::LaunchContainer::kWindow,
+        web_app::InstallSource::kExternalPolicy,
+        web_app::PendingAppManager::AppInfo::kDefaultCreateShortcuts,
+        web_app::PendingAppManager::AppInfo::
+            kDefaultOverridePreviousUserUninstall,
+        web_app::PendingAppManager::AppInfo::kDefaultBypassServiceWorkerCheck,
+        true /* always_update */);
+  };
+  pending_app_manager->Install(
+      get_always_update_info(),
+      base::BindOnce(&PendingBookmarkAppManagerTest::InstallCallback,
+                     base::Unretained(this)));
+
+  base::RunLoop().RunUntilIdle();
+  SuccessfullyLoad(GURL(kFooWebAppUrl));
+
+  EXPECT_EQ(1u, installation_task_run_count());
+  EXPECT_TRUE(app_installed());
+  EXPECT_EQ(GURL(kFooWebAppUrl), install_callback_url());
+  ResetResults();
+
+  pending_app_manager->Install(
+      get_always_update_info(),
+      base::BindOnce(&PendingBookmarkAppManagerTest::InstallCallback,
+                     base::Unretained(this)));
+
+  base::RunLoop().RunUntilIdle();
+  SuccessfullyLoad(GURL(kFooWebAppUrl));
+
+  // The app is reinstalled even though it is already installed.
+  EXPECT_EQ(1u, installation_task_run_count());
+  EXPECT_TRUE(app_installed());
+  EXPECT_EQ(GURL(kFooWebAppUrl), install_callback_url());
+}
+
 TEST_F(PendingBookmarkAppManagerTest, Install_FailsLoadIncorrectURL) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   pending_app_manager->Install(
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 519291c9..8a6944e 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -136,12 +136,6 @@
                                        base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
-#if defined(OS_MACOSX)
-// Enables the suggested text touch bar for autocomplete in textfields.
-const base::Feature kTextSuggestionsTouchBar{"TextSuggestionsTouchBar",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
-#endif
-
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
 // Enables the blocking of third-party modules.
 // Note: Due to a limitation in the implementation of this feature, it is
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 649d5ca..432449f 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -374,11 +374,6 @@
 COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kTabMetricsLogging;
 #endif
 
-#if defined(OS_MACOSX)
-COMPONENT_EXPORT(CHROME_FEATURES)
-extern const base::Feature kTextSuggestionsTouchBar;
-#endif
-
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::Feature kThirdPartyModulesBlocking;
diff --git a/chrome/common/extensions/api/networking_cast_private.idl b/chrome/common/extensions/api/networking_cast_private.idl
index cc4335cd..c4b45a3 100644
--- a/chrome/common/extensions/api/networking_cast_private.idl
+++ b/chrome/common/extensions/api/networking_cast_private.idl
@@ -67,17 +67,6 @@
     static void verifyDestination(VerificationProperties properties,
                                   BooleanCallback callback);
 
-    // Verifies that the device is a trusted device and retrieves encrypted
-    // network credentials.
-    // |properties|: Properties of the destination to use in verifying that it
-    //     is a trusted device.
-    // |networkGuid|: The GUID of the Cellular network to activate.
-    // |callback|: A callback function that receives base64-encoded encrypted
-    //     credential data to send to a trusted device.
-    static void verifyAndEncryptCredentials(VerificationProperties properties,
-                                            DOMString networkGuid,
-                                            StringCallback callback);
-
     // Verifies that the device is a trusted device and encrypts supplied
     // data with device public key.
     // |properties|: Properties of the destination to use in verifying that it
diff --git a/chrome/common/page_load_metrics/page_load_metrics.mojom b/chrome/common/page_load_metrics/page_load_metrics.mojom
index 1fd19480..0001b39 100644
--- a/chrome/common/page_load_metrics/page_load_metrics.mojom
+++ b/chrome/common/page_load_metrics/page_load_metrics.mojom
@@ -218,5 +218,6 @@
   UpdateTiming(PageLoadTiming page_load_timing,
                PageLoadMetadata page_load_metadata,
                PageLoadFeatures new_features,
-               array<ResourceDataUpdate> resources);
+               array<ResourceDataUpdate> resources,
+               PageRenderData render_data);
 };
diff --git a/chrome/common/search.mojom b/chrome/common/search.mojom
index facff8d1..f9e2c91a 100644
--- a/chrome/common/search.mojom
+++ b/chrome/common/search.mojom
@@ -66,11 +66,6 @@
   // instead.
   ResetCustomLinks(int32 page_seq_no);
 
-  // Tells InstantExtended to return true if the URL resolves and the edit
-  // custom link dialog has not timed out.
-  DoesUrlResolve(int32 page_seq_no, url.mojom.Url url)
-      => (bool resolves, bool timeout);
-
   // Logs events from InstantExtended New Tab Pages.
   LogEvent(int32 page_seq_no,
            NTPLoggingEventType event,
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
index 2cf3adc..aad56ce9 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
@@ -44,10 +44,9 @@
                   std::vector<mojom::ResourceDataUpdatePtr> resources,
                   const mojom::PageRenderData& render_data) override {
     DCHECK(page_load_metrics_);
-    // TODO: Include render_data in IPC.
     page_load_metrics_->UpdateTiming(timing->Clone(), metadata->Clone(),
                                      std::move(new_features),
-                                     std::move(resources));
+                                     std::move(resources), render_data.Clone());
   }
 
  private:
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index 219691a8..a93959e 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -204,11 +204,10 @@
   return true;
 }
 
-std::pair<GURL, bool> FixupAndValidateUrl(const std::string& url) {
+std::string FixupAndValidateUrl(const std::string& url) {
   GURL gurl = url_formatter::FixupURL(url, /*desired_tld=*/std::string());
   if (!gurl.is_valid())
-    return std::make_pair(GURL(), false);
-  bool default_https = false;
+    return std::string();
 
   // Unless "http" was specified, replaces FixupURL's default "http" with
   // "https".
@@ -217,10 +216,9 @@
     GURL::Replacements replacements;
     replacements.SetSchemeStr(url::kHttpsScheme);
     gurl = gurl.ReplaceComponents(replacements);
-    default_https = true;
   }
 
-  return std::make_pair(gurl, default_https);
+  return gurl.spec();
 }
 
 }  // namespace internal
@@ -391,19 +389,8 @@
   embedded_search_service_->ResetCustomLinks(page_seq_no_);
 }
 
-std::string SearchBox::FixupAndValidateUrl(const std::string& url) {
-  std::pair<GURL, bool> fixed_url = internal::FixupAndValidateUrl(url);
-
-  // If URL is valid and we defaulted to https, notify whether the URL resolves.
-  if (fixed_url.first.is_valid() && fixed_url.second) {
-    embedded_search_service_->DoesUrlResolve(
-        page_seq_no_, fixed_url.first,
-        base::BindOnce(&SearchBox::DoesUrlResolveResult,
-                       weak_ptr_factory_.GetWeakPtr()));
-  } else {
-    DoesUrlResolveResult(/*resolves=*/true, /*timeout=*/false);
-  }
-  return fixed_url.first.spec();
+std::string SearchBox::FixupAndValidateUrl(const std::string& url) const {
+  return internal::FixupAndValidateUrl(url);
 }
 
 void SearchBox::SetCustomBackgroundURL(const GURL& background_url) {
@@ -493,14 +480,6 @@
   }
 }
 
-void SearchBox::DoesUrlResolveResult(bool resolves, bool timeout) const {
-  // Do not notify if the edit custom link dialog has already timed out.
-  if (can_run_js_in_renderframe_ && !timeout) {
-    SearchBoxExtension::DispatchDoesUrlResolveResult(
-        render_frame()->GetWebFrame(), resolves);
-  }
-}
-
 void SearchBox::MostVisitedChanged(
     const std::vector<InstantMostVisitedItem>& items,
     bool is_custom_links) {
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index 50a34667..326e945 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -140,9 +140,9 @@
   void ResetCustomLinks();
 
   // Attempts to fix obviously invalid URLs. Uses the "https" scheme unless
-  // otherwise specified and, if so, checks if the default scheme can resolve.
-  // Returns the fixed URL if valid, otherwise returns an empty string.
-  std::string FixupAndValidateUrl(const std::string& url);
+  // otherwise specified. Returns the fixed URL if valid, otherwise returns an
+  // empty string.
+  std::string FixupAndValidateUrl(const std::string& url) const;
 
   // Updates the NTP custom background preferences, sometimes this includes
   // image attributions.
@@ -181,7 +181,6 @@
   void AddCustomLinkResult(bool success);
   void UpdateCustomLinkResult(bool success);
   void DeleteCustomLinkResult(bool success);
-  void DoesUrlResolveResult(bool resolves, bool timeout) const;
 
   // Returns the URL of the Most Visited item specified by the |item_id|.
   GURL GetURLForMostVisitedItem(InstantRestrictedID item_id) const;
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 1645eb56..2a0116b 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -444,17 +444,6 @@
     "  true;"
     "}";
 
-static const char kDispatchDoesUrlResolveResultScript[] =
-    "if (window.chrome &&"
-    "    window.chrome.embeddedSearch &&"
-    "    window.chrome.embeddedSearch.newTabPage &&"
-    "    window.chrome.embeddedSearch.newTabPage.doesurlresolve &&"
-    "    typeof window.chrome.embeddedSearch.newTabPage.doesurlresolve =="
-    "        'function') {"
-    "  window.chrome.embeddedSearch.newTabPage.doesurlresolve(%s);"
-    "  true;"
-    "}";
-
 static const char kDispatchInputCancelScript[] =
     "if (window.chrome &&"
     "    window.chrome.embeddedSearch &&"
@@ -1111,15 +1100,6 @@
 }
 
 // static
-void SearchBoxExtension::DispatchDoesUrlResolveResult(
-    blink::WebLocalFrame* frame,
-    bool resolves) {
-  blink::WebString script(blink::WebString::FromUTF8(base::StringPrintf(
-      kDispatchDoesUrlResolveResultScript, resolves ? "true" : "false")));
-  Dispatch(frame, script);
-}
-
-// static
 void SearchBoxExtension::DispatchInputCancel(blink::WebLocalFrame* frame) {
   Dispatch(frame, kDispatchInputCancelScript);
 }
diff --git a/chrome/renderer/searchbox/searchbox_extension.h b/chrome/renderer/searchbox/searchbox_extension.h
index 9929210..f2c24a0 100644
--- a/chrome/renderer/searchbox/searchbox_extension.h
+++ b/chrome/renderer/searchbox/searchbox_extension.h
@@ -31,8 +31,6 @@
                                              bool success);
   static void DispatchDeleteCustomLinkResult(blink::WebLocalFrame* frame,
                                              bool success);
-  static void DispatchDoesUrlResolveResult(blink::WebLocalFrame* frame,
-                                           bool resolves);
   static void DispatchInputCancel(blink::WebLocalFrame* frame);
   static void DispatchInputStart(blink::WebLocalFrame* frame);
   static void DispatchKeyCaptureChange(blink::WebLocalFrame* frame);
diff --git a/chrome/renderer/searchbox/searchbox_unittest.cc b/chrome/renderer/searchbox/searchbox_unittest.cc
index 2f5a62f..574bd29b 100644
--- a/chrome/renderer/searchbox/searchbox_unittest.cc
+++ b/chrome/renderer/searchbox/searchbox_unittest.cc
@@ -78,7 +78,7 @@
                                 GURL* url);
 
 // Defined in searchbox.cc
-std::pair<GURL, bool> FixupAndValidateUrl(const std::string& url);
+std::string FixupAndValidateUrl(const std::string& url);
 
 TEST(SearchBoxUtilTest, ParseViewIdAndRestrictedIdSuccess) {
   int view_id = -1;
@@ -287,8 +287,7 @@
   };
 
   for (const TestCase& test_case : test_cases) {
-    std::pair<GURL, bool> fixed_url = FixupAndValidateUrl(test_case.url);
-    const std::string& url = fixed_url.first.spec();
+    const std::string& url = FixupAndValidateUrl(test_case.url);
     EXPECT_EQ(!url.empty(), test_case.is_valid)
         << " for test_case '" << test_case.url << "'";
   }
@@ -297,27 +296,24 @@
 TEST(SearchBoxUtilTest, FixupAndValidateUrlDefaultsToHttps) {
   struct TestCase {
     const char* url;
-    bool default_https;
     const char* expected_scheme;
   } test_cases[] = {
       // No scheme.
-      {"foo.com", true, url::kHttpsScheme},
+      {"foo.com", url::kHttpsScheme},
       // With "http".
-      {"http://foo.com", false, url::kHttpScheme},
+      {"http://foo.com", url::kHttpScheme},
       // With "http" and whitespace.
-      {"\thttp://foo", false, url::kHttpScheme},
-      {"    http://foo", false, url::kHttpScheme},
+      {"\thttp://foo", url::kHttpScheme},
+      {"    http://foo", url::kHttpScheme},
       // With "https".
-      {"https://foo.com", false, url::kHttpsScheme},
+      {"https://foo.com", url::kHttpsScheme},
       // Non "http"/"https".
-      {"blob://foo", false, url::kBlobScheme},
+      {"blob://foo", url::kBlobScheme},
   };
 
   for (const TestCase& test_case : test_cases) {
-    std::pair<GURL, bool> fixed_url = FixupAndValidateUrl(test_case.url);
-    EXPECT_TRUE(fixed_url.first.SchemeIs(test_case.expected_scheme))
-        << " for test case '" << test_case.url << "'";
-    EXPECT_EQ(fixed_url.second, test_case.default_https)
+    const GURL url(FixupAndValidateUrl(test_case.url));
+    EXPECT_TRUE(url.SchemeIs(test_case.expected_scheme))
         << " for test case '" << test_case.url << "'";
   }
 }
diff --git a/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc b/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
index 91b5834..cea017a0 100644
--- a/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
+++ b/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/test/test_utils.h"
@@ -76,10 +77,13 @@
   const base::FilePath kFile2(FILE_PATH_LITERAL("random"));
   const int kRandomDataSize = 100000;
   const std::string kRandomData = base::RandBytesAsString(kRandomDataSize);
-  base::CreateDirectory(zip_base_dir().Append(kDir1));
-  base::WriteFile(zip_base_dir().Append(kFile1), "123", 3);
-  base::WriteFile(zip_base_dir().Append(kFile2), kRandomData.c_str(),
-                  kRandomData.size());
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    base::CreateDirectory(zip_base_dir().Append(kDir1));
+    base::WriteFile(zip_base_dir().Append(kFile1), "123", 3);
+    base::WriteFile(zip_base_dir().Append(kFile2), kRandomData.c_str(),
+                    kRandomData.size());
+  }
 
   bool success = false;
   base::RunLoop run_loop;
@@ -98,6 +102,8 @@
   content::RunThisRunLoop(&run_loop);
   EXPECT_TRUE(success);
 
+  base::ScopedAllowBlockingForTesting allow_io;
+
   // Check the archive content.
   zip::ZipReader reader;
   ASSERT_TRUE(reader.Open(zip_archive_path()));
@@ -147,27 +153,31 @@
   // root_dir/10/7.txt -> Hello10/7
 
   base::FilePath root_dir = zip_base_dir().Append("root_dir");
-  ASSERT_TRUE(base::CreateDirectory(root_dir));
 
   // File paths to file content. Used for validation.
   std::map<base::FilePath, std::string> file_tree_content;
-  for (int i = 1; i < 90; i++) {
-    base::FilePath file(std::to_string(i) + ".txt");
-    std::string content = "Hello" + std::to_string(i);
-    ASSERT_TRUE(CreateFile(root_dir.Append(file), content));
-    file_tree_content[file] = content;
-  }
-  for (int i = 1; i <= 10; i++) {
-    base::FilePath dir(std::to_string(i));
-    ASSERT_TRUE(base::CreateDirectory(root_dir.Append(dir)));
-    file_tree_content[dir] = std::string();
-    for (int j = 1; j <= 7; j++) {
-      base::FilePath file = dir.Append(std::to_string(j) + ".txt");
-      std::string content =
-          "Hello" + std::to_string(i) + "/" + std::to_string(j);
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    ASSERT_TRUE(base::CreateDirectory(root_dir));
+
+    for (int i = 1; i < 90; i++) {
+      base::FilePath file(std::to_string(i) + ".txt");
+      std::string content = "Hello" + std::to_string(i);
       ASSERT_TRUE(CreateFile(root_dir.Append(file), content));
       file_tree_content[file] = content;
     }
+    for (int i = 1; i <= 10; i++) {
+      base::FilePath dir(std::to_string(i));
+      ASSERT_TRUE(base::CreateDirectory(root_dir.Append(dir)));
+      file_tree_content[dir] = std::string();
+      for (int j = 1; j <= 7; j++) {
+        base::FilePath file = dir.Append(std::to_string(j) + ".txt");
+        std::string content =
+            "Hello" + std::to_string(i) + "/" + std::to_string(j);
+        ASSERT_TRUE(CreateFile(root_dir.Append(file), content));
+        file_tree_content[file] = content;
+      }
+    }
   }
 
   // Sanity check on the files created.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b503d67..a1484101 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1957,7 +1957,6 @@
         "../browser/ui/cocoa/share_menu_controller_browsertest.mm",
         "../browser/ui/cocoa/task_manager_mac_browsertest.mm",
         "../browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm",
-        "../browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm",
         "../browser/ui/views/certificate_viewer_mac_browsertest.mm",
         "../browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm",
 
@@ -1988,7 +1987,6 @@
     if (is_win) {
       sources += [
         "../browser/browser_switcher/browser_switcher_service_browsertest.cc",
-        "../browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc",
         "../browser/printing/pdf_to_emf_converter_browsertest.cc",
         "../browser/ui/views/accessibility/invert_bubble_view_browsertest.cc",
         "../browser/ui/views/settings_reset_prompt_dialog_browsertest.cc",
@@ -3385,6 +3383,7 @@
       "../browser/feature_engagement/session_duration_updater_unittest.cc",
       "../browser/ui/in_product_help/active_tab_tracker_unittest.cc",
       "../browser/ui/in_product_help/reopen_tab_in_product_help_trigger_unittest.cc",
+      "../browser/ui/in_product_help/reopen_tab_in_product_help_unittest.cc",
     ]
     deps += [ "//components/feature_engagement/test:test_support" ]
   }
@@ -4143,7 +4142,6 @@
       "../browser/ui/cocoa/test/run_loop_testing_unittest.mm",
       "../browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm",
       "../browser/ui/cocoa/touchbar/credit_card_autofill_touch_bar_controller_unittest.mm",
-      "../browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm",
       "../browser/ui/cocoa/window_size_autosaver_unittest.mm",
     ]
 
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 3aa922f..8db662d 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -570,10 +570,6 @@
 #if defined(OS_MACOSX)
   autorelease_pool_->Recycle();
 #endif
-
-#if defined(OS_CHROMEOS)  // http://crbug.com/715735
-  disable_io_checks();
-#endif
 }
 
 void InProcessBrowserTest::PostRunTestOnMainThread() {
diff --git a/chrome/test/data/extensions/api_test/networking_cast_private/test.js b/chrome/test/data/extensions/api_test/networking_cast_private/test.js
index f70b961..3d31e8d 100644
--- a/chrome/test/data/extensions/api_test/networking_cast_private/test.js
+++ b/chrome/test/data/extensions/api_test/networking_cast_private/test.js
@@ -30,15 +30,6 @@
             assertTrue(isValid);
           }));
     },
-    function verifyAndEncryptCredentials() {
-      var networkGuid = 'wifi_guid';
-      chrome.networking.castPrivate.verifyAndEncryptCredentials(
-          verificationProperties,
-          networkGuid,
-          callbackPass(function(result) {
-            assertEq('encrypted_credentials', result);
-          }));
-    },
     function verifyAndEncryptData() {
       chrome.networking.castPrivate.verifyAndEncryptData(
           verificationProperties,
diff --git a/chrome/test/data/extensions/api_test/networking_private/alias/test.js b/chrome/test/data/extensions/api_test/networking_private/alias/test.js
index 2989c1e..978f74e7 100644
--- a/chrome/test/data/extensions/api_test/networking_private/alias/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/alias/test.js
@@ -96,9 +96,6 @@
       };
       chrome.networking.onc.verifyDestination(
           stubVerificationProperties, chrome.test.callbackFail(expectedError));
-      chrome.networking.onc.verifyAndEncryptCredentials(
-          stubVerificationProperties, '',
-          chrome.test.callbackFail(expectedError));
       chrome.networking.onc.verifyAndEncryptData(
           stubVerificationProperties, '',
           chrome.test.callbackFail(expectedError));
diff --git a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
index e42cf06..ea0babe 100644
--- a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
@@ -896,15 +896,6 @@
         assertTrue(isValid);
       }));
   },
-  function verifyAndEncryptCredentials() {
-    var network_guid = 'stub_wifi2_guid';
-    chrome.networkingPrivate.verifyAndEncryptCredentials(
-      verificationProperties,
-      network_guid,
-      callbackPass(function(result) {
-        assertEq('encrypted_credentials', result);
-      }));
-  },
   function verifyAndEncryptData() {
     chrome.networkingPrivate.verifyAndEncryptData(
       verificationProperties,
diff --git a/chrome/test/data/extensions/api_test/networking_private/service_client/test.js b/chrome/test/data/extensions/api_test/networking_private/service_client/test.js
index 1ac0b8c..a0432e75 100644
--- a/chrome/test/data/extensions/api_test/networking_private/service_client/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/service_client/test.js
@@ -431,15 +431,6 @@
         assertTrue(isValid);
       }));
   },
-  function verifyAndEncryptCredentials() {
-    var network_guid = "stub_wifi2_guid";
-    chrome.networkingPrivate.verifyAndEncryptCredentials(
-      verificationProperties,
-      network_guid,
-      callbackPass(function(result) {
-        assertEq("encrypted_credentials", result);
-      }));
-  },
   function verifyAndEncryptData() {
     chrome.networkingPrivate.verifyAndEncryptData(
       verificationProperties,
diff --git a/chrome/test/data/extensions/api_test/networking_private/test.js b/chrome/test/data/extensions/api_test/networking_private/test.js
index 241cb49a..cf5b327 100644
--- a/chrome/test/data/extensions/api_test/networking_private/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/test.js
@@ -99,10 +99,6 @@
     chrome.networkingPrivate.verifyDestination(
         verificationProperties, callbackPass(callbackResult));
   },
-  function verifyAndEncryptCredentials() {
-    chrome.networkingPrivate.verifyAndEncryptCredentials(
-        verificationProperties, kGuid, callbackPass(callbackResult));
-  },
   function verifyAndEncryptData() {
     chrome.networkingPrivate.verifyAndEncryptData(
         verificationProperties, 'data', callbackPass(callbackResult));
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 2bc265df..81e95cf 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -107,6 +107,7 @@
     sources += [
       "md_user_manager/user_manager_browsertest.js",
       "signin/signin_browsertest.js",
+      "welcome/onboarding_welcome_browsertest.js",
     ]
   }
 
diff --git a/chrome/test/data/webui/settings/basic_page_browsertest.js b/chrome/test/data/webui/settings/basic_page_browsertest.js
index 550fb0ac..4dca1303 100644
--- a/chrome/test/data/webui/settings/basic_page_browsertest.js
+++ b/chrome/test/data/webui/settings/basic_page_browsertest.js
@@ -22,7 +22,7 @@
 };
 
 // http://crbug/738146
-TEST_F('SettingsBasicPageBrowserTest', 'Load', function() {
+TEST_F('SettingsBasicPageBrowserTest', 'DISABLED_Load', function() {
   // Assign |self| to |this| instead of binding since 'this' in suite()
   // and test() will be a Mocha 'Suite' or 'Test' instance.
   const self = this;
diff --git a/chrome/test/data/webui/settings/smb_shares_page_tests.js b/chrome/test/data/webui/settings/smb_shares_page_tests.js
index 53ff7e72..112c570 100644
--- a/chrome/test/data/webui/settings/smb_shares_page_tests.js
+++ b/chrome/test/data/webui/settings/smb_shares_page_tests.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/** @implements {settings.SmbBrowserProxy} */
+/** @implements {smb_shares.SmbBrowserProxy} */
 class TestSmbBrowserProxy extends TestBrowserProxy {
   constructor() {
     super([
@@ -27,12 +27,12 @@
   let page = null;
   let addDialog = null;
 
-  /** @type {?settings.TestSmbBrowserProxy} */
+  /** @type {?smb_shares.TestSmbBrowserProxy} */
   let smbBrowserProxy = null;
 
   setup(function() {
     smbBrowserProxy = new TestSmbBrowserProxy();
-    settings.SmbBrowserProxyImpl.instance_ = smbBrowserProxy;
+    smb_shares.SmbBrowserProxyImpl.instance_ = smbBrowserProxy;
 
     PolymerTest.clearBody();
 
@@ -44,7 +44,7 @@
     button.click();
     Polymer.dom.flush();
 
-    addDialog = page.$$('settings-add-smb-share-dialog');
+    addDialog = page.$$('add-smb-share-dialog');
     assertTrue(!!addDialog);
 
     Polymer.dom.flush();
diff --git a/chrome/test/data/webui/welcome/email_chooser_test.js b/chrome/test/data/webui/welcome/email_chooser_test.js
new file mode 100644
index 0000000..9cdb2782
--- /dev/null
+++ b/chrome/test/data/webui/welcome/email_chooser_test.js
@@ -0,0 +1,52 @@
+// 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.
+
+cr.define('onboarding_welcome_email_chooser', function() {
+  suite('EmailChooserTest', function() {
+    /** @type {nux.NuxEmailProxy} */
+    let testEmailBrowserProxy;
+
+    /** @type {EmailChooserElement} */
+    let testElement;
+
+    setup(function() {
+      testEmailBrowserProxy = new TestNuxEmailProxy();
+      nux.NuxEmailProxyImpl.instance_ = testEmailBrowserProxy;
+
+      testEmailBrowserProxy.setEmailList([
+        {
+          id: 0,
+          name: 'Gmail',
+          icon: 'gmail',
+          url: 'http://www.gmail.com',
+        },
+        {
+          id: 1,
+          name: 'Yahoo',
+          icon: 'yahoo',
+          url: 'http://mail.yahoo.com',
+        }
+      ]);
+
+      PolymerTest.clearBody();
+      testElement = document.createElement('email-chooser');
+      document.body.appendChild(testElement);
+      return Promise.all([
+        testEmailBrowserProxy.whenCalled('recordPageInitialized'),
+        testEmailBrowserProxy.whenCalled('getEmailList'),
+      ]);
+    });
+
+    teardown(function() {
+      testElement.remove();
+    });
+
+    test('test email chooser initialized options correctly', function() {
+      assertEquals(
+          2, testElement.shadowRoot.querySelectorAll('.option').length);
+
+      // TODO(scottchen): Add more initial layout testing.
+    });
+  });
+});
diff --git a/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js b/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js
new file mode 100644
index 0000000..a8707d4
--- /dev/null
+++ b/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js
@@ -0,0 +1,53 @@
+// 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.
+
+/** @fileoverview Runs the Polymer welcome tests on onboarding-welcome UI. */
+
+/** @const {string} Path to source root. */
+const ROOT_PATH = '../../../../../';
+
+// Polymer BrowserTest fixture.
+GEN_INCLUDE(
+    [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']);
+GEN('#include "chrome/browser/ui/webui/welcome/nux_helper.h"');
+
+/**
+ * Test fixture for Polymer onboarding welcome elements.
+ */
+const OnboardingWelcomeBrowserTest = class extends PolymerTest {
+  /** @override */
+  get browsePreload() {
+    throw 'this is abstract and should be overridden by subclasses';
+  }
+
+  get extraLibraries() {
+    return PolymerTest.getLibraries(ROOT_PATH).concat([
+      '../test_browser_proxy.js',
+    ]);
+  }
+
+  /** @override */
+  get featureList() {
+    return ['nux::kNuxOnboardingForceEnabled', ''];
+  }
+};
+
+OnboardingWelcomeEmailChooserTest = class extends OnboardingWelcomeBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://welcome/email/email_chooser.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      'email_chooser_test.js',
+      'test_nux_email_proxy.js',
+    ]);
+  }
+};
+
+TEST_F('OnboardingWelcomeEmailChooserTest', 'All', function() {
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/welcome/test_nux_email_proxy.js b/chrome/test/data/webui/welcome/test_nux_email_proxy.js
new file mode 100644
index 0000000..8f26d2f0
--- /dev/null
+++ b/chrome/test/data/webui/welcome/test_nux_email_proxy.js
@@ -0,0 +1,73 @@
+// 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.
+
+/** @implements {nux.NuxEmailProxy} */
+class TestNuxEmailProxy extends TestBrowserProxy {
+  constructor() {
+    super([
+      'cacheBookmarkIcon',
+      'getEmailList',
+      'getSavedProvider',
+      'recordPageInitialized',
+      'recordClickedOption',
+      'recordClickedDisabledButton',
+      'recordProviderSelected',
+      'recordNoThanks',
+      'recordGetStarted',
+      'recordFinalize',
+    ]);
+
+    /** @private {!Array<!nux.BookmarkListItem>} */
+    this.emailList_ = [];
+  }
+
+  /** @override */
+  recordPageInitialized() {
+    this.methodCalled('recordPageInitialized');
+  }
+
+  /** @override */
+  getEmailList() {
+    this.methodCalled('getEmailList');
+    return Promise.resolve(this.emailList_);
+  }
+
+  /** @override */
+  cacheBookmarkIcon() {
+    this.methodCalled('cacheBookmarkIcon');
+  }
+  /** @override */
+  getSavedProvider() {
+    this.methodCalled('getSavedProvider');
+  }
+  /** @override */
+  recordClickedOption() {
+    this.methodCalled('recordClickedOption');
+  }
+  /** @override */
+  recordClickedDisabledButton() {
+    this.methodCalled('recordClickedDisabledButton');
+  }
+  /** @override */
+  recordProviderSelected() {
+    this.methodCalled('recordProviderSelected');
+  }
+  /** @override */
+  recordNoThanks() {
+    this.methodCalled('recordNoThanks');
+  }
+  /** @override */
+  recordGetStarted() {
+    this.methodCalled('recordGetStarted');
+  }
+  /** @override */
+  recordFinalize() {
+    this.methodCalled('recordFinalize');
+  }
+
+  /** @param {!Array<!nux.BookmarkListItem>} emailList */
+  setEmailList(emailList) {
+    this.emailList_ = emailList;
+  }
+}
diff --git a/chromeos/chromeos_features.cc b/chromeos/chromeos_features.cc
index 1d2c3313..0dc80ed 100644
--- a/chromeos/chromeos_features.cc
+++ b/chromeos/chromeos_features.cc
@@ -25,6 +25,10 @@
 const base::Feature kChromeVoxArcSupport{"ChromeVoxArcSupport",
                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables or disables Crostini support for usb mounting.
+const base::Feature kCrostiniUsbSupport{"CrostiniUsbSupport",
+                                        base::FEATURE_DISABLED_BY_DEFAULT};
+
 // If enabled, DriveFS will be used for Drive sync.
 const base::Feature kDriveFs{"DriveFS", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chromeos/chromeos_features.h b/chromeos/chromeos_features.h
index 4000190e5..55eef692 100644
--- a/chromeos/chromeos_features.h
+++ b/chromeos/chromeos_features.h
@@ -19,6 +19,7 @@
 CHROMEOS_EXPORT extern const base::Feature kAndroidMessagesProdEndpoint;
 CHROMEOS_EXPORT extern const base::Feature kAutoScreenBrightness;
 CHROMEOS_EXPORT extern const base::Feature kChromeVoxArcSupport;
+CHROMEOS_EXPORT extern const base::Feature kCrostiniUsbSupport;
 CHROMEOS_EXPORT extern const base::Feature kDriveFs;
 CHROMEOS_EXPORT extern const base::Feature kMyFilesVolume;
 CHROMEOS_EXPORT extern const base::Feature kEnableUnifiedMultiDeviceSettings;
diff --git a/chromeos/chromeos_test_utils.cc b/chromeos/chromeos_test_utils.cc
index 6908137..be4dc4d 100644
--- a/chromeos/chromeos_test_utils.cc
+++ b/chromeos/chromeos_test_utils.cc
@@ -7,6 +7,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/threading/thread_restrictions.h"
 
 namespace chromeos {
 namespace test_utils {
@@ -20,8 +21,11 @@
   path = path.Append(FILE_PATH_LITERAL("chromeos"));
   path = path.Append(FILE_PATH_LITERAL("test"));
   path = path.Append(FILE_PATH_LITERAL("data"));
-  if (!base::PathExists(path))  // We don't want to create this.
-    return false;
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    if (!base::PathExists(path))  // We don't want to create this.
+      return false;
+  }
   DCHECK(data_dir);
   path = path.Append(component);
   *data_dir = path.Append(filename);
diff --git a/chromeos/components/drivefs/fake_drivefs.cc b/chromeos/components/drivefs/fake_drivefs.cc
index 86e22fa..f20206df 100644
--- a/chromeos/components/drivefs/fake_drivefs.cc
+++ b/chromeos/components/drivefs/fake_drivefs.cc
@@ -17,6 +17,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
+#include "base/threading/thread_restrictions.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cros_disks_client.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -287,7 +288,10 @@
 void FakeDriveFs::Init(drivefs::mojom::DriveFsConfigurationPtr config,
                        drivefs::mojom::DriveFsRequest drive_fs_request,
                        drivefs::mojom::DriveFsDelegatePtr delegate) {
-  CHECK(base::CreateDirectory(mount_path_.Append(".Trash")));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    CHECK(base::CreateDirectory(mount_path_.Append(".Trash")));
+  }
   mojo::FuseInterface(std::move(pending_delegate_request_),
                       delegate.PassInterface());
   if (binding_.is_bound())
@@ -300,9 +304,12 @@
   base::FilePath absolute_path = mount_path_;
   CHECK(base::FilePath("/").AppendRelativePath(path, &absolute_path));
   base::File::Info info;
-  if (!base::GetFileInfo(absolute_path, &info)) {
-    std::move(callback).Run(drive::FILE_ERROR_NOT_FOUND, nullptr);
-    return;
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    if (!base::GetFileInfo(absolute_path, &info)) {
+      std::move(callback).Run(drive::FILE_ERROR_NOT_FOUND, nullptr);
+      return;
+    }
   }
   auto metadata = drivefs::mojom::FileMetadata::New();
   metadata->size = info.size;
@@ -360,6 +367,7 @@
 void FakeDriveFs::CopyFile(const base::FilePath& source,
                            const base::FilePath& target,
                            CopyFileCallback callback) {
+  base::ScopedAllowBlockingForTesting allow_io;
   base::FilePath source_absolute_path = mount_path_;
   base::FilePath target_absolute_path = mount_path_;
   CHECK(base::FilePath("/").AppendRelativePath(source, &source_absolute_path));
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc
index 2244ecbe..5bf3aae4 100644
--- a/chromeos/dbus/fake_session_manager_client.cc
+++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -471,7 +471,14 @@
         base::FilePath key_path;
         GetStubPolicyFilePath(descriptor, &key_path);
         DCHECK(!key_path.empty());
-        StoreFiles({{key_path, response.new_public_key()}});
+
+        base::PostTaskWithTraits(
+            FROM_HERE,
+            {base::MayBlock(),
+             base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+            base::BindOnce(StoreFiles,
+                           std::map<base::FilePath, std::string>{
+                               {key_path, response.new_public_key()}}));
         for (auto& observer : observers_)
           observer.OwnerKeySet(true /* success */);
       }
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc
index 77ecfbd..e280a6e 100644
--- a/chromeos/network/onc/onc_signature.cc
+++ b/chromeos/network/onc/onc_signature.cc
@@ -517,6 +517,9 @@
     {&kOpenVPNSignature, ::onc::openvpn::kTLSAuthContents},
     {&kWiFiSignature, ::onc::wifi::kPassphrase},
     {&kCellularApnSignature, ::onc::cellular_apn::kPassword},
+    // While not really a credential, PKCS12 blobs may contain unencrypted
+    // private keys.
+    {&kCertificateSignature, ::onc::certificate::kPKCS12},
     {NULL}};
 
 }  // namespace
diff --git a/chromeos/network/onc/onc_test_utils.cc b/chromeos/network/onc/onc_test_utils.cc
index 1243415..c4a48d6 100644
--- a/chromeos/network/onc/onc_test_utils.cc
+++ b/chromeos/network/onc/onc_test_utils.cc
@@ -11,6 +11,7 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chromeos/chromeos_test_utils.h"
 
@@ -26,6 +27,7 @@
 }  // namespace
 
 std::string ReadTestData(const std::string& filename) {
+  base::ScopedAllowBlockingForTesting allow_io;
   base::FilePath path;
   if (!chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory,
                                              filename,
diff --git a/components/arc/test/fake_app_instance.cc b/components/arc/test/fake_app_instance.cc
index 81086ade..34f80b7 100644
--- a/components/arc/test/fake_app_instance.cc
+++ b/components/arc/test/fake_app_instance.cc
@@ -17,6 +17,7 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
 #include "components/arc/app/arc_playstore_search_request_state.h"
 
 namespace mojo {
@@ -188,8 +189,11 @@
           .AppendASCII("arc")
           .AppendASCII(base::StringPrintf(
               "icon_%s_%d.png", app_icon ? "app" : "shortcut", dimension));
-  CHECK(base::PathExists(icon_file_path)) << icon_file_path.MaybeAsASCII();
-  CHECK(base::ReadFileToString(icon_file_path, png_data_as_string));
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    CHECK(base::PathExists(icon_file_path)) << icon_file_path.MaybeAsASCII();
+    CHECK(base::ReadFileToString(icon_file_path, png_data_as_string));
+  }
   icon_responses_[dimension] = *png_data_as_string;
   return true;
 }
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index ed4587b..a13ca78 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -482,6 +482,9 @@
     case 80:
       *update_compatible_version = true;
       return MigrateToVersion80AddIsClientValidityStatesUpdatedColumn();
+    case 81:
+      *update_compatible_version = true;
+      return MigrateToVersion81CleanUpWrongModelTypeData();
   }
   return true;
 }
@@ -2545,6 +2548,11 @@
                               "(model_type, storage_key, value) "
                               "SELECT ?, storage_key, value "
                               "FROM autofill_sync_metadata"));
+  // Note: This uses the *wrong* ID for the ModelType - instead of
+  // |syncer::ModelTypeToHistogramInt|, this should be |GetKeyValueForModelType|
+  // aka |syncer::ModelTypeToStableIdentifier|. But at this point, fixing it
+  // here would just make an even bigger mess. Instead, we clean this up in the
+  // migration to version 81. See also crbug.com/895826.
   insert_metadata.BindInt(0, syncer::ModelTypeToHistogramInt(syncer::AUTOFILL));
 
   // Prior to this migration, the table was a singleton, containing only one
@@ -2553,6 +2561,7 @@
       db_->GetUniqueStatement("INSERT INTO autofill_model_type_state_temp "
                               "(model_type, value) SELECT ?, value "
                               "FROM autofill_model_type_state WHERE id=1"));
+  // Note: Like above, this uses the *wrong* ID for the ModelType.
   insert_state.BindInt(0, syncer::ModelTypeToHistogramInt(syncer::AUTOFILL));
 
   if (!insert_metadata.Run() || !insert_state.Run()) {
@@ -2579,6 +2588,32 @@
       "NULL DEFAULT FALSE");
 }
 
+bool AutofillTable::MigrateToVersion81CleanUpWrongModelTypeData() {
+  // The migration to version 78 inserted Sync data with wrong values in the
+  // model_type column of the autofill_model_type_state and
+  // autofill_sync_metadata tables. Here we just delete the bad data - no point
+  // in trying to recover anything, since by now it'll have been redownloaded
+  // anyway.
+  const int bad_model_type_id =
+      syncer::ModelTypeToHistogramInt(syncer::AUTOFILL);
+  DCHECK_NE(bad_model_type_id, GetKeyValueForModelType(syncer::AUTOFILL));
+
+  sql::Transaction transaction(db_);
+  if (!transaction.Begin())
+    return false;
+
+  sql::Statement delete_bad_model_type_state(db_->GetUniqueStatement(
+      "DELETE FROM autofill_model_type_state WHERE model_type = ?;"));
+  delete_bad_model_type_state.BindInt(0, bad_model_type_id);
+
+  sql::Statement delete_bad_sync_metadata(db_->GetUniqueStatement(
+      "DELETE FROM autofill_sync_metadata WHERE model_type = ?;"));
+  delete_bad_sync_metadata.BindInt(0, bad_model_type_id);
+
+  return delete_bad_model_type_state.Run() && delete_bad_sync_metadata.Run() &&
+         transaction.Commit();
+}
+
 bool AutofillTable::AddFormFieldValuesTime(
     const std::vector<FormFieldData>& elements,
     std::vector<AutofillChange>* changes,
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index 8af3e21..4c47232 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -527,6 +527,7 @@
   bool MigrateToVersion75AddProfileValidityBitfieldColumn();
   bool MigrateToVersion78AddModelTypeColumns();
   bool MigrateToVersion80AddIsClientValidityStatesUpdatedColumn();
+  bool MigrateToVersion81CleanUpWrongModelTypeData();
   // Max data length saved in the table, AKA the maximum length allowed for
   // form data.
   // Copied to components/autofill/ios/browser/resources/autofill_controller.js.
diff --git a/components/drive/drive_notification_manager.cc b/components/drive/drive_notification_manager.cc
index 658a89cd..3f789e5 100644
--- a/components/drive/drive_notification_manager.cc
+++ b/components/drive/drive_notification_manager.cc
@@ -107,7 +107,8 @@
       unpacked_id = id.name().substr(kTeamDriveChangePrefixLength);
     }
     auto invalidations = invalidation_map.ForObject(id);
-    int64_t& invalidation_version = invalidated_change_ids_[unpacked_id] = -1;
+    int64_t& invalidation_version =
+        invalidated_change_ids_.emplace(unpacked_id, -1).first->second;
     for (auto& invalidation : invalidations) {
       if (!invalidation.is_unknown_version() &&
           invalidation.version() > invalidation_version) {
@@ -189,6 +190,13 @@
   DVLOG(1) << "Notifying observers: " << NotificationSourceToString(source);
 
   if (source == NOTIFICATION_XMPP) {
+    auto my_drive_invalidation = invalidations.find("");
+    if (my_drive_invalidation != invalidations.end() &&
+        my_drive_invalidation->second != -1) {
+      // The invalidation version for My Drive is smaller than what's expected
+      // for fetch requests by 1. Increment it unless it hasn't been set.
+      ++my_drive_invalidation->second;
+    }
     for (auto& observer : observers_)
       observer.OnNotificationReceived(invalidations);
   } else {
@@ -249,7 +257,7 @@
   std::map<std::string, int64_t> change_ids_to_update;
   invalidated_change_ids_.swap(change_ids_to_update);
   if (!change_ids_to_update.empty()) {
-    NotifyObserversToUpdate(NOTIFICATION_XMPP, change_ids_to_update);
+    NotifyObserversToUpdate(NOTIFICATION_XMPP, std::move(change_ids_to_update));
   }
 }
 
diff --git a/components/drive/drive_notification_manager_unittest.cc b/components/drive/drive_notification_manager_unittest.cc
index 9517afa..c34a7d1e 100644
--- a/components/drive/drive_notification_manager_unittest.cc
+++ b/components/drive/drive_notification_manager_unittest.cc
@@ -184,7 +184,7 @@
   task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5));
 
   // Default corpus is has the id "" when sent to observers.
-  expected_ids = {{"", 1}};
+  expected_ids = {{"", 2}};
   EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds());
   drive_notification_observer_->ClearNotificationIds();
 
@@ -203,10 +203,19 @@
       syncer::Invalidation::Init(kDefaultCorpusObjectId, 1, ""));
   fake_invalidation_service_->EmitInvalidationForTest(
       syncer::Invalidation::Init(team_drive_1_object_id, 2, ""));
+
+  // Emit with an earlier version. This should be ignored.
+  fake_invalidation_service_->EmitInvalidationForTest(
+      syncer::Invalidation::Init(kDefaultCorpusObjectId, 0, ""));
+
+  // Emit without a version. This should be ignored too.
+  fake_invalidation_service_->EmitInvalidationForTest(
+      syncer::Invalidation::InitUnknownVersion(kDefaultCorpusObjectId));
+
   EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty());
 
   task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5));
-  expected_ids = {{"", 1}, {team_drive_id_1, 2}};
+  expected_ids = {{"", 2}, {team_drive_id_1, 2}};
   EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds());
 }
 
diff --git a/components/drive/service/fake_drive_service.cc b/components/drive/service/fake_drive_service.cc
index 414a268..dc41498a 100644
--- a/components/drive/service/fake_drive_service.cc
+++ b/components/drive/service/fake_drive_service.cc
@@ -1225,10 +1225,14 @@
   }
 
   std::string content_data;
-  if (!base::ReadFileToString(local_file_path, &content_data)) {
-    session->uploaded_size = end_position;
-    completion_callback.Run(DRIVE_FILE_ERROR, std::unique_ptr<FileResource>());
-    return CancelCallback();
+  {
+    base::ScopedAllowBlockingForTesting allow_io;
+    if (!base::ReadFileToString(local_file_path, &content_data)) {
+      session->uploaded_size = end_position;
+      completion_callback.Run(DRIVE_FILE_ERROR,
+                              std::unique_ptr<FileResource>());
+      return CancelCallback();
+    }
   }
   session->uploaded_size = end_position;
 
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc
index f9d6b78..1b461e7 100644
--- a/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -662,54 +662,8 @@
 
 // If system tray is shown by click. It should be activated if user presses tab
 // key while shell surface is active.
-TEST_F(ClientControlledShellSurfaceTest, KeyboardNavigationWithSystemTray) {
-  // This is old SystemTray version.
-  if (ash::features::IsSystemTrayUnifiedEnabled())
-    return;
-
-  const gfx::Size buffer_size(800, 600);
-  std::unique_ptr<Buffer> buffer(
-      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
-  std::unique_ptr<Surface> surface(new Surface());
-  auto shell_surface =
-      exo_test_helper()->CreateClientControlledShellSurface(surface.get());
-
-  surface->Attach(buffer.get());
-  surface->Commit();
-
-  EXPECT_TRUE(shell_surface->GetWidget()->IsActive());
-
-  // Show system tray by perfoming a gesture tap at tray.
-  ash::SystemTray* system_tray = GetPrimarySystemTray();
-  ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
-                       ui::GestureEventDetails(ui::ET_GESTURE_TAP));
-  system_tray->PerformAction(tap);
-  ASSERT_TRUE(system_tray->GetWidget());
-
-  // Confirm that system tray is not active at this time.
-  EXPECT_TRUE(shell_surface->GetWidget()->IsActive());
-  EXPECT_FALSE(
-      system_tray->GetSystemBubble()->bubble_view()->GetWidget()->IsActive());
-
-  // Send tab key event.
-  ui::test::EventGenerator* event_generator = GetEventGenerator();
-  event_generator->PressKey(ui::VKEY_TAB, ui::EF_NONE);
-  event_generator->ReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
-
-  // Confirm that system tray is activated.
-  EXPECT_FALSE(shell_surface->GetWidget()->IsActive());
-  EXPECT_TRUE(
-      system_tray->GetSystemBubble()->bubble_view()->GetWidget()->IsActive());
-}
-
-// If system tray is shown by click. It should be activated if user presses tab
-// key while shell surface is active.
 TEST_F(ClientControlledShellSurfaceTest,
        KeyboardNavigationWithUnifiedSystemTray) {
-  // This is UnifiedSystemTray version.
-  if (!ash::features::IsSystemTrayUnifiedEnabled())
-    return;
-
   const gfx::Size buffer_size(800, 600);
   std::unique_ptr<Buffer> buffer(
       new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
diff --git a/components/omnibox/browser/autocomplete_provider.cc b/components/omnibox/browser/autocomplete_provider.cc
index 7ff72b3..c13b07d 100644
--- a/components/omnibox/browser/autocomplete_provider.cc
+++ b/components/omnibox/browser/autocomplete_provider.cc
@@ -5,11 +5,16 @@
 #include "components/omnibox/browser/autocomplete_provider.h"
 
 #include <algorithm>
+#include <set>
 #include <string>
 
+#include "base/i18n/case_conversion.h"
 #include "base/logging.h"
+#include "base/no_destructor.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/strings/string_split.h"
 #include "base/trace_event/memory_usage_estimator.h"
+#include "components/omnibox/browser/autocomplete_i18n.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/url_formatter/url_fixer.h"
@@ -61,6 +66,152 @@
   return TypeToString(type_);
 }
 
+AutocompleteProvider::WordMap AutocompleteProvider::CreateWordMapForString(
+    const base::string16& text) {
+  // First, convert |text| to a vector of the unique words in it.
+  WordMap word_map;
+  // Use base::SplitString instead of base::i18n::BreakIterator due to
+  // https://crbug.com/784229
+  std::vector<base::string16> words =
+      base::SplitString(text, base::kWhitespaceASCIIAs16, base::TRIM_WHITESPACE,
+                        base::SPLIT_WANT_NONEMPTY);
+  if (words.empty())
+    return word_map;
+  std::sort(words.begin(), words.end());
+  words.erase(std::unique(words.begin(), words.end()), words.end());
+
+  // Now create a map from (first character) to (words beginning with that
+  // character).  We insert in reverse lexicographical order and rely on the
+  // multimap preserving insertion order for values with the same key.  (This
+  // is mandated in C++11, and part of that decision was based on a survey of
+  // existing implementations that found that it was already true everywhere.)
+  std::reverse(words.begin(), words.end());
+  for (std::vector<base::string16>::const_iterator i(words.begin());
+       i != words.end(); ++i)
+    word_map.insert(std::make_pair((*i)[0], *i));
+  return word_map;
+}
+
+ACMatchClassifications AutocompleteProvider::ClassifyAllMatchesInString(
+    const base::string16& find_text,
+    const WordMap& find_words,
+    const base::string16& text,
+    const bool text_is_search_query,
+    const ACMatchClassifications& original_class) {
+  DCHECK(!find_text.empty());
+  DCHECK(!find_words.empty());
+
+  static base::NoDestructor<std::set<base::char16>> whitespace_set{
+      base::StringPiece16(base::kWhitespaceASCIIAs16).begin(),
+      base::StringPiece16(base::kWhitespaceASCIIAs16).end()};
+
+  if (text.empty())
+    return original_class;
+
+  base::string16 text_lowercase(base::i18n::ToLower(text));
+
+  const ACMatchClassification::Style& class_of_find_text =
+      text_is_search_query ? ACMatchClassification::NONE
+                           : ACMatchClassification::MATCH;
+  const ACMatchClassification::Style& class_of_additional_text =
+      text_is_search_query ? ACMatchClassification::MATCH
+                           : ACMatchClassification::NONE;
+
+  ACMatchClassifications match_class;
+  size_t current_position = 0;
+
+  // First check whether |text| begins with |find_text| and mark that whole
+  // section as a match if so.
+  if (base::StartsWith(text_lowercase, find_text,
+                       base::CompareCase::SENSITIVE)) {
+    match_class.push_back(ACMatchClassification(0, class_of_find_text));
+    // If |text_lowercase| is actually equal to |find_text|, we don't need to
+    // (and in fact shouldn't) put a trailing NONE classification after the end
+    // of the string.
+    if (find_text.length() < text_lowercase.length()) {
+      match_class.push_back(
+          ACMatchClassification(find_text.length(), class_of_additional_text));
+    }
+    // Sets |current_position| to |text_lowercase.length()| to skip
+    // word-by-word highlighting.  That is, if we found a prefix match,
+    // we don't highlight additional word matches after the prefix.
+    current_position = text_lowercase.length();
+  } else {
+    // |match_class| should start at position 0.  If the first matching word is
+    // found at position 0, this will be popped from the vector further down.
+    match_class.push_back(ACMatchClassification(0, class_of_additional_text));
+  }
+
+  size_t word_end = 0;
+  bool has_matched = false;
+  // Now, starting with |current_position|, check each character in
+  // |text_lowercase| to see if we have words starting with that character in
+  // |find_words|. If so, check each of them to see if they match the portion
+  // of |text_lowercase| beginning with |current_position|. Accept the first
+  // matching word found (which should be the longest possible match at this
+  // location, given the construction of |find_words|) and add a MATCH region to
+  // |match_class|, moving |current_position| to be after the matching word. If
+  // we found no matching words, move to the next character or word and repeat.
+  while (current_position < text_lowercase.length()) {
+    auto range(find_words.equal_range(text_lowercase[current_position]));
+    for (WordMap::const_iterator i(range.first); i != range.second; ++i) {
+      const base::string16& word = i->second;
+      word_end = current_position + word.length();
+      if ((word_end <= text_lowercase.length()) &&
+          !text_lowercase.compare(current_position, word.length(), word)) {
+        // Collapse adjacent ranges into one.
+        if (match_class.back().offset == current_position)
+          match_class.pop_back();
+
+        AutocompleteMatch::AddLastClassificationIfNecessary(
+            &match_class, current_position, class_of_find_text);
+        if (word_end < text_lowercase.length()) {
+          if (!text_is_search_query ||
+              whitespace_set->find(text_lowercase[word_end]) ==
+                  whitespace_set->end()) {
+            match_class.push_back(
+                ACMatchClassification(word_end, class_of_additional_text));
+          }
+        }
+        has_matched = true;
+        current_position = word_end;
+        break;
+      }
+    }
+    // If there is no matching word, put |class_of_additional_text|.
+    if (!has_matched && (match_class.empty() || match_class.back().style !=
+                                                    class_of_additional_text)) {
+      match_class.push_back(
+          ACMatchClassification(current_position, class_of_additional_text));
+    }
+    // Moves to next character.
+    if (text_is_search_query) {
+      // Find next word for prefix search.
+      auto whitespaces = *whitespace_set;
+      auto found = std::find_if(
+          text_lowercase.begin() + current_position, text_lowercase.end(),
+          [whitespaces](auto next_char) {
+            return whitespaces.find(next_char) != whitespaces.end();
+          });
+      if (found != text_lowercase.end()) {
+        current_position =
+            std::distance(text_lowercase.begin(), found);
+        current_position++;
+      } else {
+        current_position = text_lowercase.length();
+      }
+    } else {
+      if (!has_matched)
+        current_position++;
+    }
+    has_matched = false;
+  }
+
+  if (original_class.empty())
+    return match_class;
+  return AutocompleteMatch::MergeClassifications(original_class, match_class);
+}
+
 metrics::OmniboxEventProto_ProviderType AutocompleteProvider::
     AsOmniboxEventProviderType() const {
   switch (type_) {
diff --git a/components/omnibox/browser/autocomplete_provider.h b/components/omnibox/browser/autocomplete_provider.h
index 57e3886..5f76624 100644
--- a/components/omnibox/browser/autocomplete_provider.h
+++ b/components/omnibox/browser/autocomplete_provider.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 
+#include <map>
 #include <utility>
 #include <vector>
 
@@ -207,6 +208,13 @@
   // with the previous session.
   virtual void ResetSession();
 
+  // Estimates dynamic memory usage.
+  // See base/trace_event/memory_usage_estimator.h for more info.
+  //
+  // Note: Subclasses that override this method must call the base class
+  // method and include the response in their estimate.
+  virtual size_t EstimateMemoryUsage() const;
+
   // Returns the set of matches for the current query.
   const ACMatches& matches() const { return matches_; }
 
@@ -219,19 +227,60 @@
   // Returns a string describing this provider's type.
   const char* GetName() const;
 
+  typedef std::multimap<base::char16, base::string16> WordMap;
+
+  // Returns a map mapping characters to groups of words from |text| that start
+  // with those characters, ordered lexicographically descending so that longer
+  // words appear before their prefixes (if any) within a particular
+  // equal_range().
+  static WordMap CreateWordMapForString(const base::string16& text);
+
+  // Finds all instances of the words from |find_words| within |text|, adds
+  // classifications to |original_class| according to the logic described below,
+  // and returns the result.
+  //
+  //   - if |text_is_search_query| is false, the function adds
+  //   ACMatchClassification::MATCH markers for all such instances.
+  //
+  //   For example, given the |text|
+  //   "Sports and News at sports.somesite.com - visit us!" and |original_class|
+  //   {{0, NONE}, {18, URL}, {37, NONE}} (marking "sports.somesite.com" as a
+  //   URL), calling with |find_text| set to "sp ew" would return
+  //   {{0, MATCH}, {2, NONE}, {12, MATCH}, {14, NONE}, {18, URL|MATCH},
+  //   {20, URL}, {37, NONE}}.
+  //
+  //
+  //   - if |text_is_search_query| is true, applies the same logic, but uses
+  //   NONE for the matching text and MATCH for the non-matching text. This is
+  //   done to mimic the behavior of SearchProvider which decorates matches
+  //   according to the approach used by Google Suggest.
+  //
+  //   For example, given that |text| corresponds to a search query "panama
+  //   canal" and |original class| is {{0, NONE}}, calling with |find_text| set
+  //   to "canal" would return {{0,MATCH}, {7, NONE}}.
+  //
+  // |find_text| is provided as the original string used to create
+  // |find_words|. This is supplied because it's common for this to be a prefix
+  // of |text|, so we can quickly check for that and mark that entire substring
+  // as a match before proceeding with the more generic algorithm.
+  //
+  // |find_words| should be as constructed by CreateWordMapForString(find_text).
+  //
+  // |find_text| (and thus |find_words|) are expected to be lowercase. |text|
+  // will be lowercase in this function.
+  static ACMatchClassifications ClassifyAllMatchesInString(
+      const base::string16& find_text,
+      const WordMap& find_words,
+      const base::string16& text,
+      const bool text_is_search_query,
+      const ACMatchClassifications& original_class = ACMatchClassifications());
+
   // A suggested upper bound for how many matches a provider should return.
   // TODO(pkasting): http://b/1111299 , http://b/933133 This should go away once
   // we have good relevance heuristics; the controller should handle all
   // culling.
   static const size_t kMaxMatches;
 
-  // Estimates dynamic memory usage.
-  // See base/trace_event/memory_usage_estimator.h for more info.
-  //
-  // Note: Subclasses that override this method must call the base class
-  // method and include the response in their estimate.
-  virtual size_t EstimateMemoryUsage() const;
-
  protected:
   friend class base::RefCountedThreadSafe<AutocompleteProvider>;
   FRIEND_TEST_ALL_PREFIXES(BookmarkProviderTest, InlineAutocompletion);
diff --git a/components/omnibox/browser/autocomplete_provider_unittest.cc b/components/omnibox/browser/autocomplete_provider_unittest.cc
index 8ec9119..79b53c0 100644
--- a/components/omnibox/browser/autocomplete_provider_unittest.cc
+++ b/components/omnibox/browser/autocomplete_provider_unittest.cc
@@ -199,6 +199,36 @@
   }
 }
 
+// Helper class to make running tests of ClassifyAllMatchesInString() more
+// convenient.
+class ClassifyTest {
+ public:
+  ClassifyTest(const base::string16& text,
+               const bool text_is_query,
+               ACMatchClassifications matches);
+  ~ClassifyTest();
+
+  ACMatchClassifications RunTest(const base::string16& find_text);
+
+ private:
+  const base::string16 text_;
+  const bool text_is_query_;
+  const ACMatchClassifications matches_;
+};
+
+ClassifyTest::ClassifyTest(const base::string16& text,
+                           const bool text_is_query,
+                           ACMatchClassifications matches)
+    : text_(text), text_is_query_(text_is_query), matches_(matches) {}
+
+ClassifyTest::~ClassifyTest() {}
+
+ACMatchClassifications ClassifyTest::RunTest(const base::string16& find_text) {
+  return AutocompleteProvider::ClassifyAllMatchesInString(
+      find_text, AutocompleteProvider::CreateWordMapForString(find_text), text_,
+      text_is_query_, matches_);
+}
+
 class AutocompleteProviderTest : public testing::Test {
  public:
   AutocompleteProviderTest();
@@ -776,3 +806,160 @@
   url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456));
   EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j4&", url.path());
 }
+
+TEST_F(AutocompleteProviderTest, ClassifyAllMatchesInString) {
+  ResetControllerWithKeywordAndSearchProviders();
+
+  using base::ASCIIToUTF16;
+  ACMatchClassifications matches =
+      AutocompleteMatch::ClassificationsFromString("0,0");
+  ClassifyTest classify_test(ASCIIToUTF16("A man, a plan, a canal Panama"),
+                             /*text_is_query=*/false, matches);
+
+  ACMatchClassifications spans_a = classify_test.RunTest(ASCIIToUTF16("man"));
+  // ACMatch spans should be: '--MMM------------------------'
+  EXPECT_EQ("0,0,2,2,5,0", AutocompleteMatch::ClassificationsToString(spans_a));
+
+  ACMatchClassifications spans_b = classify_test.RunTest(ASCIIToUTF16("man p"));
+  // ACMatch spans should be: '--MMM----M-------------M-----'
+  EXPECT_EQ("0,0,2,2,5,0,9,2,10,0,23,2,24,0",
+            AutocompleteMatch::ClassificationsToString(spans_b));
+
+  ACMatchClassifications spans_c =
+      classify_test.RunTest(ASCIIToUTF16("man plan panama"));
+  // ACMatch spans should be:'--MMM----MMMM----------MMMMMM'
+  EXPECT_EQ("0,0,2,2,5,0,9,2,13,0,23,2",
+            AutocompleteMatch::ClassificationsToString(spans_c));
+
+  ClassifyTest classify_test2(
+      ASCIIToUTF16("Yahoo! Sports - Sports News, "
+                   "Scores, Rumors, Fantasy Games, and more"),
+      /*text_is_query=*/false, matches);
+
+  ACMatchClassifications spans_d = classify_test2.RunTest(ASCIIToUTF16("ne"));
+  // ACMatch spans should match first two letters of the "news".
+  EXPECT_EQ("0,0,23,2,25,0",
+            AutocompleteMatch::ClassificationsToString(spans_d));
+
+  ACMatchClassifications spans_e =
+      classify_test2.RunTest(ASCIIToUTF16("news r"));
+  EXPECT_EQ(
+      "0,0,10,2,11,0,19,2,20,0,23,2,27,0,32,2,33,0,37,2,38,0,41,2,42,0,"
+      "66,2,67,0",
+      AutocompleteMatch::ClassificationsToString(spans_e));
+
+  matches = AutocompleteMatch::ClassificationsFromString("0,1");
+  ClassifyTest classify_test3(ASCIIToUTF16("livescore.goal.com"),
+                              /*text_is_query=*/false, matches);
+
+  ACMatchClassifications spans_f = classify_test3.RunTest(ASCIIToUTF16("go"));
+  // ACMatch spans should match first two letters of the "goal".
+  EXPECT_EQ("0,1,10,3,12,1",
+            AutocompleteMatch::ClassificationsToString(spans_f));
+
+  matches = AutocompleteMatch::ClassificationsFromString("0,0,13,1");
+  ClassifyTest classify_test4(ASCIIToUTF16("Email login: mail.somecorp.com"),
+                              /*text_is_query=*/false, matches);
+
+  ACMatchClassifications spans_g = classify_test4.RunTest(ASCIIToUTF16("ail"));
+  EXPECT_EQ("0,0,2,2,5,0,13,1,14,3,17,1",
+            AutocompleteMatch::ClassificationsToString(spans_g));
+
+  ACMatchClassifications spans_h =
+      classify_test4.RunTest(ASCIIToUTF16("lo log"));
+  EXPECT_EQ("0,0,6,2,9,0,13,1",
+            AutocompleteMatch::ClassificationsToString(spans_h));
+
+  ACMatchClassifications spans_i =
+      classify_test4.RunTest(ASCIIToUTF16("ail em"));
+  // 'Email' and 'ail' should be matched.
+  EXPECT_EQ("0,2,5,0,13,1,14,3,17,1",
+            AutocompleteMatch::ClassificationsToString(spans_i));
+
+  // Some web sites do not have a description.  If the string being searched is
+  // empty, the classifications must also be empty: http://crbug.com/148647
+  // Extra parens in the next line hack around C++03's "most vexing parse".
+  class ClassifyTest classify_test5((base::string16()), /*text_is_query=*/false,
+                                    ACMatchClassifications());
+  ACMatchClassifications spans_j = classify_test5.RunTest(ASCIIToUTF16("man"));
+  ASSERT_EQ(0U, spans_j.size());
+
+  // Matches which end at beginning of classification merge properly.
+  matches = AutocompleteMatch::ClassificationsFromString("0,4,9,0");
+  ClassifyTest classify_test6(ASCIIToUTF16("html password example"),
+                              /*text_is_query=*/false, matches);
+
+  // Extra space in the next string avoids having the string be a prefix of the
+  // text above, which would allow for two different valid classification sets,
+  // one of which uses two spans (the first of which would mark all of "html
+  // pass" as a match) and one which uses four (which marks the individual words
+  // as matches but not the space between them).  This way only the latter is
+  // valid.
+  ACMatchClassifications spans_k =
+      classify_test6.RunTest(ASCIIToUTF16("html  pass"));
+  EXPECT_EQ("0,6,4,4,5,6,9,0",
+            AutocompleteMatch::ClassificationsToString(spans_k));
+
+  // Multiple matches with both beginning and end at beginning of
+  // classifications merge properly.
+  matches = AutocompleteMatch::ClassificationsFromString("0,1,11,0");
+  ClassifyTest classify_test7(ASCIIToUTF16("http://a.co is great"),
+                              /*text_is_query=*/false, matches);
+
+  ACMatchClassifications spans_l =
+      classify_test7.RunTest(ASCIIToUTF16("ht co"));
+  EXPECT_EQ("0,3,2,1,9,3,11,0",
+            AutocompleteMatch::ClassificationsToString(spans_l));
+
+  // Queries should be classify the same way as google search autocomplete
+  // suggestions.
+  matches = AutocompleteMatch::ClassificationsFromString("0,0");
+  ClassifyTest classify_test8(ASCIIToUTF16("panama canal"),
+                              /*text_is_query=*/true, matches);
+
+  ACMatchClassifications spans_m = classify_test8.RunTest(ASCIIToUTF16("pan"));
+  // ACMatch spans should be: "---MMMMMMMMM";
+  EXPECT_EQ("0,0,3,2", AutocompleteMatch::ClassificationsToString(spans_m));
+  ACMatchClassifications spans_n =
+      classify_test8.RunTest(ASCIIToUTF16("canal"));
+  // ACMatch spans should be: "MMMMMM-----";
+  EXPECT_EQ("0,2,7,0", AutocompleteMatch::ClassificationsToString(spans_n));
+
+  // Search autocomplete suggesion.
+  ClassifyTest classify_test9(ASCIIToUTF16("comcast webmail login"),
+                              /*text_is_query=*/true, ACMatchClassifications());
+
+  // Matches first and first part of middle word and the last word..
+  ACMatchClassifications spans_o =
+      classify_test9.RunTest(ASCIIToUTF16("comcast web login"));
+  // ACMatch spans should be: "-----------MMMMM-----";
+  EXPECT_EQ("0,0,11,2,16,0",
+            AutocompleteMatch::ClassificationsToString(spans_o));
+
+  // Matches partial word in the middle of suggestion.
+  ACMatchClassifications spans_p =
+      classify_test9.RunTest(ASCIIToUTF16("web"));
+  // ACMatch spans should be: "MMMMMMMM---MMMMMMMMMM";
+  EXPECT_EQ("0,2,8,0,11,2",
+            AutocompleteMatch::ClassificationsToString(spans_p));
+
+  ClassifyTest classify_test10(ASCIIToUTF16("comcast.net web mail login"),
+                              /*text_is_query=*/true, ACMatchClassifications());
+
+  ACMatchClassifications spans_q =
+      classify_test10.RunTest(ASCIIToUTF16("comcast web login"));
+  // ACMatch spans should be: "-------MMMMM----MMMMM-----";
+  EXPECT_EQ("0,0,7,2,12,0,16,2,21,0",
+            AutocompleteMatch::ClassificationsToString(spans_q));
+
+  // Same with |classify_test10| except using characters in
+  // base::kWhitespaceASCIIAs16 instead of white space.
+  ClassifyTest classify_test11(ASCIIToUTF16("comcast.net\x0aweb\x0dmail login"),
+                              /*text_is_query=*/true, ACMatchClassifications());
+
+  ACMatchClassifications spans_r =
+      classify_test11.RunTest(ASCIIToUTF16("comcast web login"));
+  // ACMatch spans should be: "-------MMMMM----MMMMM-----";
+  EXPECT_EQ("0,0,7,2,12,0,16,2,21,0",
+            AutocompleteMatch::ClassificationsToString(spans_r));
+}
diff --git a/components/omnibox/browser/search_suggestion_parser.cc b/components/omnibox/browser/search_suggestion_parser.cc
index 48ee325..52a58c6 100644
--- a/components/omnibox/browser/search_suggestion_parser.cc
+++ b/components/omnibox/browser/search_suggestion_parser.cc
@@ -8,7 +8,6 @@
 
 #include <algorithm>
 #include <memory>
-#include <utility>
 
 #include "base/i18n/icu_string_conversions.h"
 #include "base/json/json_reader.h"
@@ -17,10 +16,15 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "components/omnibox/browser/autocomplete_i18n.h"
 #include "components/omnibox/browser/autocomplete_input.h"
+#include "components/omnibox/browser/autocomplete_provider.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/url_prefix.h"
 #include "components/url_formatter/url_fixer.h"
@@ -175,42 +179,11 @@
     // so, leave it as is.
     return;
   }
-  match_contents_class_.clear();
-  // We do intra-string highlighting for suggestions - the suggested segment
-  // will be highlighted, e.g. for input_text = "you" the suggestion may be
-  // "youtube", so we'll bold the "tube" section: you*tube*.
-  if (input_text != match_contents_) {
-    if (lookup_position == match_contents_.end()) {
-      // The input text is not a substring of the query string, e.g. input
-      // text is "slasdot" and the query string is "slashdot", so we bold the
-      // whole thing.
-      match_contents_class_.push_back(
-          ACMatchClassification(0, ACMatchClassification::MATCH));
-    } else {
-      // We don't iterate over the string here annotating all matches because
-      // it looks odd to have every occurrence of a substring that may be as
-      // short as a single character highlighted in a query suggestion result,
-      // e.g. for input text "s" and query string "southwest airlines", it
-      // looks odd if both the first and last s are highlighted.
-      const size_t lookup_index = lookup_position - match_contents_.begin();
-      if (lookup_index != 0) {
-        match_contents_class_.push_back(
-            ACMatchClassification(0, ACMatchClassification::MATCH));
-      }
-      match_contents_class_.push_back(
-          ACMatchClassification(lookup_index, ACMatchClassification::NONE));
-      size_t next_fragment_position = lookup_index + lookup_text.length();
-      if (next_fragment_position < match_contents_.length()) {
-        match_contents_class_.push_back(ACMatchClassification(
-            next_fragment_position, ACMatchClassification::MATCH));
-      }
-    }
-  } else {
-    // Otherwise, match_contents_ is a verbatim (what-you-typed) match, either
-    // for the default provider or a keyword search provider.
-    match_contents_class_.push_back(
-        ACMatchClassification(0, ACMatchClassification::NONE));
-  }
+
+  match_contents_class_ = AutocompleteProvider::ClassifyAllMatchesInString(
+      input_text,
+      SearchSuggestionParser::GetOrCreateWordMapForInputText(input_text),
+      match_contents_, true);
 }
 
 void SearchSuggestionParser::SuggestResult::SetAnswer(
@@ -614,3 +587,25 @@
   results->relevances_from_server = relevances != nullptr;
   return true;
 }
+
+// static
+const AutocompleteProvider::WordMap&
+SearchSuggestionParser::GetOrCreateWordMapForInputText(
+    const base::string16& input_text) {
+  auto& cache = GetWordMapCache();
+  if (cache.first != input_text) {
+    auto new_cache = std::make_pair(
+        input_text, AutocompleteProvider::CreateWordMapForString(input_text));
+    cache.swap(new_cache);
+  }
+  return cache.second;
+}
+
+// static
+std::pair<base::string16, AutocompleteProvider::WordMap>&
+SearchSuggestionParser::GetWordMapCache() {
+  static base::NoDestructor<
+      std::pair<base::string16, AutocompleteProvider::WordMap>>
+      word_map_cache;
+  return *word_map_cache;
+}
diff --git a/components/omnibox/browser/search_suggestion_parser.h b/components/omnibox/browser/search_suggestion_parser.h
index 10f8a38..6b9285ef 100644
--- a/components/omnibox/browser/search_suggestion_parser.h
+++ b/components/omnibox/browser/search_suggestion_parser.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -15,6 +16,7 @@
 #include "base/strings/string_piece.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_match_type.h"
+#include "components/omnibox/browser/autocomplete_provider.h"
 #include "components/omnibox/browser/suggestion_answer.h"
 #include "url/gurl.h"
 
@@ -341,7 +343,16 @@
       bool is_keyword_result,
       Results* results);
 
+  // Creates or returns a WordMap for |input_text|. A WordMap is a mapping from
+  // characters to groups of words that start with those characters. See
+  // comments by AutocompleteProvider::CreateWordMapForString() for details.
+  static const AutocompleteProvider::WordMap& GetOrCreateWordMapForInputText(
+      const base::string16& input_text);
+
  private:
+  static std::pair<base::string16, AutocompleteProvider::WordMap>&
+  GetWordMapCache();
+
   DISALLOW_COPY_AND_ASSIGN(SearchSuggestionParser);
 };
 
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc
index 96e73af5..6de34c0 100644
--- a/components/omnibox/browser/shortcuts_provider.cc
+++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -12,7 +12,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
@@ -163,119 +162,6 @@
     backend->RemoveObserver(this);
 }
 
-// static
-ShortcutsProvider::WordMap ShortcutsProvider::CreateWordMapForString(
-    const base::string16& text) {
-  // First, convert |text| to a vector of the unique words in it.
-  WordMap word_map;
-  base::i18n::BreakIterator word_iter(text,
-                                      base::i18n::BreakIterator::BREAK_WORD);
-  if (!word_iter.Init())
-    return word_map;
-  std::vector<base::string16> words;
-  while (word_iter.Advance()) {
-    if (word_iter.IsWord())
-      words.push_back(word_iter.GetString());
-  }
-  if (words.empty())
-    return word_map;
-  std::sort(words.begin(), words.end());
-  words.erase(std::unique(words.begin(), words.end()), words.end());
-
-  // Now create a map from (first character) to (words beginning with that
-  // character).  We insert in reverse lexicographical order and rely on the
-  // multimap preserving insertion order for values with the same key.  (This
-  // is mandated in C++11, and part of that decision was based on a survey of
-  // existing implementations that found that it was already true everywhere.)
-  std::reverse(words.begin(), words.end());
-  for (std::vector<base::string16>::const_iterator i(words.begin());
-       i != words.end(); ++i)
-    word_map.insert(std::make_pair((*i)[0], *i));
-  return word_map;
-}
-
-// static
-ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString(
-    const base::string16& find_text,
-    const WordMap& find_words,
-    const base::string16& text,
-    const bool text_is_search_query,
-    const ACMatchClassifications& original_class) {
-  DCHECK(!find_text.empty());
-  DCHECK(!find_words.empty());
-
-  // The code below assumes |text| is nonempty and therefore the resulting
-  // classification vector should always be nonempty as well.  Returning early
-  // if |text| is empty assures we'll return the (correct) empty vector rather
-  // than a vector with a single (0, NONE) match.
-  if (text.empty())
-    return original_class;
-
-  // First check whether |text| begins with |find_text| and mark that whole
-  // section as a match if so.
-  base::string16 text_lowercase(base::i18n::ToLower(text));
-  const ACMatchClassification::Style& class_of_find_text =
-      text_is_search_query ? ACMatchClassification::NONE
-                           : ACMatchClassification::MATCH;
-  const ACMatchClassification::Style& class_of_additional_text =
-      text_is_search_query ? ACMatchClassification::MATCH
-                           : ACMatchClassification::NONE;
-  ACMatchClassifications match_class;
-  size_t last_position = 0;
-  if (base::StartsWith(text_lowercase, find_text,
-                       base::CompareCase::SENSITIVE)) {
-    match_class.push_back(ACMatchClassification(0, class_of_find_text));
-    last_position = find_text.length();
-    // If |text_lowercase| is actually equal to |find_text|, we don't need to
-    // (and in fact shouldn't) put a trailing NONE classification after the end
-    // of the string.
-    if (last_position < text_lowercase.length()) {
-      match_class.push_back(
-          ACMatchClassification(last_position, class_of_additional_text));
-    }
-  } else {
-    // |match_class| should start at position 0.  If the first matching word is
-    // found at position 0, this will be popped from the vector further down.
-    match_class.push_back(ACMatchClassification(0, class_of_additional_text));
-  }
-
-  // Now, starting with |last_position|, check each character in
-  // |text_lowercase| to see if we have words starting with that character in
-  // |find_words|.  If so, check each of them to see if they match the portion
-  // of |text_lowercase| beginning with |last_position|. Accept the first
-  // matching word found (which should be the longest possible match at this
-  // location, given the construction of |find_words|) and add a MATCH region to
-  // |match_class|, moving |last_position| to be after the matching word.  If we
-  // found no matching words, move to the next character and repeat.
-  while (last_position < text_lowercase.length()) {
-    std::pair<WordMap::const_iterator, WordMap::const_iterator> range(
-        find_words.equal_range(text_lowercase[last_position]));
-    size_t next_character = last_position + 1;
-    for (auto i(range.first); i != range.second; ++i) {
-      const base::string16& word = i->second;
-      size_t word_end = last_position + word.length();
-      if ((word_end <= text_lowercase.length()) &&
-          !text_lowercase.compare(last_position, word.length(), word)) {
-        // Collapse adjacent ranges into one.
-        if (match_class.back().offset == last_position)
-          match_class.pop_back();
-
-        AutocompleteMatch::AddLastClassificationIfNecessary(
-            &match_class, last_position, class_of_find_text);
-        if (word_end < text_lowercase.length()) {
-          match_class.push_back(
-              ACMatchClassification(word_end, class_of_additional_text));
-        }
-        last_position = word_end;
-        break;
-      }
-    }
-    last_position = std::max(last_position, next_character);
-  }
-
-  return AutocompleteMatch::MergeClassifications(original_class, match_class);
-}
-
 void ShortcutsProvider::OnShortcutsLoaded() {
   initialized_ = true;
 }
diff --git a/components/omnibox/browser/shortcuts_provider.h b/components/omnibox/browser/shortcuts_provider.h
index c6646f94..ec659ca 100644
--- a/components/omnibox/browser/shortcuts_provider.h
+++ b/components/omnibox/browser/shortcuts_provider.h
@@ -6,7 +6,6 @@
 #define COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_PROVIDER_H_
 
 #include <map>
-#include <set>
 #include <string>
 
 #include "base/gtest_prod_util.h"
@@ -37,56 +36,8 @@
   friend class ShortcutsProviderTest;
   FRIEND_TEST_ALL_PREFIXES(ShortcutsProviderTest, CalculateScore);
 
-  typedef std::multimap<base::char16, base::string16> WordMap;
-
   ~ShortcutsProvider() override;
 
-  // Returns a map mapping characters to groups of words from |text| that start
-  // with those characters, ordered lexicographically descending so that longer
-  // words appear before their prefixes (if any) within a particular
-  // equal_range().
-  static WordMap CreateWordMapForString(const base::string16& text);
-
-  // Finds all instances of the words from |find_words| within |text|, adds
-  // classifications to |original_class| according to the logic described below,
-  // and returns the result.
-  //
-  //   - if |text_is_search_query| is false, the function adds
-  //   ACMatchClassification::MATCH markers for all such instances.
-  //
-  //   For example, given the |text|
-  //   "Sports and News at sports.somesite.com - visit us!" and |original_class|
-  //   {{0, NONE}, {18, URL}, {37, NONE}} (marking "sports.somesite.com" as a
-  //   URL), calling with |find_text| set to "sp ew" would return
-  //   {{0, MATCH}, {2, NONE}, {12, MATCH}, {14, NONE}, {18, URL|MATCH},
-  //   {20, URL}, {37, NONE}}.
-  //
-  //
-  //   - if |text_is_search_query| is true, applies the same logic, but uses
-  //   NONE for the matching text and MATCH for the non-matching text. This is
-  //   done to mimic the behavior of SearchProvider which decorates matches
-  //   according to the approach used by Google Suggest.
-  //
-  //   For example, given that |text| corresponds to a search query "panama
-  //   canal" and |original class| is {{0, NONE}}, calling with |find_text| set
-  //   to "canal" would return {{0,MATCH}, {7, NONE}}.
-  //
-  // |find_text| is provided as the original string used to create
-  // |find_words|.  This is supplied because it's common for this to be a prefix
-  // of |text|, so we can quickly check for that and mark that entire substring
-  // as a match before proceeding with the more generic algorithm.
-  //
-  // |find_words| should be as constructed by CreateWordMapForString(find_text).
-  //
-  // |find_text| (and thus |find_words|) are expected to be lowercase.  |text|
-  // will be lowercased in this function.
-  static ACMatchClassifications ClassifyAllMatchesInString(
-      const base::string16& find_text,
-      const WordMap& find_words,
-      const base::string16& text,
-      const bool text_is_search_query,
-      const ACMatchClassifications& original_class);
-
   // ShortcutsBackendObserver:
   void OnShortcutsLoaded() override;
 
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc
index 865ada6..b08fda7 100644
--- a/components/omnibox/browser/shortcuts_provider_unittest.cc
+++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -163,38 +163,6 @@
 
 }  // namespace
 
-// ClassifyTest ---------------------------------------------------------------
-
-// Helper class to make running tests of ClassifyAllMatchesInString() more
-// convenient.
-class ClassifyTest {
- public:
-  ClassifyTest(const base::string16& text,
-               const bool text_is_query,
-               ACMatchClassifications matches);
-  ~ClassifyTest();
-
-  ACMatchClassifications RunTest(const base::string16& find_text);
-
- private:
-  const base::string16 text_;
-  const bool text_is_query_;
-  const ACMatchClassifications matches_;
-};
-
-ClassifyTest::ClassifyTest(const base::string16& text,
-                           const bool text_is_query,
-                           ACMatchClassifications matches)
-    : text_(text), text_is_query_(text_is_query), matches_(matches) {}
-
-ClassifyTest::~ClassifyTest() {}
-
-ACMatchClassifications ClassifyTest::RunTest(const base::string16& find_text) {
-  return ShortcutsProvider::ClassifyAllMatchesInString(
-      find_text, ShortcutsProvider::CreateWordMapForString(find_text), text_,
-      text_is_query_, matches_);
-}
-
 // ShortcutsProviderTest ------------------------------------------------------
 
 class ShortcutsProviderTest : public testing::Test {
@@ -464,122 +432,6 @@
                            base::string16());
 }
 
-TEST_F(ShortcutsProviderTest, ClassifyAllMatchesInString) {
-  ACMatchClassifications matches =
-      AutocompleteMatch::ClassificationsFromString("0,0");
-  ClassifyTest classify_test(ASCIIToUTF16("A man, a plan, a canal Panama"),
-                             /*text_is_query=*/false, matches);
-
-  ACMatchClassifications spans_a = classify_test.RunTest(ASCIIToUTF16("man"));
-  // ACMatch spans should be: '--MMM------------------------'
-  EXPECT_EQ("0,0,2,2,5,0", AutocompleteMatch::ClassificationsToString(spans_a));
-
-  ACMatchClassifications spans_b = classify_test.RunTest(ASCIIToUTF16("man p"));
-  // ACMatch spans should be: '--MMM----M-------------M-----'
-  EXPECT_EQ("0,0,2,2,5,0,9,2,10,0,23,2,24,0",
-            AutocompleteMatch::ClassificationsToString(spans_b));
-
-  ACMatchClassifications spans_c =
-      classify_test.RunTest(ASCIIToUTF16("man plan panama"));
-  // ACMatch spans should be:'--MMM----MMMM----------MMMMMM'
-  EXPECT_EQ("0,0,2,2,5,0,9,2,13,0,23,2",
-            AutocompleteMatch::ClassificationsToString(spans_c));
-
-  ClassifyTest classify_test2(
-      ASCIIToUTF16("Yahoo! Sports - Sports News, "
-                   "Scores, Rumors, Fantasy Games, and more"),
-      /*text_is_query=*/false, matches);
-
-  ACMatchClassifications spans_d = classify_test2.RunTest(ASCIIToUTF16("ne"));
-  // ACMatch spans should match first two letters of the "news".
-  EXPECT_EQ("0,0,23,2,25,0",
-            AutocompleteMatch::ClassificationsToString(spans_d));
-
-  ACMatchClassifications spans_e =
-      classify_test2.RunTest(ASCIIToUTF16("news r"));
-  EXPECT_EQ(
-      "0,0,10,2,11,0,19,2,20,0,23,2,27,0,32,2,33,0,37,2,38,0,41,2,42,0,"
-      "66,2,67,0",
-      AutocompleteMatch::ClassificationsToString(spans_e));
-
-  matches = AutocompleteMatch::ClassificationsFromString("0,1");
-  ClassifyTest classify_test3(ASCIIToUTF16("livescore.goal.com"),
-                              /*text_is_query=*/false, matches);
-
-  ACMatchClassifications spans_f = classify_test3.RunTest(ASCIIToUTF16("go"));
-  // ACMatch spans should match first two letters of the "goal".
-  EXPECT_EQ("0,1,10,3,12,1",
-            AutocompleteMatch::ClassificationsToString(spans_f));
-
-  matches = AutocompleteMatch::ClassificationsFromString("0,0,13,1");
-  ClassifyTest classify_test4(ASCIIToUTF16("Email login: mail.somecorp.com"),
-                              /*text_is_query=*/false, matches);
-
-  ACMatchClassifications spans_g = classify_test4.RunTest(ASCIIToUTF16("ail"));
-  EXPECT_EQ("0,0,2,2,5,0,13,1,14,3,17,1",
-            AutocompleteMatch::ClassificationsToString(spans_g));
-
-  ACMatchClassifications spans_h =
-      classify_test4.RunTest(ASCIIToUTF16("lo log"));
-  EXPECT_EQ("0,0,6,2,9,0,13,1",
-            AutocompleteMatch::ClassificationsToString(spans_h));
-
-  ACMatchClassifications spans_i =
-      classify_test4.RunTest(ASCIIToUTF16("ail em"));
-  // 'Email' and 'ail' should be matched.
-  EXPECT_EQ("0,2,5,0,13,1,14,3,17,1",
-            AutocompleteMatch::ClassificationsToString(spans_i));
-
-  // Some web sites do not have a description.  If the string being searched is
-  // empty, the classifications must also be empty: http://crbug.com/148647
-  // Extra parens in the next line hack around C++03's "most vexing parse".
-  class ClassifyTest classify_test5((base::string16()), /*text_is_query=*/false,
-                                    ACMatchClassifications());
-  ACMatchClassifications spans_j = classify_test5.RunTest(ASCIIToUTF16("man"));
-  ASSERT_EQ(0U, spans_j.size());
-
-  // Matches which end at beginning of classification merge properly.
-  matches = AutocompleteMatch::ClassificationsFromString("0,4,9,0");
-  ClassifyTest classify_test6(ASCIIToUTF16("html password example"),
-                              /*text_is_query=*/false, matches);
-
-  // Extra space in the next string avoids having the string be a prefix of the
-  // text above, which would allow for two different valid classification sets,
-  // one of which uses two spans (the first of which would mark all of "html
-  // pass" as a match) and one which uses four (which marks the individual words
-  // as matches but not the space between them).  This way only the latter is
-  // valid.
-  ACMatchClassifications spans_k =
-      classify_test6.RunTest(ASCIIToUTF16("html  pass"));
-  EXPECT_EQ("0,6,4,4,5,6,9,0",
-            AutocompleteMatch::ClassificationsToString(spans_k));
-
-  // Multiple matches with both beginning and end at beginning of
-  // classifications merge properly.
-  matches = AutocompleteMatch::ClassificationsFromString("0,1,11,0");
-  ClassifyTest classify_test7(ASCIIToUTF16("http://a.co is great"),
-                              /*text_is_query=*/false, matches);
-
-  ACMatchClassifications spans_l =
-      classify_test7.RunTest(ASCIIToUTF16("ht co"));
-  EXPECT_EQ("0,3,2,1,9,3,11,0",
-            AutocompleteMatch::ClassificationsToString(spans_l));
-
-  // Queries should be classify the same way as google seach autocomplete
-  // suggestions.
-  matches = AutocompleteMatch::ClassificationsFromString("0,0");
-  ClassifyTest classify_test8(ASCIIToUTF16("panama canal"),
-                              /*text_is_query=*/true, matches);
-
-  ACMatchClassifications spans_m = classify_test8.RunTest(ASCIIToUTF16("pan"));
-  // ACMatch spans should be: "---MMMMMMMMM";
-  EXPECT_EQ("0,0,3,2", AutocompleteMatch::ClassificationsToString(spans_m));
-  ACMatchClassifications spans_n =
-      classify_test8.RunTest(ASCIIToUTF16("canal"));
-  // ACMatch spans should be: "MMMMMM-----";
-  EXPECT_EQ("0,2,7,0", AutocompleteMatch::ClassificationsToString(spans_n));
-}
-
 TEST_F(ShortcutsProviderTest, CalculateScore) {
   ShortcutsDatabase::Shortcut shortcut(
       std::string(), ASCIIToUTF16("test"),
diff --git a/components/search/BUILD.gn b/components/search/BUILD.gn
index d6d3db31..b3896ba 100644
--- a/components/search/BUILD.gn
+++ b/components/search/BUILD.gn
@@ -14,19 +14,6 @@
     "//components/search_engines",
     "//url",
   ]
-
-  if (!is_ios && !is_android) {
-    sources += [
-      "url_validity_checker.h",
-      "url_validity_checker_impl.cc",
-      "url_validity_checker_impl.h",
-    ]
-
-    deps += [
-      "//net",
-      "//services/network/public/cpp",
-    ]
-  }
 }
 
 source_set("unit_tests") {
@@ -41,15 +28,4 @@
     "//components/variations",
     "//testing/gtest",
   ]
-
-  if (!is_ios && !is_android) {
-    sources += [ "url_validity_checker_impl_unittest.cc" ]
-
-    deps += [
-      "//net",
-      "//net:test_support",
-      "//services/network:test_support",
-      "//testing/gmock",
-    ]
-  }
 }
diff --git a/components/search/DEPS b/components/search/DEPS
index 8402eab..d9bc813 100644
--- a/components/search/DEPS
+++ b/components/search/DEPS
@@ -2,7 +2,4 @@
   "+components/google/core",
   "+components/search_engines",
   "+components/variations",
-  "+net",
-  "+services/network/public/cpp",
-  "+services/network/test",
 ]
diff --git a/components/search/url_validity_checker.h b/components/search/url_validity_checker.h
deleted file mode 100644
index 7560e81..0000000
--- a/components/search/url_validity_checker.h
+++ /dev/null
@@ -1,31 +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.
-
-#ifndef COMPONENTS_SEARCH_URL_VALIDITY_CHECKER_H_
-#define COMPONENTS_SEARCH_URL_VALIDITY_CHECKER_H_
-
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "url/gurl.h"
-
-// A standalone service that validates if the provided URL is able to resolve to
-// a valid page.
-class UrlValidityChecker {
- public:
-  // The callback invoked when the request completes. Returns true if the
-  // response was |valid| and the request |duration|.
-  using UrlValidityCheckerCallback =
-      base::OnceCallback<void(bool valid, base::TimeDelta duration)>;
-
-  virtual ~UrlValidityChecker() = default;
-
-  // Creates a HEAD request to check if |url| resolves to an existing page.
-  // Returns true if the URL resolves and the request duration. Redirects (3xx)
-  // and 2xx response codes are considered as resolving.
-  virtual void DoesUrlResolve(
-      const GURL& url,
-      net::NetworkTrafficAnnotationTag traffic_annotation,
-      UrlValidityCheckerCallback callback) = 0;
-};
-
-#endif  // COMPONENTS_SEARCH_URL_VALIDITY_CHECKER_H_
diff --git a/components/search/url_validity_checker_impl.cc b/components/search/url_validity_checker_impl.cc
deleted file mode 100644
index 697eb5e..0000000
--- a/components/search/url_validity_checker_impl.cc
+++ /dev/null
@@ -1,102 +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.
-
-#include "components/search/url_validity_checker_impl.h"
-
-#include "base/bind.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_status_code.h"
-
-namespace {
-
-// Request timeout duration.
-constexpr base::TimeDelta kRequestTimeout = base::TimeDelta::FromSeconds(10);
-
-}  // namespace
-
-// Stores the pending request and associated metadata. Deleted once the request
-// finishes.
-struct UrlValidityCheckerImpl::PendingRequest {
-  PendingRequest(const GURL& url,
-                 const base::TimeTicks& time_created,
-                 const base::TickClock* clock,
-                 UrlValidityCheckerCallback callback)
-      : url(url),
-        time_created(time_created),
-        timeout_timer(clock),
-        callback(std::move(callback)) {}
-
-  GURL url;
-  base::TimeTicks time_created;
-  base::OneShotTimer timeout_timer;
-  UrlValidityCheckerCallback callback;
-  std::unique_ptr<network::SimpleURLLoader> loader;
-
-  DISALLOW_COPY_AND_ASSIGN(PendingRequest);
-};
-
-UrlValidityCheckerImpl::UrlValidityCheckerImpl(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    const base::TickClock* tick_clock)
-    : url_loader_factory_(std::move(url_loader_factory)), clock_(tick_clock) {}
-
-UrlValidityCheckerImpl::~UrlValidityCheckerImpl() = default;
-
-void UrlValidityCheckerImpl::DoesUrlResolve(
-    const GURL& url,
-    net::NetworkTrafficAnnotationTag traffic_annotation,
-    UrlValidityCheckerCallback callback) {
-  auto resource_request = std::make_unique<network::ResourceRequest>();
-  resource_request->url = url;
-  resource_request->method = "HEAD";
-  resource_request->allow_credentials = false;
-
-  auto request_iter = pending_requests_.emplace(pending_requests_.begin(), url,
-                                                clock_->NowTicks(), clock_,
-                                                std::move(callback));
-  request_iter->loader = network::SimpleURLLoader::Create(
-      std::move(resource_request), traffic_annotation);
-  // Don't follow redirects to prevent leaking URL data to HTTP sites.
-  request_iter->loader->SetOnRedirectCallback(
-      base::BindRepeating(&UrlValidityCheckerImpl::OnSimpleLoaderRedirect,
-                          weak_ptr_factory_.GetWeakPtr(), request_iter));
-  request_iter->loader->DownloadToString(
-      url_loader_factory_.get(),
-      base::BindOnce(&UrlValidityCheckerImpl::OnSimpleLoaderComplete,
-                     weak_ptr_factory_.GetWeakPtr(), request_iter),
-      /*max_body_size=*/1);
-  request_iter->timeout_timer.Start(
-      FROM_HERE, kRequestTimeout,
-      base::BindOnce(&UrlValidityCheckerImpl::OnSimpleLoaderHandler,
-                     weak_ptr_factory_.GetWeakPtr(), request_iter, false));
-}
-
-void UrlValidityCheckerImpl::OnSimpleLoaderRedirect(
-    std::list<PendingRequest>::iterator request_iter,
-    const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
-    std::vector<std::string>* to_be_removed_headers) {
-  // Assume the URL is valid if a redirect is returned.
-  OnSimpleLoaderHandler(request_iter, true);
-}
-
-void UrlValidityCheckerImpl::OnSimpleLoaderComplete(
-    std::list<PendingRequest>::iterator request_iter,
-    std::unique_ptr<std::string> response_body) {
-  // |response_body| is null for non-2xx responses.
-  OnSimpleLoaderHandler(request_iter, response_body.get() != nullptr);
-}
-
-void UrlValidityCheckerImpl::OnSimpleLoaderHandler(
-    std::list<PendingRequest>::iterator request_iter,
-    bool valid) {
-  base::TimeDelta elapsed_time =
-      clock_->NowTicks() - request_iter->time_created;
-  std::move(request_iter->callback).Run(valid, elapsed_time);
-  pending_requests_.erase(request_iter);
-}
diff --git a/components/search/url_validity_checker_impl.h b/components/search/url_validity_checker_impl.h
deleted file mode 100644
index d4996e5c..0000000
--- a/components/search/url_validity_checker_impl.h
+++ /dev/null
@@ -1,74 +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.
-
-#ifndef COMPONENTS_SEARCH_URL_VALIDITY_CHECKER_IMPL_H_
-#define COMPONENTS_SEARCH_URL_VALIDITY_CHECKER_IMPL_H_
-
-#include <list>
-#include <vector>
-
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
-#include "components/search/url_validity_checker.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/cpp/simple_url_loader.h"
-
-namespace base {
-class TickClock;
-}  // namespace base
-
-namespace net {
-struct RedirectInfo;
-}  // namespace net
-
-namespace network {
-struct ResourceResponseHead;
-class SharedURLLoaderFactory;
-}  // namespace network
-
-class UrlValidityCheckerImpl : public UrlValidityChecker {
- public:
-  UrlValidityCheckerImpl(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      const base::TickClock* tick_clock);
-  ~UrlValidityCheckerImpl() override;
-
-  void DoesUrlResolve(const GURL& url,
-                      net::NetworkTrafficAnnotationTag traffic_annotation,
-                      UrlValidityCheckerCallback callback) override;
-
- private:
-  struct PendingRequest;
-
-  // Called when the request times out. Calls back false and returns the request
-  // duration.
-  void OnRequestTimeout(std::list<PendingRequest>::iterator request_iter);
-
-  void OnSimpleLoaderRedirect(
-      std::list<PendingRequest>::iterator request_iter,
-      const net::RedirectInfo& redirect_info,
-      const network::ResourceResponseHead& response_head,
-      std::vector<std::string>* to_be_removed_headers);
-  void OnSimpleLoaderComplete(std::list<PendingRequest>::iterator request_iter,
-                              std::unique_ptr<std::string> response_body);
-  // Called when the request from |DoesUrlResolve| finishes. Invokes the
-  // associated callback with the request status and duration.
-  void OnSimpleLoaderHandler(std::list<PendingRequest>::iterator request_iter,
-                             bool valid);
-
-  // Stores any ongoing network requests. Once a request is completed, it is
-  // deleted from the list.
-  std::list<PendingRequest> pending_requests_;
-  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
-  // Non-owned pointer to TickClock. Used for request timeouts.
-  const base::TickClock* const clock_;
-
-  base::WeakPtrFactory<UrlValidityCheckerImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(UrlValidityCheckerImpl);
-};
-
-#endif  // COMPONENTS_SEARCH_URL_VALIDITY_CHECKER_IMPL_H_
diff --git a/components/search/url_validity_checker_impl_unittest.cc b/components/search/url_validity_checker_impl_unittest.cc
deleted file mode 100644
index b300abf..0000000
--- a/components/search/url_validity_checker_impl_unittest.cc
+++ /dev/null
@@ -1,150 +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.
-
-#include "components/search/url_validity_checker_impl.h"
-
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using ::testing::_;
-
-class UrlValidityCheckerImplTest : public testing::Test {
- protected:
-  UrlValidityCheckerImplTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        test_shared_loader_factory_(
-            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-                &test_url_loader_factory_)),
-        url_checker_(test_shared_loader_factory_,
-                     scoped_task_environment_.GetMockTickClock()) {}
-
-  ~UrlValidityCheckerImplTest() override {}
-
-  void SetUp() override {
-    test_shared_loader_factory_ =
-        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-            url_loader_factory());
-  }
-
-  UrlValidityCheckerImpl* url_checker() { return &url_checker_; }
-
-  network::TestURLLoaderFactory* url_loader_factory() {
-    return &test_url_loader_factory_;
-  }
-
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
- private:
-  network::TestURLLoaderFactory test_url_loader_factory_;
-  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
-
-  UrlValidityCheckerImpl url_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(UrlValidityCheckerImplTest);
-};
-
-TEST_F(UrlValidityCheckerImplTest, DoesUrlResolve_OnSuccess) {
-  const GURL kUrl("https://www.foo.com");
-  const int kTimeAdvance = 10;
-  base::TimeDelta expected_duration =
-      base::TimeDelta::FromSeconds(kTimeAdvance);
-
-  network::ResourceResponseHead response;
-  response.headers = new net::HttpResponseHeaders(
-      "HTTP/1.1 200 OK\nContent-type: text/html\n\n");
-  url_loader_factory()->SetInterceptor(
-      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
-        scoped_task_environment_.FastForwardBy(expected_duration);
-        url_loader_factory()->AddResponse(
-            request.url, response, std::string(),
-            network::URLLoaderCompletionStatus(net::OK));
-      }));
-  base::MockCallback<UrlValidityChecker::UrlValidityCheckerCallback>
-      callback_ok;
-  EXPECT_CALL(callback_ok, Run(true, expected_duration));
-
-  url_checker()->DoesUrlResolve(kUrl, TRAFFIC_ANNOTATION_FOR_TESTS,
-                                callback_ok.Get());
-  scoped_task_environment_.RunUntilIdle();
-
-  response.headers =
-      new net::HttpResponseHeaders("HTTP/1.1 204 No Content\r\n\r\n");
-  base::MockCallback<UrlValidityChecker::UrlValidityCheckerCallback>
-      callback_no_content;
-  EXPECT_CALL(callback_no_content, Run(true, expected_duration));
-
-  url_checker()->DoesUrlResolve(kUrl, TRAFFIC_ANNOTATION_FOR_TESTS,
-                                callback_no_content.Get());
-  scoped_task_environment_.RunUntilIdle();
-}
-
-TEST_F(UrlValidityCheckerImplTest, DoesUrlResolve_OnFailure) {
-  const GURL kUrl("https://www.foo.com");
-  const int kTimeAdvance = 20;
-  base::TimeDelta expected_duration =
-      base::TimeDelta::FromSeconds(kTimeAdvance);
-
-  url_loader_factory()->SetInterceptor(
-      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
-        scoped_task_environment_.FastForwardBy(expected_duration);
-        url_loader_factory()->AddResponse(
-            request.url, network::ResourceResponseHead(), std::string(),
-            network::URLLoaderCompletionStatus(net::ERR_FAILED));
-      }));
-  base::MockCallback<UrlValidityChecker::UrlValidityCheckerCallback> callback;
-  EXPECT_CALL(callback, Run(false, expected_duration));
-
-  url_checker()->DoesUrlResolve(kUrl, TRAFFIC_ANNOTATION_FOR_TESTS,
-                                callback.Get());
-  scoped_task_environment_.RunUntilIdle();
-}
-
-TEST_F(UrlValidityCheckerImplTest, DoesUrlResolve_OnRedirect) {
-  const GURL kUrl("https://www.foo.com");
-  const GURL kRedirectUrl("https://www.foo2.com");
-  const int kTimeAdvance = 30;
-  base::TimeDelta expected_duration =
-      base::TimeDelta::FromSeconds(kTimeAdvance);
-
-  net::RedirectInfo redirect_info;
-  redirect_info.status_code = 301;
-  redirect_info.new_url = kRedirectUrl;
-  network::TestURLLoaderFactory::Redirects redirects{
-      {redirect_info, network::ResourceResponseHead()}};
-  url_loader_factory()->SetInterceptor(
-      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
-        scoped_task_environment_.FastForwardBy(expected_duration);
-        url_loader_factory()->AddResponse(
-            request.url, network::ResourceResponseHead(), std::string(),
-            network::URLLoaderCompletionStatus(), redirects);
-      }));
-  base::MockCallback<UrlValidityChecker::UrlValidityCheckerCallback> callback;
-  EXPECT_CALL(callback, Run(true, expected_duration));
-
-  url_checker()->DoesUrlResolve(kUrl, TRAFFIC_ANNOTATION_FOR_TESTS,
-                                callback.Get());
-  scoped_task_environment_.RunUntilIdle();
-}
-
-TEST_F(UrlValidityCheckerImplTest, DoesUrlResolve_OnTimeout) {
-  const GURL kUrl("https://www.foo.com");
-
-  base::MockCallback<UrlValidityChecker::UrlValidityCheckerCallback> callback;
-  EXPECT_CALL(callback, Run(false, _));
-
-  url_checker()->DoesUrlResolve(kUrl, TRAFFIC_ANNOTATION_FOR_TESTS,
-                                callback.Get());
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(20));
-  scoped_task_environment_.RunUntilIdle();
-}
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
index 268042f..5c6d895 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
@@ -23,7 +23,7 @@
   auto value = std::make_unique<base::trace_event::TracedValue>();
   value->SetInteger("request_id", request_id);
   value->SetInteger("threat_type", threat_type);
-  value->SetValue("threat_metadata", *threat_metadata.ToTracedValue());
+  value->SetValue("threat_metadata", threat_metadata.ToTracedValue().get());
   value->SetInteger("check_time (us)", check_time.InMicroseconds());
   value->SetBoolean("finished", finished);
   return value;
diff --git a/components/subresource_filter/core/browser/subresource_filter_features.cc b/components/subresource_filter/core/browser/subresource_filter_features.cc
index bedf9d1..312112aa 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features.cc
+++ b/components/subresource_filter/core/browser/subresource_filter_features.cc
@@ -342,7 +342,7 @@
     const {
   auto value = std::make_unique<base::trace_event::TracedValue>();
   auto traced_conditions = activation_conditions.ToTracedValue();
-  value->SetValue("activation_conditions", *traced_conditions);
+  value->SetValue("activation_conditions", traced_conditions.get());
   value->SetString("activation_level",
                    StreamToString(activation_options.activation_level));
   value->SetDouble("performance_measurement_rate",
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
index 2cd784c..4a5389fa 100644
--- a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
@@ -14,7 +14,7 @@
 namespace {
 
 const char kModelTypeEntityChangeHistogramPrefix[] =
-    "Sync.ModelTypeEntityChange2.";
+    "Sync.ModelTypeEntityChange3.";
 
 // Values corrospond to a UMA histogram, do not modify, or delete any values.
 // Add new values only directly before COUNT.
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc b/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc
index fc25eec..a81ec0be1 100644
--- a/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc
@@ -22,13 +22,13 @@
   base::HistogramTester histogram_tester;
   emitter.EmitCommitCountersUpdate();
   EXPECT_EQ(
-      3, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      3, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*LOCAL_DELETION=*/0));
   EXPECT_EQ(
-      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*LOCAL_CREATION=*/1));
   EXPECT_EQ(1, histogram_tester.GetBucketCount(
-                   "Sync.ModelTypeEntityChange2.BOOKMARK", /*LOCAL_UPDATE=*/2));
+                   "Sync.ModelTypeEntityChange3.BOOKMARK", /*LOCAL_UPDATE=*/2));
 }
 
 TEST(DataTypeDebugInfoEmitterTest, ShouldNotEmitCommitsToUMAIfNotChanged) {
@@ -37,7 +37,7 @@
 
   base::HistogramTester histogram_tester;
   emitter.EmitCommitCountersUpdate();
-  histogram_tester.ExpectTotalCount("Sync.ModelTypeEntityChange2.BOOKMARK", 0);
+  histogram_tester.ExpectTotalCount("Sync.ModelTypeEntityChange3.BOOKMARK", 0);
 }
 
 // Tests that at each EmitCommitCountersUpdate() call, only the changes since
@@ -63,13 +63,13 @@
   base::HistogramTester histogram_tester;
   emitter.EmitCommitCountersUpdate();
   EXPECT_EQ(
-      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*LOCAL_DELETION=*/0));
   EXPECT_EQ(
-      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*LOCAL_CREATION=*/1));
   EXPECT_EQ(3, histogram_tester.GetBucketCount(
-                   "Sync.ModelTypeEntityChange2.BOOKMARK", /*LOCAL_UPDATE=*/2));
+                   "Sync.ModelTypeEntityChange3.BOOKMARK", /*LOCAL_UPDATE=*/2));
 }
 
 TEST(DataTypeDebugInfoEmitterTest, ShouldEmitUpdatesToUMAIfChanged) {
@@ -84,13 +84,13 @@
   base::HistogramTester histogram_tester;
   emitter.EmitUpdateCountersUpdate();
   EXPECT_EQ(
-      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*REMOTE_DELETION=*/3));
   EXPECT_EQ(
-      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*REMOTE_NON_INITIAL_UPDATE=*/4));
   EXPECT_EQ(
-      5, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      5, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*REMOTE_INITIAL_UPDATE=*/5));
 }
 
@@ -100,7 +100,7 @@
 
   base::HistogramTester histogram_tester;
   emitter.EmitUpdateCountersUpdate();
-  histogram_tester.ExpectTotalCount("Sync.ModelTypeEntityChange2.BOOKMARK", 0);
+  histogram_tester.ExpectTotalCount("Sync.ModelTypeEntityChange3.BOOKMARK", 0);
 }
 
 // Tests that at each EmitUpdateCountersUpdate() call, only the changes since
@@ -126,13 +126,13 @@
   base::HistogramTester histogram_tester;
   emitter.EmitUpdateCountersUpdate();
   EXPECT_EQ(
-      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*REMOTE_DELETION=*/3));
   EXPECT_EQ(
-      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*REMOTE_NON_INITIAL_UPDATE=*/4));
   EXPECT_EQ(
-      4, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange2.BOOKMARK",
+      4, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
                                          /*REMOTE_INITIAL_UPDATE=*/5));
 }
 
diff --git a/components/sync/engine_impl/directory_update_handler.cc b/components/sync/engine_impl/directory_update_handler.cc
index 1a81d06..2f917610 100644
--- a/components/sync/engine_impl/directory_update_handler.cc
+++ b/components/sync/engine_impl/directory_update_handler.cc
@@ -87,9 +87,10 @@
     CreateTypeRoot(&trans);
   }
 
-  UpdateSyncEntities(&trans, applicable_updates,
-                     /*is_initial_sync=*/dir_->HasEmptyDownloadProgress(type_),
-                     status);
+  UpdateSyncEntities(
+      &trans, applicable_updates,
+      /*is_initial_sync=*/!dir_->InitialSyncEndedForType(&trans, type_),
+      status);
 
   if (IsValidProgressMarker(progress_marker)) {
     ExpireEntriesIfNeeded(&trans, progress_marker);
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc
index 59af9f6..eb4108d9 100644
--- a/components/sync/engine_impl/loopback_server/loopback_server.cc
+++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -75,21 +75,23 @@
   }
 
   // Determines whether the server should send an |entity| to the client as
-  // part of a GetUpdatesResponse. Update internal tracking of max versions as a
-  // side effect which will later be used to set response progress markers.
-  bool ClientWantsItem(const LoopbackServerEntity& entity) {
+  // part of a GetUpdatesResponse.
+  bool ClientWantsItem(const LoopbackServerEntity& entity) const {
     ModelType type = entity.GetModelType();
-    // Return only requested datatypes, which makes sure we don't add new
-    // entries to |response_version_map_|, which would otherwise send
-    // unnecessary (and unrequested) progress markers in the response.
     auto it = request_version_map_.find(type);
     if (it == request_version_map_.end())
       return false;
-    DCHECK_NE(0U, request_version_map_.count(type));
-    int64_t version = entity.GetVersion();
+    DCHECK_NE(0U, response_version_map_.count(type));
+    return it->second < entity.GetVersion();
+  }
+
+  // Updates internal tracking of max versions to later be used to set response
+  // progress markers.
+  void UpdateProgressMarker(const LoopbackServerEntity& entity) {
+    DCHECK(ClientWantsItem(entity));
+    ModelType type = entity.GetModelType();
     response_version_map_[type] =
-        std::max(response_version_map_[type], version);
-    return it->second < version;
+        std::max(response_version_map_[type], entity.GetVersion());
   }
 
  private:
@@ -136,6 +138,11 @@
   ModelTypeToVersionMap response_version_map_;
 };
 
+bool SortByVersion(const LoopbackServerEntity* lhs,
+                   const LoopbackServerEntity* rhs) {
+  return lhs->GetVersion() < rhs->GetVersion();
+}
+
 }  // namespace
 
 LoopbackServer::LoopbackServer(const base::FilePath& persistent_file)
@@ -296,8 +303,6 @@
 bool LoopbackServer::HandleGetUpdatesRequest(
     const sync_pb::GetUpdatesMessage& get_updates,
     sync_pb::GetUpdatesResponse* response) {
-  // TODO(pvalenzuela): Implement batching instead of sending all information
-  // at once.
   response->set_changes_remaining(0);
 
   auto sieve = std::make_unique<UpdateSieve>(get_updates);
@@ -310,18 +315,36 @@
     return false;
   }
 
-  bool send_encryption_keys_based_on_nigori = false;
-  for (const auto& kv : entities_) {
-    const LoopbackServerEntity& entity = *kv.second;
-    if (sieve->ClientWantsItem(entity)) {
-      sync_pb::SyncEntity* response_entity = response->add_entries();
-      entity.SerializeAsProto(response_entity);
+  std::vector<const LoopbackServerEntity*> wanted_entities;
+  for (const auto& id_and_entity : entities_) {
+    if (sieve->ClientWantsItem(*id_and_entity.second)) {
+      wanted_entities.push_back(id_and_entity.second.get());
+    }
+  }
 
-      if (entity.GetModelType() == syncer::NIGORI) {
-        send_encryption_keys_based_on_nigori =
-            response_entity->specifics().nigori().passphrase_type() ==
-            sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
-      }
+  int max_batch_size = max_get_updates_batch_size_;
+  if (get_updates.batch_size() > 0)
+    max_batch_size = std::min(max_batch_size, get_updates.batch_size());
+
+  if (static_cast<int>(wanted_entities.size()) > max_batch_size) {
+    response->set_changes_remaining(wanted_entities.size() - max_batch_size);
+    std::partial_sort(wanted_entities.begin(),
+                      wanted_entities.begin() + max_batch_size,
+                      wanted_entities.end(), SortByVersion);
+    wanted_entities.resize(max_batch_size);
+  }
+
+  bool send_encryption_keys_based_on_nigori = false;
+  for (const LoopbackServerEntity* entity : wanted_entities) {
+    sieve->UpdateProgressMarker(*entity);
+
+    sync_pb::SyncEntity* response_entity = response->add_entries();
+    entity->SerializeAsProto(response_entity);
+
+    if (entity->GetModelType() == syncer::NIGORI) {
+      send_encryption_keys_based_on_nigori =
+          response_entity->specifics().nigori().passphrase_type() ==
+          sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
     }
   }
 
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.h b/components/sync/engine_impl/loopback_server/loopback_server.h
index 680e9a1..de4b120 100644
--- a/components/sync/engine_impl/loopback_server/loopback_server.h
+++ b/components/sync/engine_impl/loopback_server/loopback_server.h
@@ -56,6 +56,11 @@
   // Enables strong consistency model (i.e. server detects conflicts).
   void EnableStrongConsistencyWithConflictDetectionModel();
 
+  // Sets a maximum batch size for GetUpdates requests.
+  void SetMaxGetUpdatesBatchSize(int batch_size) {
+    max_get_updates_batch_size_ = batch_size;
+  }
+
  private:
   // Allow the FakeServer decorator to inspect the internals of this class.
   friend class fake_server::FakeServer;
@@ -198,6 +203,8 @@
 
   int64_t store_birthday_;
 
+  int max_get_updates_batch_size_ = 1000000;
+
   EntityMap entities_;
   std::map<ModelType, std::string> top_level_permanent_item_ids_;
   std::vector<std::string> keystore_keys_;
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc
index e2f9c67c..18e688f 100644
--- a/components/sync/test/fake_server/fake_server.cc
+++ b/components/sync/test/fake_server/fake_server.cc
@@ -458,6 +458,11 @@
   loopback_server_->EnableStrongConsistencyWithConflictDetectionModel();
 }
 
+void FakeServer::SetMaxGetUpdatesBatchSize(int batch_size) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  loopback_server_->SetMaxGetUpdatesBatchSize(batch_size);
+}
+
 base::WeakPtr<FakeServer> FakeServer::AsWeakPtr() {
   DCHECK(thread_checker_.CalledOnValidThread());
   return weak_ptr_factory_.GetWeakPtr();
diff --git a/components/sync/test/fake_server/fake_server.h b/components/sync/test/fake_server/fake_server.h
index 6a8c2928..05e571d 100644
--- a/components/sync/test/fake_server/fake_server.h
+++ b/components/sync/test/fake_server/fake_server.h
@@ -178,6 +178,9 @@
   // Enables strong consistency model (i.e. server detects conflicts).
   void EnableStrongConsistencyWithConflictDetectionModel();
 
+  // Sets a maximum batch size for GetUpdates requests.
+  void SetMaxGetUpdatesBatchSize(int batch_size);
+
   // Implement LoopbackServer::ObserverForTests:
   void OnCommit(const std::string& committer_id,
                 syncer::ModelTypeSet committed_model_types) override;
diff --git a/components/test/data/web_database/version_80.sql b/components/test/data/web_database/version_80.sql
new file mode 100644
index 0000000..5ab83ed
--- /dev/null
+++ b/components/test/data/web_database/version_80.sql
@@ -0,0 +1,28 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('mmap_status','-1');
+INSERT INTO "meta" VALUES('version','80');
+INSERT INTO "meta" VALUES('last_compatible_version','79');
+CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE TABLE keywords (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR,alternate_urls VARCHAR,image_url VARCHAR,search_url_post_params VARCHAR,suggest_url_post_params VARCHAR,image_url_post_params VARCHAR,new_tab_url VARCHAR,last_visited INTEGER DEFAULT 0);
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, date_created INTEGER DEFAULT 0, date_last_used INTEGER DEFAULT 0, count INTEGER DEFAULT 1, PRIMARY KEY (name, value));
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, street_address VARCHAR, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, sorting_code VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', language_code VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, validity_bitfield UNSIGNED NOT NULL DEFAULT 0, is_client_validity_states_updated BOOL NOT NULL DEFAULT FALSE);
+INSERT INTO "autofill_profiles" VALUES('00000000-0000-0000-0000-000000000001','Google Inc','340 Main St','','Los Angeles','CA','90291','','US',1395948829,'Chrome settings','en',12,12,1365,true);
+CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR, full_name VARCHAR);
+CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
+CREATE TABLE autofill_profile_phones ( guid VARCHAR, number VARCHAR);
+CREATE TABLE autofill_profiles_trash ( guid VARCHAR);
+CREATE TABLE masked_credit_cards (id VARCHAR,status VARCHAR,name_on_card VARCHAR,network VARCHAR,last_four VARCHAR,exp_month INTEGER DEFAULT 0,exp_year INTEGER DEFAULT 0, bank_name VARCHAR, type INTEGER DEFAULT 0);
+CREATE TABLE unmasked_credit_cards (id VARCHAR,card_number_encrypted VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, unmask_date INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE server_card_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR);
+CREATE TABLE server_addresses (id VARCHAR,company_name VARCHAR,street_address VARCHAR,address_1 VARCHAR,address_2 VARCHAR,address_3 VARCHAR,address_4 VARCHAR,postal_code VARCHAR,sorting_code VARCHAR,country_code VARCHAR,language_code VARCHAR, recipient_name VARCHAR, phone_number VARCHAR);
+CREATE TABLE server_address_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, has_converted BOOL NOT NULL DEFAULT FALSE);
+CREATE TABLE autofill_sync_metadata (model_type INTEGER NOT NULL, storage_key VARCHAR NOT NULL, value BLOB, PRIMARY KEY (model_type, storage_key));
+INSERT INTO autofill_sync_metadata VALUES (6, 'storage_key1', 'blob1'), (7, 'storage_key2', 'blob2');
+CREATE TABLE autofill_model_type_state (model_type INTEGER NOT NULL PRIMARY KEY, value BLOB);
+INSERT INTO autofill_model_type_state VALUES (6, 'state1'), (7, 'state2');
+CREATE INDEX autofill_name ON autofill (name);
+CREATE INDEX autofill_name_value_lower ON autofill (name, value_lower);
+COMMIT;
diff --git a/components/tracing/common/native_stack_sampler_android.cc b/components/tracing/common/native_stack_sampler_android.cc
index 3ab46766..15d5b41 100644
--- a/components/tracing/common/native_stack_sampler_android.cc
+++ b/components/tracing/common/native_stack_sampler_android.cc
@@ -29,7 +29,7 @@
     unwinder_.Initialize();
   }
   const void* pcs[kMaxFrameDepth];
-  size_t depth = unwinder_.TraceStack(tid_, pcs, kMaxFrameDepth);
+  size_t depth = unwinder_.TraceStack(tid_, stack_buffer, pcs, kMaxFrameDepth);
   std::vector<base::StackSamplingProfiler::Frame> frames;
   frames.reserve(depth);
   for (size_t i = 0; i < depth; ++i) {
diff --git a/components/tracing/common/stack_unwinder_android.cc b/components/tracing/common/stack_unwinder_android.cc
index 637911e..a1cdd9ca2 100644
--- a/components/tracing/common/stack_unwinder_android.cc
+++ b/components/tracing/common/stack_unwinder_android.cc
@@ -12,7 +12,6 @@
 #include "link.h"
 
 #include <algorithm>
-#include <memory>
 
 #include "base/android/jni_generator/jni_generator_helper.h"
 #include "base/debug/proc_maps_linux.h"
@@ -171,8 +170,6 @@
       pc - CFIBacktraceAndroid::executable_start_addr(), cfi);
 }
 
-constexpr size_t kMaxStackBytesCopied = 1024 * 1024;
-
 // Struct to store the arguments to the signal handler.
 struct HandlerParams {
   const tracing::StackUnwinderAndroid* unwinder;
@@ -186,8 +183,8 @@
   unw_context_t* context;
   // The value of Stack pointer of the thread.
   uintptr_t* sp;
-  // The address where the full stack is copied to.
-  char* stack_copy_buffer;
+  // Buffer to copy the stack segment.
+  base::NativeStackSampler::StackBuffer* stack_buffer;
   size_t* stack_size;
 };
 
@@ -219,9 +216,10 @@
 
   uintptr_t stack_base_addr = params->unwinder->GetEndAddressOfRegion(sp);
   *params->stack_size = stack_base_addr - sp;
-  if (stack_base_addr == 0 || *params->stack_size > kMaxStackBytesCopied)
+  if (stack_base_addr == 0 ||
+      *params->stack_size > params->stack_buffer->size())
     return;
-  memcpy(params->stack_copy_buffer, reinterpret_cast<void*>(sp),
+  memcpy(params->stack_buffer->buffer(), reinterpret_cast<void*>(sp),
          *params->stack_size);
   *params->success = true;
 }
@@ -303,22 +301,22 @@
       /* stack_segment_base=*/0, JniMarkers(), out_trace, max_depth);
 }
 
-size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid,
-                                        const void** out_trace,
-                                        size_t max_depth) const {
+size_t StackUnwinderAndroid::TraceStack(
+    base::PlatformThreadId tid,
+    base::NativeStackSampler::StackBuffer* stack_buffer,
+    const void** out_trace,
+    size_t max_depth) const {
   // Stops the thread with given tid with a signal handler. The signal handler
   // copies the stack of the thread and returns. This function tries to unwind
   // stack frames from the copied stack.
   DCHECK(is_initialized_);
   AsyncSafeWaitableEvent wait_event;
   size_t stack_size;
-  std::unique_ptr<char[]> stack_copy_buffer(new char[kMaxStackBytesCopied]);
   bool copied = false;
   unw_context_t context;
   uintptr_t sp = 0;
-  HandlerParams params = {this,       &wait_event, &copied,
-                          &context,   &sp,         stack_copy_buffer.get(),
-                          &stack_size};
+  HandlerParams params = {this, &wait_event,  &copied,    &context,
+                          &sp,  stack_buffer, &stack_size};
   base::subtle::Release_Store(&g_handler_params,
                               reinterpret_cast<uintptr_t>(&params));
 
@@ -353,7 +351,7 @@
   // Context contains list of saved registers. Replace the SP and any register
   // that points to address on the previous stack to point to the copied stack.
   const uintptr_t relocation_offset =
-      reinterpret_cast<uintptr_t>(stack_copy_buffer.get()) - sp;
+      reinterpret_cast<uintptr_t>(stack_buffer->buffer()) - sp;
   bool replaced_sp = false;
   uintptr_t* register_context = reinterpret_cast<uintptr_t*>(&context);
   for (size_t i = 0; i < 16; ++i) {
@@ -364,7 +362,7 @@
   }
   DCHECK(replaced_sp);
 
-  uintptr_t* new_stack = reinterpret_cast<uintptr_t*>(stack_copy_buffer.get());
+  uintptr_t* new_stack = reinterpret_cast<uintptr_t*>(stack_buffer->buffer());
   constexpr uintptr_t marker_l =
                           jni_generator::kJniStackMarkerValue & 0xFFFFFFFF,
                       marker_r = jni_generator::kJniStackMarkerValue >> 32;
@@ -398,7 +396,7 @@
   }
   uintptr_t ip = 0;
   unw_get_reg(&cursor, UNW_REG_SP, &sp);
-  DCHECK_EQ(sp, reinterpret_cast<uintptr_t>(stack_copy_buffer.get()));
+  DCHECK_EQ(sp, reinterpret_cast<uintptr_t>(stack_buffer->buffer()));
   unw_get_reg(&cursor, UNW_REG_IP, &ip);
 
   // Unwind handler function (ThreadSignalHandler()) since libunwind cannot
@@ -427,7 +425,7 @@
 
   return TraceStackWithContext(
       &cursor, cfi_unwinder, this,
-      reinterpret_cast<uintptr_t>(stack_copy_buffer.get()) + stack_size,
+      reinterpret_cast<uintptr_t>(stack_buffer->buffer()) + stack_size,
       jni_markers, out_trace, max_depth);
 }
 
diff --git a/components/tracing/common/stack_unwinder_android.h b/components/tracing/common/stack_unwinder_android.h
index f61e6d3..b211eef 100644
--- a/components/tracing/common/stack_unwinder_android.h
+++ b/components/tracing/common/stack_unwinder_android.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "base/debug/proc_maps_linux.h"
+#include "base/profiler/native_stack_sampler.h"
 #include "base/threading/platform_thread.h"
 #include "components/tracing/tracing_export.h"
 
@@ -38,6 +39,7 @@
   // Same as above function, but pauses the thread with the given |tid| and then
   // unwinds. |tid| should not be current thread's.
   size_t TraceStack(base::PlatformThreadId tid,
+                    base::NativeStackSampler::StackBuffer* stack_buffer,
                     const void** out_trace,
                     size_t max_depth) const;
 
diff --git a/components/tracing/common/stack_unwinder_android_unittest.cc b/components/tracing/common/stack_unwinder_android_unittest.cc
index 96a107c4..6864ba6d 100644
--- a/components/tracing/common/stack_unwinder_android_unittest.cc
+++ b/components/tracing/common/stack_unwinder_android_unittest.cc
@@ -66,7 +66,10 @@
                      base::WaitableEvent* unwind_finished_event,
                      uintptr_t test_pc) {
     const void* frames[kMaxStackFrames];
-    size_t result = unwinder->TraceStack(tid, frames, kMaxStackFrames);
+    auto stack_buffer = base::NativeStackSampler::CreateStackBuffer();
+    EXPECT_GT(stack_buffer->size(), 0u);
+    size_t result =
+        unwinder->TraceStack(tid, stack_buffer.get(), frames, kMaxStackFrames);
     EXPECT_GT(result, 0u);
     for (size_t i = 0; i < result; ++i) {
       uintptr_t addr = reinterpret_cast<uintptr_t>(frames[i]);
@@ -104,7 +107,11 @@
   auto callback = [](StackUnwinderAndroid* unwinder, base::PlatformThreadId tid,
                      uintptr_t test_pc) {
     const void* frames[kMaxStackFrames];
-    size_t result = unwinder->TraceStack(tid, frames, kMaxStackFrames);
+    auto stack_buffer = base::NativeStackSampler::CreateStackBuffer();
+    EXPECT_GT(stack_buffer->size(), 0u);
+    size_t result =
+        unwinder->TraceStack(tid, stack_buffer.get(), frames, kMaxStackFrames);
+
     bool found_jni = false;
     uintptr_t jni_address =
         reinterpret_cast<uintptr_t>(&Java_UnwindTestHelper_blockCurrentThread);
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 6909569..e9e0d89 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -221,6 +221,7 @@
     "frame_sinks/delay_based_time_source_unittest.cc",
     "gl_helper_unittest.cc",
     "gl_scaler_overscan_pixeltest.cc",
+    "gl_scaler_pixeltest.cc",
     "gl_scaler_shader_pixeltest.cc",
     "gl_scaler_test_util.cc",
     "gl_scaler_test_util.h",
diff --git a/components/viz/common/DEPS b/components/viz/common/DEPS
index 639f7cb..2c8d528 100644
--- a/components/viz/common/DEPS
+++ b/components/viz/common/DEPS
@@ -22,8 +22,9 @@
     "+gpu/ipc/common",
     "+third_party/skia",
   ],
-  ".*(_unittest|_pixeltest)\.cc": [
+  ".*(_unittest|_pixeltest|test_util)\.cc": [
     "+cc/test",
+    "+components/viz/test",
     "+gpu/ipc/gl_in_process_context.h",
     "+media/base",
     "+third_party/skia/include/core",
diff --git a/components/viz/common/gl_scaler.cc b/components/viz/common/gl_scaler.cc
index df66d86..b65c2335 100644
--- a/components/viz/common/gl_scaler.cc
+++ b/components/viz/common/gl_scaler.cc
@@ -4,6 +4,8 @@
 
 #include "components/viz/common/gl_scaler.h"
 
+#include <algorithm>
+#include <array>
 #include <sstream>
 #include <string>
 
@@ -16,6 +18,30 @@
 
 namespace viz {
 
+namespace {
+
+// The code in GLScaler that computes the ScalerStages is greatly simplified by
+// being able to access the X and Y components by index (instead of
+// Vector2d::x() or Vector2d::y()). Thus, define a helper class to represent the
+// relative size as a 2-element std::array and convert to/from Vector2d.
+struct RelativeSize : public std::array<int, 2> {
+  using std::array<int, 2>::operator[];
+
+  RelativeSize(int width, int height) : std::array<int, 2>{{width, height}} {}
+  explicit RelativeSize(const gfx::Vector2d& v)
+      : std::array<int, 2>{{v.x(), v.y()}} {}
+
+  gfx::Vector2d AsVector2d() const {
+    return gfx::Vector2d((*this)[0], (*this)[1]);
+  }
+};
+
+std::ostream& operator<<(std::ostream& out, const RelativeSize& size) {
+  return (out << size[0] << 'x' << size[1]);
+}
+
+}  // namespace
+
 GLScaler::GLScaler(scoped_refptr<ContextProvider> context_provider)
     : context_provider_(std::move(context_provider)) {
   if (context_provider_) {
@@ -115,10 +141,13 @@
     }
   }
 
-  // Color space transformation is meaningless when using the deinterleaver.
+  // Color space transformation is meaningless when using the deinterleaver
+  // because it only deals with two color channels. This also means precise
+  // color management must be disabled.
   if (params_.export_format ==
           Parameters::ExportFormat::DEINTERLEAVE_PAIRWISE &&
-      params_.source_color_space != params_.output_color_space) {
+      (params_.source_color_space != params_.output_color_space ||
+       params_.enable_precise_color_management)) {
     NOTIMPLEMENTED();
     return false;
   }
@@ -131,8 +160,121 @@
     }
   }
 
-  // TODO(crbug.com/870036): Build ScalerStage chain (upcoming CL).
+  // Create the chain of ScalerStages. If the quality setting is FAST or there
+  // is no scaling to be done, just create a single stage.
+  std::unique_ptr<ScalerStage> chain;
+  if (params_.quality == Parameters::Quality::FAST ||
+      params_.scale_from == params_.scale_to) {
+    chain = std::make_unique<ScalerStage>(gl, Shader::BILINEAR, HORIZONTAL,
+                                          params_.scale_from, params_.scale_to);
+  } else if (params_.quality == Parameters::Quality::GOOD) {
+    chain = CreateAGoodScalingChain(gl, params_.scale_from, params_.scale_to);
+  } else if (params_.quality == Parameters::Quality::BEST) {
+    chain = CreateTheBestScalingChain(gl, params_.scale_from, params_.scale_to);
+  } else {
+    NOTREACHED();
+  }
+  chain = MaybeAppendExportStage(gl, std::move(chain), params_.export_format);
 
+  // Determine the color space and the data type of the pixels in the
+  // intermediate textures, depending on whether precise color management is
+  // enabled. Note that nothing special need be done here if no scaling will be
+  // performed.
+  GLenum intermediate_texture_type;
+  if (params_.enable_precise_color_management &&
+      params_.scale_from != params_.scale_to) {
+    // Ensure the scaling color space is using a linear transfer function.
+    constexpr auto kLinearFunction = std::make_tuple(1, 0, 1, 0, 0, 0, 1);
+    SkColorSpaceTransferFn fn;
+    if (params_.source_color_space.GetTransferFunction(&fn) &&
+        std::make_tuple(fn.fA, fn.fB, fn.fC, fn.fD, fn.fE, fn.fF, fn.fG) ==
+            kLinearFunction) {
+      scaling_color_space_ = params_.source_color_space;
+    } else {
+      // Use the source color space, but with a linear transfer function.
+      SkMatrix44 to_XYZD50;
+      params_.source_color_space.GetPrimaryMatrix(&to_XYZD50);
+      std::tie(fn.fA, fn.fB, fn.fC, fn.fD, fn.fE, fn.fF, fn.fG) =
+          kLinearFunction;
+      scaling_color_space_ = gfx::ColorSpace::CreateCustom(to_XYZD50, fn);
+    }
+    intermediate_texture_type = GL_HALF_FLOAT_OES;
+  } else {
+    scaling_color_space_ = params_.source_color_space;
+    intermediate_texture_type = GL_UNSIGNED_BYTE;
+  }
+
+  // Set the shader program on the final stage. Include color space
+  // transformation and swizzling, if necessary.
+  std::unique_ptr<gfx::ColorTransform> transform;
+  if (scaling_color_space_ != params_.output_color_space) {
+    transform = gfx::ColorTransform::NewColorTransform(
+        scaling_color_space_, params_.output_color_space,
+        gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
+    if (!transform->CanGetShaderSource()) {
+      NOTIMPLEMENTED() << "color transform from "
+                       << scaling_color_space_.ToString() << " to "
+                       << params_.output_color_space.ToString();
+      return false;
+    }
+  }
+  ScalerStage* const final_stage = chain.get();
+  final_stage->set_shader_program(
+      GetShaderProgram(final_stage->shader(), intermediate_texture_type,
+                       transform.get(), params_.swizzle));
+
+  // Set the shader program on all prior stages. These stages are all operating
+  // in the same color space, |scaling_color_space_|.
+  static const GLenum kNoSwizzle[2] = {GL_RGBA, GL_RGBA};
+  ScalerStage* input_stage = final_stage;
+  while (input_stage->input_stage()) {
+    input_stage = input_stage->input_stage();
+    input_stage->set_shader_program(GetShaderProgram(
+        input_stage->shader(), intermediate_texture_type, nullptr, kNoSwizzle));
+  }
+  // From this point, |input_stage| points to the first ScalerStage (i.e., the
+  // one that will be reading from the source).
+
+  // If necessary, prepend an extra "import stage" that color-converts the input
+  // before any scaling occurs. It's important not to merge color space
+  // conversion of the source with any other steps because the texture sampler
+  // must not linearly interpolate until after the colors have been mapped to a
+  // linear color space.
+  if (params_.source_color_space != scaling_color_space_) {
+    input_stage->set_input_stage(std::make_unique<ScalerStage>(
+        gl, Shader::BILINEAR, HORIZONTAL, input_stage->scale_from(),
+        input_stage->scale_from()));
+    input_stage = input_stage->input_stage();
+    transform = gfx::ColorTransform::NewColorTransform(
+        params_.source_color_space, scaling_color_space_,
+        gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
+    if (!transform->CanGetShaderSource()) {
+      NOTIMPLEMENTED() << "color transform from "
+                       << params_.source_color_space.ToString() << " to "
+                       << scaling_color_space_.ToString();
+      return false;
+    }
+    input_stage->set_shader_program(
+        GetShaderProgram(input_stage->shader(), intermediate_texture_type,
+                         transform.get(), kNoSwizzle));
+  }
+
+  // If the source content is Y-flipped, the input scaler stage will perform
+  // math to account for this. It also will flip the content during scaling so
+  // that all following stages may assume the content is not flipped. Then, the
+  // final stage must ensure the final output is correctly flipped-back (or not)
+  // based on what the first stage did PLUS what is being requested by the
+  // client code.
+  if (params_.is_flipped_source) {
+    input_stage->set_is_flipped_source(true);
+    input_stage->set_flip_output(true);
+  }
+  if (input_stage->flip_output() != params_.flip_output) {
+    final_stage->set_flip_output(!final_stage->flip_output());
+  }
+
+  chain_ = std::move(chain);
+  VLOG(2) << __func__ << " built this: " << *this;
   return true;
 }
 
@@ -244,6 +386,287 @@
 }
 
 // static
+std::unique_ptr<GLScaler::ScalerStage> GLScaler::CreateAGoodScalingChain(
+    gpu::gles2::GLES2Interface* gl,
+    const gfx::Vector2d& scale_from,
+    const gfx::Vector2d& scale_to) {
+  DCHECK(scale_from.x() != 0 && scale_from.y() != 0)
+      << "Bad scale_from: " << scale_from.ToString();
+  DCHECK(scale_to.x() != 0 && scale_to.y() != 0)
+      << "Bad scale_to: " << scale_to.ToString();
+  DCHECK(scale_from != scale_to);
+
+  // The GOOD quality chain performs one bilinear upscale followed by N bilinear
+  // halvings, and does this is both directions. Exception: No upscale is needed
+  // when |scale_from| is a power of two multiple of |scale_to|.
+  //
+  // Since all shaders use bilinear filtering, the heuristics below attempt to
+  // greedily merge steps wherever possible to minimize GPU memory usage and
+  // processing time. This also means that it will be extremely rare for the
+  // stage doing the initial upscale to actually require a larger output texture
+  // than the source texture (a downscale will be merged into the same stage).
+
+  // Determine the initial upscaled-to size, as the minimum number of doublings
+  // to make |scale_to| greater than |scale_from|.
+  const RelativeSize from(scale_from);
+  const RelativeSize to(scale_to);
+  RelativeSize upscale_to = to;
+  for (Axis x_or_y : std::array<Axis, 2>{HORIZONTAL, VERTICAL}) {
+    while (upscale_to[x_or_y] < from[x_or_y]) {
+      upscale_to[x_or_y] *= 2;
+    }
+  }
+
+  // Create the stages in order from first-to-last, taking the greediest path
+  // each time. Something like an A* algorithm would be better for discovering
+  // an optimal sequence of operations, and would allow using the BILINEAR3
+  // shader as well, but the run-time performance to compute the stages would be
+  // too prohibitive.
+  std::unique_ptr<ScalerStage> chain;
+  struct CandidateOp {
+    Shader shader;
+    Axis primary_axis;
+    RelativeSize output_size;
+  };
+  std::vector<CandidateOp> candidates;
+  for (RelativeSize cur = from; cur != to;
+       cur = RelativeSize(chain->scale_to())) {
+    candidates.clear();
+
+    // Determine whether it's possible to do exactly 2 bilinear passes in both
+    // directions.
+    RelativeSize output_size_2x2 = {0, 0};
+    for (Axis x_or_y : std::array<Axis, 2>{VERTICAL, HORIZONTAL}) {
+      if (cur[x_or_y] == from[x_or_y]) {
+        // For the first stage, the 2 bilinear passes must be the initial
+        // upscale followed by one downscale. If there is no initial upscale,
+        // then the 2 passes must both be downscales.
+        if (upscale_to[x_or_y] != from[x_or_y] &&
+            upscale_to[x_or_y] / 2 >= to[x_or_y]) {
+          output_size_2x2[x_or_y] = upscale_to[x_or_y] / 2;
+        } else if (upscale_to[x_or_y] == from[x_or_y] &&
+                   upscale_to[x_or_y] / 4 >= to[x_or_y]) {
+          output_size_2x2[x_or_y] = cur[x_or_y] / 4;
+        }
+      } else {
+        // For all later stages, the 2 bilinear passes must be 2 halvings.
+        if (cur[x_or_y] / 4 >= to[x_or_y]) {
+          output_size_2x2[x_or_y] = cur[x_or_y] / 4;
+        }
+      }
+    }
+    if (output_size_2x2[HORIZONTAL] != 0 && output_size_2x2[VERTICAL] != 0) {
+      candidates.push_back(
+          CandidateOp{Shader::BILINEAR2X2, HORIZONTAL, output_size_2x2});
+    }
+
+    // Determine the valid set of Ops that do 1 to 3 bilinear passes in one
+    // direction and 0 or 1 pass in the other direction.
+    for (Axis x_or_y : std::array<Axis, 2>{VERTICAL, HORIZONTAL}) {
+      // The first bilinear pass in x_or_y must be an upscale or a halving.
+      Shader shader = Shader::BILINEAR;
+      RelativeSize output_size = cur;
+      if (cur[x_or_y] == from[x_or_y] && upscale_to[x_or_y] != from[x_or_y]) {
+        output_size[x_or_y] = upscale_to[x_or_y];
+      } else if (cur[x_or_y] / 2 >= to[x_or_y]) {
+        output_size[x_or_y] /= 2;
+      } else {
+        DCHECK_EQ(cur[x_or_y], to[x_or_y]);
+        continue;
+      }
+
+      // Determine whether 1 or 2 additional passes can be made in the same
+      // direction.
+      if (output_size[x_or_y] / 4 >= to[x_or_y]) {
+        shader = Shader::BILINEAR4;  // 2 more passes == 3 total.
+        output_size[x_or_y] /= 4;
+      } else if (output_size[x_or_y] / 2 >= to[x_or_y]) {
+        shader = Shader::BILINEAR2;  // 1 more pass == 2 total.
+        output_size[x_or_y] /= 2;
+      } else {
+        DCHECK_EQ(output_size[x_or_y], to[x_or_y]);
+      }
+
+      // Determine whether 0 or 1 bilinear passes can be made in the other
+      // direction at the same time.
+      const Axis y_or_x = TheOtherAxis(x_or_y);
+      if (cur[y_or_x] == from[y_or_x] && upscale_to[y_or_x] != from[y_or_x]) {
+        output_size[y_or_x] = upscale_to[y_or_x];
+      } else if (cur[y_or_x] / 2 >= to[y_or_x]) {
+        output_size[y_or_x] /= 2;
+      } else {
+        DCHECK_EQ(cur[y_or_x], to[y_or_x]);
+      }
+
+      candidates.push_back(CandidateOp{shader, x_or_y, output_size});
+    }
+
+    // From the candidates, pick the one that produces the fewest number of
+    // output pixels, and append a new ScalerStage. There are opportunities to
+    // improve the "cost function" here (e.g., pixels in the Y direction
+    // probably cost more to process than pixels in the X direction), but that
+    // would require more research.
+    const auto best_candidate = std::min_element(
+        candidates.begin(), candidates.end(),
+        [](const CandidateOp& a, const CandidateOp& b) {
+          static_assert(sizeof(a.output_size[0]) <= sizeof(int32_t),
+                        "Overflow issue in the math here.");
+          const int64_t cost_of_a =
+              int64_t{a.output_size[HORIZONTAL]} * a.output_size[VERTICAL];
+          const int64_t cost_of_b =
+              int64_t{b.output_size[HORIZONTAL]} * b.output_size[VERTICAL];
+          return cost_of_a < cost_of_b;
+        });
+    DCHECK(best_candidate != candidates.end());
+    DCHECK(cur != best_candidate->output_size)
+        << "Best candidate's output size (" << best_candidate->output_size
+        << ") should not equal the input size.";
+    auto next_stage = std::make_unique<ScalerStage>(
+        gl, best_candidate->shader, best_candidate->primary_axis,
+        cur.AsVector2d(), best_candidate->output_size.AsVector2d());
+    next_stage->set_input_stage(std::move(chain));
+    chain = std::move(next_stage);
+  }
+
+  return chain;
+}
+
+// static
+std::unique_ptr<GLScaler::ScalerStage> GLScaler::CreateTheBestScalingChain(
+    gpu::gles2::GLES2Interface* gl,
+    const gfx::Vector2d& scale_from,
+    const gfx::Vector2d& scale_to) {
+  // The BEST quality chain performs one bicubic upscale followed by N bicubic
+  // halvings, and does this is both directions. Exception: No upscale is needed
+  // when |scale_from| is a power of two multiple of |scale_to|.
+
+  // Determine the initial upscaled-to size, as the minimum number of doublings
+  // to make |scale_to| greater than |scale_from|.
+  const RelativeSize from(scale_from);
+  const RelativeSize to(scale_to);
+  RelativeSize upscale_to = to;
+  for (Axis x_or_y : std::array<Axis, 2>{HORIZONTAL, VERTICAL}) {
+    while (upscale_to[x_or_y] < from[x_or_y]) {
+      upscale_to[x_or_y] *= 2;
+    }
+  }
+
+  // Create the stages in order from first-to-last.
+  RelativeSize cur = from;
+  std::unique_ptr<ScalerStage> chain;
+  for (Axis x_or_y : std::array<Axis, 2>{VERTICAL, HORIZONTAL}) {
+    if (upscale_to[x_or_y] != from[x_or_y]) {
+      RelativeSize next = cur;
+      next[x_or_y] = upscale_to[x_or_y];
+      auto upscale_stage =
+          std::make_unique<ScalerStage>(gl, Shader::BICUBIC_UPSCALE, x_or_y,
+                                        cur.AsVector2d(), next.AsVector2d());
+      upscale_stage->set_input_stage(std::move(chain));
+      chain = std::move(upscale_stage);
+      cur = next;
+    }
+    while (cur[x_or_y] > to[x_or_y]) {
+      RelativeSize next = cur;
+      next[x_or_y] /= 2;
+      auto next_stage =
+          std::make_unique<ScalerStage>(gl, Shader::BICUBIC_HALF_1D, x_or_y,
+                                        cur.AsVector2d(), next.AsVector2d());
+      next_stage->set_input_stage(std::move(chain));
+      chain = std::move(next_stage);
+      cur = next;
+    }
+  }
+  DCHECK_EQ(cur, to);
+
+  return chain;
+}
+
+// static
+std::unique_ptr<GLScaler::ScalerStage> GLScaler::MaybeAppendExportStage(
+    gpu::gles2::GLES2Interface* gl,
+    std::unique_ptr<GLScaler::ScalerStage> chain,
+    GLScaler::Parameters::ExportFormat export_format) {
+  DCHECK(chain);
+
+  if (export_format == Parameters::ExportFormat::INTERLEAVED_QUADS) {
+    return chain;  // No format change.
+  }
+
+  // If the final stage uses the BILINEAR shader that is not upscaling, the
+  // export stage can replace it with no change in the results. Otherwise, a
+  // separate export stage will be appended.
+  gfx::Vector2d scale_from = chain->scale_from();
+  const gfx::Vector2d scale_to = chain->scale_to();
+  if (chain->shader() == Shader::BILINEAR && scale_from.x() >= scale_to.x() &&
+      scale_from.y() >= scale_to.y()) {
+    chain = chain->take_input_stage();
+  } else {
+    scale_from = scale_to;
+  }
+
+  Shader shader = Shader::BILINEAR;
+  scale_from.set_x(scale_from.x() * 4);
+  switch (export_format) {
+    case Parameters::ExportFormat::INTERLEAVED_QUADS:
+      NOTREACHED();
+      break;
+    case Parameters::ExportFormat::CHANNEL_0:
+      shader = Shader::PLANAR_CHANNEL_0;
+      break;
+    case Parameters::ExportFormat::CHANNEL_1:
+      shader = Shader::PLANAR_CHANNEL_1;
+      break;
+    case Parameters::ExportFormat::CHANNEL_2:
+      shader = Shader::PLANAR_CHANNEL_2;
+      break;
+    case Parameters::ExportFormat::CHANNEL_3:
+      shader = Shader::PLANAR_CHANNEL_3;
+      break;
+    case Parameters::ExportFormat::NV61:
+      shader = Shader::I422_NV61_MRT;
+      break;
+    case Parameters::ExportFormat::DEINTERLEAVE_PAIRWISE:
+      shader = Shader::DEINTERLEAVE_PAIRWISE_MRT;
+      // Horizontal scale is only 0.5X, not 0.25X like all the others.
+      scale_from.set_x(scale_from.x() / 2);
+      break;
+  }
+
+  auto export_stage = std::make_unique<ScalerStage>(gl, shader, HORIZONTAL,
+                                                    scale_from, scale_to);
+  export_stage->set_input_stage(std::move(chain));
+  return export_stage;
+}
+
+// static
+GLScaler::Axis GLScaler::TheOtherAxis(GLScaler::Axis x_or_y) {
+  return x_or_y == HORIZONTAL ? VERTICAL : HORIZONTAL;
+}
+
+// static
+const char* GLScaler::GetShaderName(GLScaler::Shader shader) {
+  switch (shader) {
+#define CASE_RETURN_SHADER_STR(x) \
+  case Shader::x:                 \
+    return #x
+    CASE_RETURN_SHADER_STR(BILINEAR);
+    CASE_RETURN_SHADER_STR(BILINEAR2);
+    CASE_RETURN_SHADER_STR(BILINEAR3);
+    CASE_RETURN_SHADER_STR(BILINEAR4);
+    CASE_RETURN_SHADER_STR(BILINEAR2X2);
+    CASE_RETURN_SHADER_STR(BICUBIC_UPSCALE);
+    CASE_RETURN_SHADER_STR(BICUBIC_HALF_1D);
+    CASE_RETURN_SHADER_STR(PLANAR_CHANNEL_0);
+    CASE_RETURN_SHADER_STR(PLANAR_CHANNEL_1);
+    CASE_RETURN_SHADER_STR(PLANAR_CHANNEL_2);
+    CASE_RETURN_SHADER_STR(PLANAR_CHANNEL_3);
+    CASE_RETURN_SHADER_STR(I422_NV61_MRT);
+    CASE_RETURN_SHADER_STR(DEINTERLEAVE_PAIRWISE_MRT);
+#undef CASE_RETURN_SHADER_STR
+  }
+}
+
+// static
 bool GLScaler::AreAllGLExtensionsPresent(
     gpu::gles2::GLES2Interface* gl,
     const std::vector<std::string>& names) {
@@ -1079,16 +1502,18 @@
     case Shader::PLANAR_CHANNEL_2:
     case Shader::PLANAR_CHANNEL_3:
     case Shader::I422_NV61_MRT:
-      // All of these sample exactly 4x1 source pixels to produce each output
-      // "pixel." There is no overscan.
-      DCHECK_EQ(scale_from_.x(), 4 * scale_to_.x());
+      // All of these sample 4x1 source pixels to produce each output "pixel."
+      // There is no overscan. They can also be combined with a bilinear
+      // downscale, but not an upscale.
+      DCHECK_GE(scale_from_.x(), 4 * scale_to_.x());
       DCHECK_EQ(HORIZONTAL, primary_axis_);
       break;
 
     case Shader::DEINTERLEAVE_PAIRWISE_MRT:
-      // This shader samples exactly 2x1 source pixels to produce each output
-      // "pixel." There is no overscan.
-      DCHECK_EQ(scale_from_.x(), 2 * scale_to_.x());
+      // This shader samples 2x1 source pixels to produce each output "pixel."
+      // There is no overscan. It can also be combined with a bilinear
+      // downscale, but not an upscale.
+      DCHECK_GE(scale_from_.x(), 2 * scale_to_.x());
       DCHECK_EQ(HORIZONTAL, primary_axis_);
       break;
   }
@@ -1113,4 +1538,58 @@
   }
 }
 
+std::ostream& operator<<(std::ostream& out, const GLScaler& scaler) {
+  if (!scaler.chain_) {
+    return (out << "[GLScaler NOT configured]");
+  }
+
+  out << "Output";
+  const GLScaler::ScalerStage* const final_stage = scaler.chain_.get();
+  for (auto* stage = final_stage; stage; stage = stage->input_stage()) {
+    out << u8" ← {" << GLScaler::GetShaderName(stage->shader());
+    if (stage->shader_program()) {
+      switch (stage->shader_program()->texture_type()) {
+        case GL_FLOAT:
+          out << "/highp";
+          break;
+        case GL_HALF_FLOAT_OES:
+          out << "/mediump";
+          break;
+        default:
+          out << "/lowp";
+          break;
+      }
+    }
+    if (stage->flip_output()) {
+      out << "+flip_y";
+    }
+    if (stage->scale_from() == stage->scale_to()) {
+      out << " copy";
+    } else {
+      out << ' ' << stage->scale_from().ToString() << " to "
+          << stage->scale_to().ToString();
+    }
+    if (!stage->input_stage() &&
+        scaler.params_.source_color_space != scaler.scaling_color_space_) {
+      out << ", with color x-form "
+          << scaler.params_.source_color_space.ToString() << " to "
+          << scaler.scaling_color_space_.ToString();
+    }
+    if (stage == final_stage) {
+      if (scaler.params_.output_color_space != scaler.scaling_color_space_) {
+        out << ", with color x-form to "
+            << scaler.params_.output_color_space.ToString();
+      }
+      for (int i = 0; i < 2; ++i) {
+        if (scaler.params_.swizzle[i] != GL_RGBA) {
+          out << ", with swizzle(" << i << ')';
+        }
+      }
+    }
+    out << '}';
+  }
+  out << u8" ← Source";
+  return out;
+}
+
 }  // namespace viz
diff --git a/components/viz/common/gl_scaler.h b/components/viz/common/gl_scaler.h
index 592435c..eb65815 100644
--- a/components/viz/common/gl_scaler.h
+++ b/components/viz/common/gl_scaler.h
@@ -9,6 +9,7 @@
 
 #include <map>
 #include <memory>
+#include <ostream>
 #include <string>
 #include <tuple>
 #include <utility>
@@ -260,10 +261,12 @@
  private:
   friend class GLScalerOverscanPixelTest;
   friend class GLScalerShaderPixelTest;
+  friend VIZ_COMMON_EXPORT std::ostream& operator<<(std::ostream&,
+                                                    const GLScaler&);
 
   using GLES2Interface = gpu::gles2::GLES2Interface;
 
-  enum Axis { HORIZONTAL, VERTICAL };
+  enum Axis { HORIZONTAL = 0, VERTICAL = 1 };
 
   // The shaders used by each stage in the scaling pipeline.
   enum class Shader : int8_t {
@@ -370,7 +373,11 @@
     void set_input_stage(std::unique_ptr<ScalerStage> stage) {
       input_stage_ = std::move(stage);
     }
+    std::unique_ptr<ScalerStage> take_input_stage() {
+      return std::move(input_stage_);
+    }
 
+    ShaderProgram* shader_program() const { return program_; }
     void set_shader_program(ShaderProgram* program) { program_ = program; }
 
     bool is_flipped_source() const { return is_flipped_source_; }
@@ -428,6 +435,32 @@
                                   const gfx::ColorTransform* color_transform,
                                   const GLenum swizzle[2]);
 
+  // Create a scaling chain using the bilinear shaders.
+  static std::unique_ptr<ScalerStage> CreateAGoodScalingChain(
+      gpu::gles2::GLES2Interface* gl,
+      const gfx::Vector2d& scale_from,
+      const gfx::Vector2d& scale_to);
+
+  // Create a scaling chain using the bicubic shaders.
+  static std::unique_ptr<ScalerStage> CreateTheBestScalingChain(
+      gpu::gles2::GLES2Interface* gl,
+      const gfx::Vector2d& scale_from,
+      const gfx::Vector2d& scale_to);
+
+  // Modifies |chain| by appending an export stage, to rearrange the image data
+  // according to the requested |export_format|. In some cases, this will delete
+  // the final stage in |chain| before appending the export stage.
+  static std::unique_ptr<ScalerStage> MaybeAppendExportStage(
+      gpu::gles2::GLES2Interface* gl,
+      std::unique_ptr<ScalerStage> chain,
+      Parameters::ExportFormat export_format);
+
+  // Returns the other of the two axes.
+  static Axis TheOtherAxis(Axis axis);
+
+  // Returns the name of the |shader| in string form, for logging purposes.
+  static const char* GetShaderName(Shader shader);
+
   // Returns true if the given |gl| context mentions all of |names| in its
   // extensions string.
   static bool AreAllGLExtensionsPresent(gpu::gles2::GLES2Interface* gl,
@@ -463,9 +496,16 @@
   // The chain of ScalerStages.
   std::unique_ptr<ScalerStage> chain_;
 
+  // The color space in which the scaling stages operate.
+  gfx::ColorSpace scaling_color_space_;
+
   DISALLOW_COPY_AND_ASSIGN(GLScaler);
 };
 
+// For logging.
+VIZ_COMMON_EXPORT std::ostream& operator<<(std::ostream& out,
+                                           const GLScaler& scaler);
+
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_COMMON_GL_SCALER_H_
diff --git a/components/viz/common/gl_scaler_pixeltest.cc b/components/viz/common/gl_scaler_pixeltest.cc
new file mode 100644
index 0000000..9f66671
--- /dev/null
+++ b/components/viz/common/gl_scaler_pixeltest.cc
@@ -0,0 +1,534 @@
+// 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 "components/viz/common/gl_scaler.h"
+
+#include <sstream>
+
+#include "base/strings/pattern.h"
+#include "build/build_config.h"
+#include "cc/test/pixel_test.h"
+#include "cc/test/pixel_test_utils.h"
+#include "components/viz/common/gl_scaler_test_util.h"
+#include "components/viz/common/gpu/context_provider.h"
+#include "gpu/GLES2/gl2chromium.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/color_space.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
+namespace viz {
+
+#define EXPECT_STRING_MATCHES(expected, actual)                     \
+  if (!base::MatchPattern(actual, expected)) {                      \
+    ADD_FAILURE() << "\nActual: " << (actual)                       \
+                  << "\nExpected to match pattern: " << (expected); \
+  }
+
+class GLScalerPixelTest : public cc::PixelTest, public GLScalerTestUtil {
+ public:
+  GLScaler* scaler() const { return scaler_.get(); }
+
+  std::string GetScalerString() const {
+    std::ostringstream oss;
+    oss << *scaler_;
+    return oss.str();
+  }
+
+  GLuint CreateTexture(const gfx::Size& size) {
+    return texture_helper_->CreateTexture(size);
+  }
+
+  GLuint UploadTexture(const SkBitmap& bitmap) {
+    return texture_helper_->UploadTexture(bitmap);
+  }
+
+  SkBitmap DownloadTexture(GLuint texture, const gfx::Size& size) {
+    return texture_helper_->DownloadTexture(texture, size);
+  }
+
+  // Test convenience to upload |src_bitmap| to the GPU, execute the scaling,
+  // then download the result from the GPU and return it as a SkBitmap.
+  SkBitmap Scale(const SkBitmap& src_bitmap,
+                 const gfx::Vector2d& src_offset,
+                 const gfx::Rect& output_rect) {
+    const GLuint src_texture = UploadTexture(src_bitmap);
+    const GLuint dest_texture = CreateTexture(output_rect.size());
+    if (!scaler()->Scale(src_texture,
+                         gfx::Size(src_bitmap.width(), src_bitmap.height()),
+                         src_offset, dest_texture, output_rect)) {
+      return SkBitmap();
+    }
+    return DownloadTexture(dest_texture, output_rect.size());
+  }
+
+  // Returns the amount of color error expected due to bugs in the current
+  // platform's bilinear texture sampler.
+  int GetBaselineColorDifference() const {
+#if defined(OS_ANDROID)
+    // Android seems to have texture sampling problems that are not at all seen
+    // on any of the desktop platforms. Also, versions before Marshmallow seem
+    // to have a much larger accuracy issues.
+    if (base::android::BuildInfo::GetInstance()->sdk_int() <
+        base::android::SDK_VERSION_MARSHMALLOW) {
+      return 12;
+    }
+    return 2;
+#else
+    return 0;
+#endif
+  }
+
+ protected:
+  void SetUp() final {
+    cc::PixelTest::SetUpGLWithoutRenderer(false);
+
+    scaler_ = std::make_unique<GLScaler>(context_provider());
+    gl_ = context_provider()->ContextGL();
+    CHECK(gl_);
+    texture_helper_ = std::make_unique<GLScalerTestTextureHelper>(gl_);
+  }
+
+  void TearDown() final {
+    texture_helper_.reset();
+    gl_ = nullptr;
+    scaler_.reset();
+
+    cc::PixelTest::TearDown();
+  }
+
+ private:
+  std::unique_ptr<GLScaler> scaler_;
+  gpu::gles2::GLES2Interface* gl_ = nullptr;
+  std::unique_ptr<GLScalerTestTextureHelper> texture_helper_;
+};
+
+// Tests that the default GLScaler::Parameters produces an unscaled copy.
+TEST_F(GLScalerPixelTest, CopiesByDefault) {
+  ASSERT_TRUE(scaler()->Configure(GLScaler::Parameters()));
+  EXPECT_EQ(u8"Output ← {BILINEAR/lowp copy} ← Source", GetScalerString());
+  const SkBitmap source = CreateSMPTETestImage(kSMPTEFullSize);
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(kSMPTEFullSize));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(
+      actual, kSMPTEFullSize, gfx::Rect(kSMPTEFullSize), 0, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests a FAST quality scaling of 2→1 in X and 3→2 in Y.
+TEST_F(GLScalerPixelTest, ScalesAtFastQuality) {
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(2, 3);
+  params.scale_to = gfx::Vector2d(1, 2);
+  params.quality = GLScaler::Parameters::Quality::FAST;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {BILINEAR/lowp [2 3] to [1 2]} ← Source",
+            GetScalerString());
+  const SkBitmap source = CreateSMPTETestImage(kSMPTEFullSize);
+  static_assert(kSMPTEFullSize.width() % 2 == 0, "Fix kSMPTEFullSize.");
+  static_assert(kSMPTEFullSize.height() % 3 == 0, "Fix kSMPTEFullSize.");
+  const SkBitmap actual = Scale(source, gfx::Vector2d(),
+                                gfx::Rect(0, 0, kSMPTEFullSize.width() / 2,
+                                          kSMPTEFullSize.height() * 2 / 3));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(
+      actual, kSMPTEFullSize, gfx::Rect(kSMPTEFullSize), 2, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests a GOOD quality scaling of 1280x720 → 1024x700.
+TEST_F(GLScalerPixelTest, ScalesALittleAtGoodQuality) {
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(1280, 720);
+  params.scale_to = gfx::Vector2d(1024, 700);
+  params.quality = GLScaler::Parameters::Quality::GOOD;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {BILINEAR2X2/lowp [1280 720] to [1024 700]} ← Source",
+            GetScalerString());
+  constexpr gfx::Size kSourceSize = gfx::Size(1280, 720);
+  const SkBitmap source = CreateSMPTETestImage(kSourceSize);
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(0, 0, 1024, 700));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(
+      actual, kSourceSize, gfx::Rect(kSourceSize), 2, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests a large, skewed reduction at GOOD quality: 3840x720 → 128x256.
+TEST_F(GLScalerPixelTest, ScalesALotHorizontallyAtGoodQuality) {
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(3840, 720);
+  params.scale_to = gfx::Vector2d(128, 256);
+  params.quality = GLScaler::Parameters::Quality::GOOD;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(
+      u8"Output "
+      u8"← {BILINEAR/lowp [256 256] to [128 256]} "
+      u8"← {BILINEAR4/lowp [2048 512] to [256 256]} "
+      u8"← {BILINEAR2X2/lowp [3840 720] to [2048 512]} "
+      u8"← Source",
+      GetScalerString());
+  constexpr gfx::Size kSourceSize = gfx::Size(3840, 720);
+  const SkBitmap source = CreateSMPTETestImage(kSourceSize);
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(0, 0, 128, 256));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(
+      actual, kSourceSize, gfx::Rect(kSourceSize), 2, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests a large, skewed reduction at GOOD quality: 640x2160 → 256x128.
+TEST_F(GLScalerPixelTest, ScalesALotVerticallyAtGoodQuality) {
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(640, 2160);
+  params.scale_to = gfx::Vector2d(256, 128);
+  params.quality = GLScaler::Parameters::Quality::GOOD;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(
+      u8"Output "
+      u8"← {BILINEAR/lowp [256 256] to [256 128]} "
+      u8"← {BILINEAR4/lowp [512 2048] to [256 256]} "
+      u8"← {BILINEAR2X2/lowp [640 2160] to [512 2048]} "
+      u8"← Source",
+      GetScalerString());
+  constexpr gfx::Size kSourceSize = gfx::Size(640, 2160);
+  const SkBitmap source = CreateSMPTETestImage(kSourceSize);
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(0, 0, 256, 128));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(
+      actual, kSourceSize, gfx::Rect(kSourceSize), 2, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests a BEST quality scaling of 1280x720 → 1024x700.
+TEST_F(GLScalerPixelTest, ScalesAtBestQuality) {
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(1280, 720);
+  params.scale_to = gfx::Vector2d(1024, 700);
+  params.quality = GLScaler::Parameters::Quality::BEST;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(
+      u8"Output "
+      u8"← {BICUBIC_HALF_1D/lowp [2048 700] to [1024 700]} "
+      u8"← {BICUBIC_UPSCALE/lowp [1280 700] to [2048 700]} "
+      u8"← {BICUBIC_HALF_1D/lowp [1280 1400] to [1280 700]} "
+      u8"← {BICUBIC_UPSCALE/lowp [1280 720] to [1280 1400]} "
+      u8"← Source",
+      GetScalerString());
+  constexpr gfx::Size kSourceSize = gfx::Size(1280, 720);
+  const SkBitmap source = CreateSMPTETestImage(kSourceSize);
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(0, 0, 1024, 700));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(
+      actual, kSourceSize, gfx::Rect(kSourceSize), 4, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests that a source offset can be provided to sample the source starting at a
+// different location.
+TEST_F(GLScalerPixelTest, TranslatesWithSourceOffset) {
+  GLScaler::Parameters params;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {BILINEAR/lowp copy} ← Source", GetScalerString());
+  const SkBitmap source = CreateSMPTETestImage(kSMPTEFullSize);
+  static_assert(kSMPTEFullSize.width() % 2 == 0, "Fix kSMPTEFullSize.");
+  static_assert(kSMPTEFullSize.height() % 4 == 0, "Fix kSMPTEFullSize.");
+  const gfx::Vector2d offset(kSMPTEFullSize.width() / 2,
+                             kSMPTEFullSize.height() / 4);
+  const gfx::Rect src_rect(offset.x(), offset.y(),
+                           kSMPTEFullSize.width() - offset.x(),
+                           kSMPTEFullSize.height() - offset.y());
+  const gfx::Rect output_rect(0, 0, kSMPTEFullSize.width() - offset.x(),
+                              kSMPTEFullSize.height() - offset.y());
+  const SkBitmap actual = Scale(source, offset, output_rect);
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(actual, kSMPTEFullSize, src_rect, 0,
+                                      &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual: " << cc::GetPNGDataUrl(actual);
+}
+
+// Tests that the source offset works when the source content is vertically
+// flipped.
+TEST_F(GLScalerPixelTest, TranslatesVerticallyFlippedSourceWithSourceOffset) {
+  GLScaler::Parameters params;
+  params.is_flipped_source = true;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {BILINEAR/lowp copy} ← Source", GetScalerString());
+  const SkBitmap flipped_source =
+      CreateVerticallyFlippedBitmap(CreateSMPTETestImage(kSMPTEFullSize));
+  const gfx::Vector2d offset(kSMPTEFullSize.width() / 2,
+                             kSMPTEFullSize.height() / 4);
+  const gfx::Rect src_rect(offset.x(), offset.y(),
+                           kSMPTEFullSize.width() - offset.x(),
+                           kSMPTEFullSize.height() - offset.y());
+  const gfx::Rect output_rect(0, 0, kSMPTEFullSize.width() - offset.x(),
+                              kSMPTEFullSize.height() - offset.y());
+  const SkBitmap flipped_back_actual =
+      CreateVerticallyFlippedBitmap(Scale(flipped_source, offset, output_rect));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(flipped_back_actual, kSMPTEFullSize,
+                                      src_rect, 0, &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual (flipped-back): " << cc::GetPNGDataUrl(flipped_back_actual);
+}
+
+// Tests that the output is vertically flipped, if requested in the parameters.
+TEST_F(GLScalerPixelTest, VerticallyFlipsOutput) {
+  GLScaler::Parameters params;
+  params.is_flipped_source = false;
+  params.flip_output = true;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {BILINEAR/lowp+flip_y copy} ← Source",
+            GetScalerString());
+  const SkBitmap source = CreateSMPTETestImage(kSMPTEFullSize);
+  const SkBitmap flipped_back_actual = CreateVerticallyFlippedBitmap(
+      Scale(source, gfx::Vector2d(), gfx::Rect(kSMPTEFullSize)));
+  int max_color_diff = GetBaselineColorDifference();
+  EXPECT_TRUE(LooksLikeSMPTETestImage(flipped_back_actual, kSMPTEFullSize,
+                                      gfx::Rect(kSMPTEFullSize), 0,
+                                      &max_color_diff))
+      << "max_color_diff measured was " << max_color_diff
+      << "\nActual (flipped-back): " << cc::GetPNGDataUrl(flipped_back_actual);
+}
+
+// Tests that the single-channel export ScalerStage works by executing a red
+// channel export.
+TEST_F(GLScalerPixelTest, ExportsTheRedColorChannel) {
+  GLScaler::Parameters params;
+  params.is_flipped_source = false;
+  params.export_format = GLScaler::Parameters::ExportFormat::CHANNEL_0;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {PLANAR_CHANNEL_0/lowp [4 1] to [1 1]} ← Source",
+            GetScalerString());
+  const SkBitmap source = CreateSMPTETestImage(kSMPTEFullSize);
+  const SkBitmap expected = CreatePackedPlanarBitmap(source, 0);
+  const gfx::Size output_size(expected.width(), expected.height());
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(output_size));
+  constexpr float kAvgAbsoluteErrorLimit = 1.f;
+  constexpr int kMaxAbsoluteErrorLimit = 2;
+  EXPECT_TRUE(cc::FuzzyPixelComparator(
+                  false, 100.f, 0.f,
+                  GetBaselineColorDifference() + kAvgAbsoluteErrorLimit,
+                  GetBaselineColorDifference() + kMaxAbsoluteErrorLimit, 0)
+                  .Compare(expected, actual))
+      << "\nActual: " << cc::GetPNGDataUrl(actual)
+      << "\Expected: " << cc::GetPNGDataUrl(expected);
+}
+
+// A test that also stands as an example for how to use the GLScaler to scale a
+// screen-sized RGB source (2160x1440, 16:10 aspect ratio) to a typical video
+// resolution (720p, 16:9). The end-goal is to produce three textures, which
+// contain the three YUV planes in I420 format.
+//
+// This is a two step process: First, the source is scaled and color space
+// converted, with the final result exported as NV61 format (a full size luma
+// plane + a half-width interleaved UV image). Second, the interleaved UV image
+// is scaled by half in the vertical direction and then separated into one U and
+// one V plane.
+TEST_F(GLScalerPixelTest, Example_ScaleAndExportForScreenVideoCapture) {
+  if (scaler()->GetMaxDrawBuffersSupported() < 2) {
+    LOG(WARNING) << "Skipping test due to lack of MRT support.";
+    return;
+  }
+
+  // Step 1: Produce a scaled NV61-format result.
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(2160, 1440);
+  params.scale_to = gfx::Vector2d(1280, 720);
+  params.source_color_space = DefaultRGBColorSpace();
+  params.output_color_space = DefaultYUVColorSpace();
+  params.enable_precise_color_management = true;
+  params.quality = GLScaler::Parameters::Quality::GOOD;
+  params.is_flipped_source = true;
+  params.flip_output = true;
+  params.export_format = GLScaler::Parameters::ExportFormat::NV61;
+  params.swizzle[0] = GL_BGRA_EXT;  // Swizzle for readback.
+  params.swizzle[1] = GL_RGBA;      // Don't swizzle output for Step 2.
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_STRING_MATCHES(
+      u8"Output "
+      u8"← {I422_NV61_MRT/mediump [5120 720] to [1280 720], with color x-form "
+      u8"to *BT709*, with swizzle(0)} "
+      u8"← {BILINEAR2/mediump [2160 1440] to [1280 720]} "
+      u8"← {BILINEAR/mediump+flip_y copy, with color x-form *BT709* to "
+      u8"*transfer:1.0000\\*x*} "
+      u8"← Source",
+      GetScalerString());
+
+  constexpr gfx::Size kSourceSize = gfx::Size(2160, 1440);
+  const GLuint src_texture = UploadTexture(
+      CreateVerticallyFlippedBitmap(CreateSMPTETestImage(kSourceSize)));
+  constexpr gfx::Size kOutputSize = gfx::Size(1280, 720);
+  SkBitmap expected = CreateSMPTETestImage(kOutputSize);
+  ConvertBitmapToYUV(&expected);
+
+  // While the output size is 1280x720, the packing of 4 pixels into one RGBA
+  // quad means that the texture width must be divided by 4, and that size
+  // passed in the output_rect argument in the call to ScaleToMultipleOutputs().
+  const gfx::Size y_plane_size(kOutputSize.width() / 4, kOutputSize.height());
+  const GLuint y_plane_texture = CreateTexture(y_plane_size);
+  const GLuint uv_interleaved_texture = CreateTexture(y_plane_size);
+
+  ASSERT_TRUE(scaler()->ScaleToMultipleOutputs(
+      src_texture, kSourceSize, gfx::Vector2d(), y_plane_texture,
+      uv_interleaved_texture, gfx::Rect(y_plane_size)));
+
+  // Step 2: Run the scaler again with the deinterleaver exporter, to produce
+  // the I420 U and V planes from the NV61 UV interleaved image.
+  params = GLScaler::Parameters();  // Reset params.
+  params.scale_from = gfx::Vector2d(1, 2);
+  params.scale_to = gfx::Vector2d(1, 1);
+  params.source_color_space = DefaultYUVColorSpace();
+  params.quality = GLScaler::Parameters::Quality::GOOD;
+  params.is_flipped_source = false;  // Output was already flipped in Step 1.
+  params.export_format =
+      GLScaler::Parameters::ExportFormat::DEINTERLEAVE_PAIRWISE;
+  params.swizzle[0] = GL_BGRA_EXT;  // Swizzle for readback.
+  params.swizzle[1] = GL_BGRA_EXT;  // Swizzle for readback.
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(
+      u8"Output "
+      u8"← {DEINTERLEAVE_PAIRWISE_MRT/lowp [2 2] to [1 1], with swizzle(0), "
+      u8"with swizzle(1)} "
+      u8"← Source",
+      GetScalerString());
+
+  const gfx::Size uv_plane_size(y_plane_size.width() / 2,
+                                y_plane_size.height() / 2);
+  const GLuint u_plane_texture = CreateTexture(uv_plane_size);
+  const GLuint v_plane_texture = CreateTexture(uv_plane_size);
+  ASSERT_TRUE(scaler()->ScaleToMultipleOutputs(
+      uv_interleaved_texture, y_plane_size, gfx::Vector2d(), u_plane_texture,
+      v_plane_texture, gfx::Rect(uv_plane_size)));
+
+  // Download the textures, and unpack them into an interleaved YUV bitmap, for
+  // comparison against the |expected| rendition.
+  SkBitmap actual = AllocateRGBABitmap(kOutputSize);
+  actual.eraseColor(SkColorSetARGB(0xff, 0x00, 0x80, 0x80));
+  SkBitmap y_plane = DownloadTexture(y_plane_texture, y_plane_size);
+  SwizzleBitmap(&y_plane);
+  UnpackPlanarBitmap(y_plane, 0, &actual);
+  SkBitmap u_plane = DownloadTexture(u_plane_texture, uv_plane_size);
+  SwizzleBitmap(&u_plane);
+  UnpackPlanarBitmap(u_plane, 1, &actual);
+  SkBitmap v_plane = DownloadTexture(v_plane_texture, uv_plane_size);
+  SwizzleBitmap(&v_plane);
+  UnpackPlanarBitmap(v_plane, 2, &actual);
+
+  // Provide generous error limits to account for the chroma subsampling in the
+  // |actual| result when compared to the perfect |expected| rendition.
+  constexpr float kAvgAbsoluteErrorLimit = 16.f;
+  constexpr int kMaxAbsoluteErrorLimit = 0x80;
+  EXPECT_TRUE(cc::FuzzyPixelComparator(false, 100.f, 0.f,
+                                       kAvgAbsoluteErrorLimit,
+                                       kMaxAbsoluteErrorLimit, 0)
+                  .Compare(expected, actual))
+      << "\nActual: " << cc::GetPNGDataUrl(actual)
+      << "\nExpected: " << cc::GetPNGDataUrl(expected);
+}
+
+// Performs a scaling-with-gamma-correction experiment to test GLScaler's
+// "precise color management" feature. A 50% scale is executed on the same
+// source image, once with color management turned on, and once with it turned
+// off. The results, each of which should be different, are then examined.
+TEST_F(GLScalerPixelTest, ScalesWithColorManagement) {
+  if (!scaler()->SupportsPreciseColorManagement()) {
+    LOG(WARNING) << "Skipping test due to lack of 16-bit float support.";
+    return;
+  }
+
+  // An image of a raspberry (source:
+  // https://commons.wikimedia.org/wiki/File:Framboise_Margy_3.jpg) has been
+  // transformed in such a way that scaling it by half in both directions will
+  // reveal whether scaling is occurring on linearized color values. When scaled
+  // correctly, the output image should contain a visible raspberry blended
+  // heavily with solid gray. However, if done naively, the output will be a
+  // solid 50% gray. For details, see: http://www.ericbrasseur.org/gamma.html
+  //
+  // Note that the |source| and |expected| images both use the sRGB color space.
+  const SkBitmap source = LoadPNGTestImage("rasp-grayator.png");
+  ASSERT_FALSE(source.isNull());
+  const SkBitmap expected = LoadPNGTestImage("rasp-grayator-half.png");
+  ASSERT_FALSE(expected.isNull());
+  const gfx::Size output_size =
+      gfx::Size(source.width() / 2, source.height() / 2);
+  ASSERT_EQ(gfx::Size(expected.width(), expected.height()), output_size);
+  const SkBitmap expected_naive = AllocateRGBABitmap(output_size);
+  expected_naive.eraseColor(SkColorSetARGB(0xff, 0x7f, 0x7f, 0x7f));
+
+  // Scale the right way: With color management enabled, the raspberry should be
+  // visible in the downscaled result.
+  GLScaler::Parameters params;
+  params.scale_from = gfx::Vector2d(2, 2);
+  params.scale_to = gfx::Vector2d(1, 1);
+  params.source_color_space = gfx::ColorSpace::CreateSRGB();
+  params.enable_precise_color_management = true;
+  params.quality = GLScaler::Parameters::Quality::GOOD;
+  params.is_flipped_source = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_STRING_MATCHES(
+      u8"Output "
+      u8"← {BILINEAR/mediump [2 2] to [1 1], with color x-form to *BT709*} "
+      u8"← {BILINEAR/mediump copy, with color x-form *BT709* to "
+      u8"*transfer:1.0000\\*x*} "
+      u8"← Source",
+      GetScalerString());
+  const SkBitmap actual =
+      Scale(source, gfx::Vector2d(), gfx::Rect(output_size));
+  constexpr float kAvgAbsoluteErrorLimit = 1.f;
+  constexpr int kMaxAbsoluteErrorLimit = 2;
+  EXPECT_TRUE(cc::FuzzyPixelComparator(
+                  false, 100.f, 0.f,
+                  GetBaselineColorDifference() + kAvgAbsoluteErrorLimit,
+                  GetBaselineColorDifference() + kMaxAbsoluteErrorLimit, 0)
+                  .Compare(expected, actual))
+      << "\nActual: " << cc::GetPNGDataUrl(actual)
+      << "\nExpected (half size): " << cc::GetPNGDataUrl(expected)
+      << "\nOriginal: " << cc::GetPNGDataUrl(source);
+
+  // Scale the naive way: Without color management, expect a solid gray result.
+  params.enable_precise_color_management = false;
+  ASSERT_TRUE(scaler()->Configure(params));
+  EXPECT_EQ(u8"Output ← {BILINEAR/lowp [2 2] to [1 1]} ← Source",
+            GetScalerString());
+  const SkBitmap actual_naive =
+      Scale(source, gfx::Vector2d(), gfx::Rect(output_size));
+  EXPECT_TRUE(cc::FuzzyPixelComparator(
+                  false, 100.f, 0.f,
+                  GetBaselineColorDifference() + kAvgAbsoluteErrorLimit,
+                  GetBaselineColorDifference() + kMaxAbsoluteErrorLimit, 0)
+                  .Compare(expected_naive, actual_naive))
+      << "\nActual: " << cc::GetPNGDataUrl(actual_naive)
+      << "\nExpected (half size): " << cc::GetPNGDataUrl(expected_naive)
+      << "\nOriginal: " << cc::GetPNGDataUrl(source);
+}
+
+#undef EXPECT_STRING_MATCHES
+
+}  // namespace viz
diff --git a/components/viz/common/gl_scaler_shader_pixeltest.cc b/components/viz/common/gl_scaler_shader_pixeltest.cc
index 347ee7b..1b93812 100644
--- a/components/viz/common/gl_scaler_shader_pixeltest.cc
+++ b/components/viz/common/gl_scaler_shader_pixeltest.cc
@@ -346,7 +346,7 @@
     // Android seems to have texture sampling and/or readback accuracy issues
     // with these programs that are not at all seen on any of the desktop
     // platforms. Also, versions before Marshmallow seem to have a much larger
-    // accuracy issue with a few of the programs. Thus, use higher thresholds,
+    // accuracy issues with a few of the programs. Thus, use higher thresholds,
     // assuming that the programs are correct if they can pass a much lower
     // threshold on other platforms.
     if (base::android::BuildInfo::GetInstance()->sdk_int() <
diff --git a/components/viz/common/gl_scaler_test_util.cc b/components/viz/common/gl_scaler_test_util.cc
index a706e82..62560e8 100644
--- a/components/viz/common/gl_scaler_test_util.cc
+++ b/components/viz/common/gl_scaler_test_util.cc
@@ -7,7 +7,11 @@
 #include <algorithm>
 #include <cmath>
 
+#include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/path_service.h"
+#include "cc/test/pixel_test_utils.h"
+#include "components/viz/test/paths.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "ui/gfx/geometry/rect.h"
@@ -256,6 +260,86 @@
   return result;
 }
 
+// static
+void GLScalerTestUtil::UnpackPlanarBitmap(const SkBitmap& plane,
+                                          int channel,
+                                          SkBitmap* out) {
+  // The heuristic below auto-adapts to subsampled plane sizes. However, there
+  // are two cricital requirements: 1) |plane| cannot be empty; 2) |plane| must
+  // have a size that cleanly unpacks to |out|'s size.
+  CHECK_GT(plane.width(), 0);
+  CHECK_GT(plane.height(), 0);
+  const int col_sampling_ratio = out->width() / plane.width();
+  CHECK_EQ(out->width() % plane.width(), 0);
+  CHECK_GT(col_sampling_ratio, 0);
+  const int row_sampling_ratio = out->height() / plane.height();
+  CHECK_EQ(out->height() % plane.height(), 0);
+  CHECK_GT(row_sampling_ratio, 0);
+  const int ch_sampling_ratio = col_sampling_ratio / 4;
+  CHECK_GT(ch_sampling_ratio, 0);
+
+  // These determine which single byte in each of |out|'s uint32_t-valued pixels
+  // will be modified.
+  constexpr int kShiftForChannel[4] = {kRedShift, kGreenShift, kBlueShift,
+                                       kAlphaShift};
+  const int output_shift = kShiftForChannel[channel];
+  const uint32_t output_retain_mask = ~(UINT32_C(0xff) << output_shift);
+
+  // Iterate over the pixels of |out|, sampling each of the 4 components of each
+  // of |plane|'s pixels.
+  for (int y = 0; y < out->height(); ++y) {
+    const uint32_t* const src = plane.getAddr32(0, y / row_sampling_ratio);
+    uint32_t* const dst = out->getAddr32(0, y);
+    for (int x = 0; x < out->width(); ++x) {
+      // Zero-out the existing byte (e.g., if channel==1, then "RGBA" → "R0BA").
+      dst[x] &= output_retain_mask;
+
+      // From |src|, grab one of "XYZW". Then, copy it to the target byte in
+      // |dst| (e.g., if x_src_ch=3, then grab "W" from |src|, and |dst| changes
+      // from "R0BA" to "RWBA").
+      const int x_src = x / col_sampling_ratio;
+      const int x_src_ch = (x / ch_sampling_ratio) % 4;
+      dst[x] |= ((src[x_src] >> kShiftForChannel[x_src_ch]) & 0xff)
+                << output_shift;
+    }
+  }
+}
+
+// static
+SkBitmap GLScalerTestUtil::CreateVerticallyFlippedBitmap(
+    const SkBitmap& source) {
+  SkBitmap bitmap;
+  bitmap.allocPixels(source.info());
+  CHECK_EQ(bitmap.rowBytes(), source.rowBytes());
+  for (int y = 0; y < bitmap.height(); ++y) {
+    const int src_y = bitmap.height() - y - 1;
+    memcpy(bitmap.getAddr32(0, y), source.getAddr32(0, src_y),
+           bitmap.rowBytes());
+  }
+  return bitmap;
+}
+
+// static
+SkBitmap GLScalerTestUtil::LoadPNGTestImage(const std::string& basename) {
+  base::FilePath test_dir;
+  if (!base::PathService::Get(Paths::DIR_TEST_DATA, &test_dir)) {
+    LOG(ERROR) << "Unable to get Paths::DIR_TEST_DATA from base::PathService.";
+    return SkBitmap();
+  }
+  const auto source_file = test_dir.AppendASCII(basename);
+  SkBitmap as_n32;
+  if (!cc::ReadPNGFile(source_file, &as_n32)) {
+    return SkBitmap();
+  }
+  SkBitmap as_rgba =
+      AllocateRGBABitmap(gfx::Size(as_n32.width(), as_n32.height()));
+  if (!as_n32.readPixels(SkPixmap(as_rgba.info(), as_rgba.getAddr(0, 0),
+                                  as_rgba.rowBytes()))) {
+    return SkBitmap();
+  }
+  return as_rgba;
+}
+
 // The area and color of the bars in a 1920x1080 HD SMPTE color bars test image
 // (https://commons.wikimedia.org/wiki/File:SMPTE_Color_Bars_16x9.svg). The gray
 // linear gradient bar is defined as half solid 0-level black and half solid
diff --git a/components/viz/common/gl_scaler_test_util.h b/components/viz/common/gl_scaler_test_util.h
index 3c4e47e..296dbdb 100644
--- a/components/viz/common/gl_scaler_test_util.h
+++ b/components/viz/common/gl_scaler_test_util.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -98,6 +99,21 @@
   // considered a reference implementation of that.
   static SkBitmap CreatePackedPlanarBitmap(const SkBitmap& source, int channel);
 
+  // Performs the inverse operation to CreatePackedPlanarBitmap(). This takes
+  // all of the data in |plane| and uses it to populate a single color channel
+  // of all the pixels of |out|. The |plane| can be a full-size or half-size
+  // (subsampled) plane.
+  static void UnpackPlanarBitmap(const SkBitmap& plane,
+                                 int channel,
+                                 SkBitmap* out);
+
+  // Returns the |source| bitmap, but with its content vertically flipped.
+  static SkBitmap CreateVerticallyFlippedBitmap(const SkBitmap& source);
+
+  // Loads a PNG test image from the test directory, and converts it to the same
+  // SkImageInfo format used by AllocateRGBABitmap() (i.e., GL_RGBA byte order).
+  static SkBitmap LoadPNGTestImage(const std::string& basename);
+
   // The area and color of the bars in a 1920x1080 HD SMPTE color bars test
   // image (https://commons.wikimedia.org/wiki/File:SMPTE_Color_Bars_16x9.svg).
   // The gray linear gradient bar is defined as half solid 0-level black and
diff --git a/components/viz/common/gl_scaler_unittest.cc b/components/viz/common/gl_scaler_unittest.cc
index ed70215..7cc690c 100644
--- a/components/viz/common/gl_scaler_unittest.cc
+++ b/components/viz/common/gl_scaler_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "components/viz/common/gl_scaler.h"
 
+#include "cc/test/pixel_test.h"
+#include "components/viz/common/gl_scaler_test_util.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "gpu/GLES2/gl2chromium.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -79,7 +81,12 @@
   }
 };
 
-class GLScalerTest : public testing::Test {};
+class GLScalerTest : public cc::PixelTest {
+ protected:
+  void SetUp() final { cc::PixelTest::SetUpGLWithoutRenderer(false); }
+
+  void TearDown() final { cc::PixelTest::TearDown(); }
+};
 
 TEST_F(GLScalerTest, AddAndRemovesSelfAsContextLossObserver) {
   NiceMock<MockContextProvider> provider;
@@ -93,7 +100,7 @@
   GLScaler scaler(base::WrapRefCounted(&provider));
 }
 
-TEST_F(GLScalerTest, CleansUpWhenContextIsLost) {
+TEST_F(GLScalerTest, RemovesObserverWhenContextIsLost) {
   NiceMock<MockContextProvider> provider;
   ContextLostObserver* registered_observer = nullptr;
   Sequence s;
@@ -108,9 +115,29 @@
   Mock::VerifyAndClearExpectations(&provider);
 }
 
+TEST_F(GLScalerTest, StopsScalingWhenContextIsLost) {
+  GLScaler scaler(context_provider());
+
+  // Configure the scaler with default parameters (1:1 scale ratio).
+  ASSERT_TRUE(scaler.Configure(GLScaler::Parameters()));
+
+  // Call Scale() and expect it to return true to indicate the operation
+  // succeeded.
+  GLScalerTestTextureHelper helper(context_provider()->ContextGL());
+  constexpr gfx::Size kSomeSize = gfx::Size(32, 32);
+  const GLuint src_texture = helper.CreateTexture(kSomeSize);
+  const GLuint dest_texture = helper.CreateTexture(kSomeSize);
+  EXPECT_TRUE(scaler.Scale(src_texture, kSomeSize, gfx::Vector2d(),
+                           dest_texture, gfx::Rect(kSomeSize)));
+
+  // After the context is lost, another call to Scale() should return false.
+  static_cast<ContextLostObserver&>(scaler).OnContextLost();
+  EXPECT_FALSE(scaler.Scale(src_texture, kSomeSize, gfx::Vector2d(),
+                            dest_texture, gfx::Rect(kSomeSize)));
+}
+
 TEST_F(GLScalerTest, Configure_RequiresValidScalingVectors) {
-  NiceMock<MockContextProvider> provider;
-  GLScaler scaler(base::WrapRefCounted(&provider));
+  GLScaler scaler(context_provider());
 
   GLScaler::Parameters params;
   EXPECT_TRUE(scaler.Configure(params));
@@ -123,8 +150,7 @@
 }
 
 TEST_F(GLScalerTest, Configure_ResolvesUnspecifiedColorSpaces) {
-  NiceMock<MockContextProvider> provider;
-  GLScaler scaler(base::WrapRefCounted(&provider));
+  GLScaler scaler(context_provider());
 
   // Neither source nor output space specified: Both should resolve to sRGB.
   GLScaler::Parameters params;
@@ -151,8 +177,7 @@
 }
 
 TEST_F(GLScalerTest, Configure_RequiresValidSwizzles) {
-  NiceMock<MockContextProvider> provider;
-  GLScaler scaler(base::WrapRefCounted(&provider));
+  GLScaler scaler(context_provider());
   GLScaler::Parameters params;
 
   // Test that all valid combinations work.
diff --git a/components/viz/common/quads/draw_quad_unittest.cc b/components/viz/common/quads/draw_quad_unittest.cc
index cae3f216..82b9c82 100644
--- a/components/viz/common/quads/draw_quad_unittest.cc
+++ b/components/viz/common/quads/draw_quad_unittest.cc
@@ -151,19 +151,19 @@
   { QUAD_DATA quad_new->SetNew(shared_state, quad_rect, __VA_ARGS__); } \
   SETUP_AND_COPY_QUAD_NEW(Type, quad_new);
 
-#define CREATE_QUAD_ALL_RP(Type, a, b, c, d, e, f, g, h, i, copy_a)        \
+#define CREATE_QUAD_ALL_RP(Type, a, b, c, d, e, f, g, h, copy_a)           \
   Type* quad_all = render_pass->CreateAndAppendDrawQuad<Type>();           \
   {                                                                        \
     QUAD_DATA quad_all->SetAll(shared_state, quad_rect, quad_visible_rect, \
-                               needs_blending, a, b, c, d, e, f, g, h, i); \
+                               needs_blending, a, b, c, d, e, f, g, h);    \
   }                                                                        \
   SETUP_AND_COPY_QUAD_ALL_RP(Type, quad_all, copy_a);
 
-#define CREATE_QUAD_NEW_RP(Type, a, b, c, d, e, f, g, h, i, j, copy_a)       \
+#define CREATE_QUAD_NEW_RP(Type, a, b, c, d, e, f, g, h, i, copy_a)          \
   Type* quad_new = render_pass->CreateAndAppendDrawQuad<Type>();             \
   {                                                                          \
     QUAD_DATA quad_new->SetNew(shared_state, quad_rect, a, b, c, d, e, f, g, \
-                               h, i, j);                                     \
+                               h, i);                                        \
   }                                                                          \
   SETUP_AND_COPY_QUAD_NEW_RP(Type, quad_new, copy_a);
 
@@ -195,7 +195,6 @@
   gfx::PointF filters_origin;
   gfx::RectF tex_coord_rect(1, 1, 255, 254);
   bool force_anti_aliasing_off = false;
-  float backdrop_filter_quality = 1.0f;
 
   RenderPassId copied_render_pass_id = 235;
   CREATE_SHARED_STATE();
@@ -203,8 +202,7 @@
   CREATE_QUAD_NEW_RP(RenderPassDrawQuad, visible_rect, render_pass_id,
                      mask_resource_id, mask_uv_rect, mask_texture_size,
                      filters_scale, filters_origin, tex_coord_rect,
-                     force_anti_aliasing_off, backdrop_filter_quality,
-                     copied_render_pass_id);
+                     force_anti_aliasing_off, copied_render_pass_id);
   EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material);
   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
   EXPECT_EQ(copied_render_pass_id, copy_quad->render_pass_id);
@@ -219,7 +217,7 @@
   CREATE_QUAD_ALL_RP(RenderPassDrawQuad, render_pass_id, mask_resource_id,
                      mask_uv_rect, mask_texture_size, filters_scale,
                      filters_origin, tex_coord_rect, force_anti_aliasing_off,
-                     backdrop_filter_quality, copied_render_pass_id);
+                     copied_render_pass_id);
   EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material);
   EXPECT_EQ(copied_render_pass_id, copy_quad->render_pass_id);
   EXPECT_EQ(mask_resource_id, copy_quad->mask_resource_id());
@@ -523,7 +521,6 @@
   gfx::PointF filters_origin(0.f, 0.f);
   gfx::RectF tex_coord_rect(1.f, 1.f, 33.f, 19.f);
   bool force_anti_aliasing_off = false;
-  float backdrop_filter_quality = 1.0f;
 
   int copied_render_pass_id = 235;
 
@@ -531,8 +528,7 @@
   CREATE_QUAD_NEW_RP(RenderPassDrawQuad, visible_rect, render_pass_id,
                      mask_resource_id, mask_uv_rect, mask_texture_size,
                      filters_scale, filters_origin, tex_coord_rect,
-                     force_anti_aliasing_off, backdrop_filter_quality,
-                     copied_render_pass_id);
+                     force_anti_aliasing_off, copied_render_pass_id);
   EXPECT_EQ(mask_resource_id, quad_new->mask_resource_id());
   EXPECT_EQ(1, IterateAndCount(quad_new));
   EXPECT_EQ(mask_resource_id + 1, quad_new->mask_resource_id());
@@ -542,7 +538,7 @@
   quad_new->SetNew(shared_state, quad_rect, visible_rect, render_pass_id,
                    new_mask_resource_id, mask_uv_rect, mask_texture_size,
                    filters_scale, filters_origin, tex_coord_rect,
-                   force_anti_aliasing_off, backdrop_filter_quality);
+                   force_anti_aliasing_off);
   EXPECT_EQ(0, IterateAndCount(quad_new));
   EXPECT_EQ(0u, quad_new->mask_resource_id());
 }
diff --git a/components/viz/common/quads/render_pass_draw_quad.cc b/components/viz/common/quads/render_pass_draw_quad.cc
index 2eec14d..4bd6826 100644
--- a/components/viz/common/quads/render_pass_draw_quad.cc
+++ b/components/viz/common/quads/render_pass_draw_quad.cc
@@ -29,15 +29,13 @@
                                 const gfx::Vector2dF& filters_scale,
                                 const gfx::PointF& filters_origin,
                                 const gfx::RectF& tex_coord_rect,
-                                bool force_anti_aliasing_off,
-                                float backdrop_filter_quality) {
+                                bool force_anti_aliasing_off) {
   DCHECK(render_pass_id);
 
   bool needs_blending = true;
   SetAll(shared_quad_state, rect, visible_rect, needs_blending, render_pass_id,
          mask_resource_id, mask_uv_rect, mask_texture_size, filters_scale,
-         filters_origin, tex_coord_rect, force_anti_aliasing_off,
-         backdrop_filter_quality);
+         filters_origin, tex_coord_rect, force_anti_aliasing_off);
 }
 
 void RenderPassDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
@@ -51,8 +49,7 @@
                                 const gfx::Vector2dF& filters_scale,
                                 const gfx::PointF& filters_origin,
                                 const gfx::RectF& tex_coord_rect,
-                                bool force_anti_aliasing_off,
-                                float backdrop_filter_quality) {
+                                bool force_anti_aliasing_off) {
   DCHECK(render_pass_id);
 
   DrawQuad::SetAll(shared_quad_state, DrawQuad::RENDER_PASS, rect, visible_rect,
@@ -66,7 +63,6 @@
   this->filters_origin = filters_origin;
   this->tex_coord_rect = tex_coord_rect;
   this->force_anti_aliasing_off = force_anti_aliasing_off;
-  this->backdrop_filter_quality = backdrop_filter_quality;
 }
 
 const RenderPassDrawQuad* RenderPassDrawQuad::MaterialCast(
@@ -84,7 +80,6 @@
   cc::MathUtil::AddToTracedValue("mask_uv_rect", mask_uv_rect, value);
   cc::MathUtil::AddToTracedValue("tex_coord_rect", tex_coord_rect, value);
   value->SetBoolean("force_anti_aliasing_off", force_anti_aliasing_off);
-  value->SetDouble("backdrop_filter_quality", backdrop_filter_quality);
 }
 
 }  // namespace viz
diff --git a/components/viz/common/quads/render_pass_draw_quad.h b/components/viz/common/quads/render_pass_draw_quad.h
index fe641f9..c4e3f6de 100644
--- a/components/viz/common/quads/render_pass_draw_quad.h
+++ b/components/viz/common/quads/render_pass_draw_quad.h
@@ -37,8 +37,7 @@
               const gfx::Vector2dF& filters_scale,
               const gfx::PointF& filters_origin,
               const gfx::RectF& tex_coord_rect,
-              bool force_anti_aliasing_off,
-              float backdrop_filter_quality);
+              bool force_anti_aliasing_off);
 
   void SetAll(const SharedQuadState* shared_quad_state,
               const gfx::Rect& rect,
@@ -51,8 +50,7 @@
               const gfx::Vector2dF& filters_scale,
               const gfx::PointF& filters_origin,
               const gfx::RectF& tex_coord_rect,
-              bool force_anti_aliasing_off,
-              float backdrop_filter_quality);
+              bool force_anti_aliasing_off);
 
   RenderPassId render_pass_id;
   gfx::RectF mask_uv_rect;
@@ -72,8 +70,6 @@
 
   bool force_anti_aliasing_off;
 
-  float backdrop_filter_quality;
-
   ResourceId mask_resource_id() const {
     return resources.ids[kMaskResourceIdIndex];
   }
diff --git a/components/viz/common/quads/render_pass_unittest.cc b/components/viz/common/quads/render_pass_unittest.cc
index 34c7546..a501452 100644
--- a/components/viz/common/quads/render_pass_unittest.cc
+++ b/components/viz/common/quads/render_pass_unittest.cc
@@ -214,7 +214,7 @@
   pass_quad->SetNew(pass->shared_quad_state_list.back(), contrib_output_rect,
                     contrib_output_rect, contrib_id, 0, gfx::RectF(),
                     gfx::Size(), gfx::Vector2dF(), gfx::PointF(), gfx::RectF(),
-                    false, 1.0f);
+                    false);
 
   pass_list.push_back(std::move(pass));
   pass_list.push_back(std::move(contrib));
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc
index 40bf2c85..d4e8ccf2 100644
--- a/components/viz/service/display/display_unittest.cc
+++ b/components/viz/service/display/display_unittest.cc
@@ -2522,8 +2522,7 @@
     quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
     quad1->SetNew(shared_quad_state2, rect1, rect1, render_pass_id,
                   mask_resource_id, gfx::RectF(), gfx::Size(),
-                  gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false,
-                  1.0f);
+                  gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     EXPECT_EQ(1u, frame.render_pass_list.front()->quad_list.size());
     EXPECT_EQ(1u, frame.render_pass_list.at(1)->quad_list.size());
     display_->RemoveOverdrawQuads(&frame);
@@ -2768,10 +2767,10 @@
                                SkBlendMode::kSrcOver, 0);
     R1->SetNew(shared_quad_state, rect1, rect1, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     R2->SetNew(shared_quad_state, rect2, rect2, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     D1->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
     D2->SetNew(shared_quad_state4, rect4, rect4, SK_ColorBLACK, false);
     EXPECT_EQ(4u, frame.render_pass_list.front()->quad_list.size());
@@ -2816,10 +2815,10 @@
                                SkBlendMode::kSrcOver, 0);
     R1->SetNew(shared_quad_state, rect5, rect5, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     R2->SetNew(shared_quad_state, rect1, rect1, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     D1->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
     D2->SetNew(shared_quad_state4, rect6, rect6, SK_ColorBLACK, false);
     EXPECT_EQ(4u, frame.render_pass_list.front()->quad_list.size());
@@ -2863,10 +2862,10 @@
                                SkBlendMode::kSrcOver, 0);
     R1->SetNew(shared_quad_state, rect5, rect5, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     R2->SetNew(shared_quad_state, rect1, rect1, render_pass_id,
                mask_resource_id, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
     D1->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
     D2->SetNew(shared_quad_state4, rect7, rect7, SK_ColorBLACK, false);
     EXPECT_EQ(4u, frame.render_pass_list.front()->quad_list.size());
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 0095043a..5720d33 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -259,9 +259,6 @@
   // Filtered background texture.
   sk_sp<SkImage> background_image;
   GLuint background_image_id = 0;
-  // A multiplier for the temporary surface we create to apply the backdrop
-  // filter.
-  float backdrop_filter_quality = 1.0;
   // Whether the original background texture is needed for the mask.
   bool mask_for_background = false;
 };
@@ -808,8 +805,7 @@
     const cc::FilterOperations& backdrop_filters,
     uint32_t background_texture,
     const gfx::Rect& rect,
-    const gfx::Rect& unclipped_rect,
-    const float backdrop_filter_quality) {
+    const gfx::Rect& unclipped_rect) {
   DCHECK(ShouldApplyBackgroundFilters(quad, &backdrop_filters));
   auto use_gr_context = ScopedUseGrContext::Create(this);
 
@@ -838,12 +834,9 @@
     return nullptr;
   }
 
-  gfx::Rect quality_adjusted_rect =
-      ScaleToEnclosingRect(rect, backdrop_filter_quality);
-
   // Create surface to draw into.
-  SkImageInfo dst_info = SkImageInfo::MakeN32Premul(
-      quality_adjusted_rect.width(), quality_adjusted_rect.height());
+  SkImageInfo dst_info =
+      SkImageInfo::MakeN32Premul(rect.width(), rect.height());
   sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
       use_gr_context->context(), SkBudgeted::kYes, dst_info);
   if (!surface) {
@@ -857,17 +850,12 @@
   // to disable subnormal floats for performance and security reasons.
   cc::ScopedSubnormalFloatDisabler disabler;
   SkMatrix local_matrix;
-  local_matrix.setScale(quad->filters_scale.x() * backdrop_filter_quality,
-                        quad->filters_scale.y() * backdrop_filter_quality);
+  local_matrix.setScale(quad->filters_scale.x(), quad->filters_scale.y());
 
   SkPaint paint;
   paint.setImageFilter(filter->makeWithLocalMatrix(local_matrix));
-  surface->getCanvas()->translate(-quality_adjusted_rect.x(),
-                                  -quality_adjusted_rect.y());
-  surface->getCanvas()->drawImageRect(
-      src_image, SkRect::MakeWH(rect.width(), rect.height()),
-      RectToSkRect(quality_adjusted_rect), &paint);
-
+  surface->getCanvas()->translate(-rect.x(), -rect.y());
+  surface->getCanvas()->drawImage(src_image, rect.x(), rect.y(), &paint);
   // Flush the drawing before source texture read lock goes out of scope.
   // Skia API does not guarantee that when the SkImage goes out of scope,
   // its externally referenced resources would force the rendering to be
@@ -895,7 +883,6 @@
   params.window_matrix = current_frame()->window_matrix;
   params.projection_matrix = current_frame()->projection_matrix;
   params.tex_coord_rect = quad->tex_coord_rect;
-  params.backdrop_filter_quality = quad->backdrop_filter_quality;
   if (bypass != render_pass_bypass_quads_.end()) {
     TileDrawQuad* tile_quad = &bypass->second;
     // The projection matrix used by GLRenderer has a flip.  As tile texture
@@ -1047,8 +1034,7 @@
         // pixels' coordinate space.
         params->background_image = ApplyBackgroundFilters(
             quad, *params->backdrop_filters, params->background_texture,
-            params->background_rect, unclipped_rect,
-            params->backdrop_filter_quality);
+            params->background_rect, unclipped_rect);
         if (params->background_image) {
           params->background_image_id =
               GetGLTextureIDFromSkImage(params->background_image.get());
@@ -1366,8 +1352,6 @@
     if (params->background_image_id) {
       gl_->ActiveTexture(GL_TEXTURE0 + last_texture_unit);
       gl_->BindTexture(GL_TEXTURE_2D, params->background_image_id);
-      if (params->backdrop_filter_quality != 1.0f)
-        gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
       gl_->ActiveTexture(GL_TEXTURE0);
     }
     // If |mask_for_background| then we have both |background_image_id| and
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h
index 106de94..cd43cab 100644
--- a/components/viz/service/display/gl_renderer.h
+++ b/components/viz/service/display/gl_renderer.h
@@ -211,8 +211,7 @@
       const cc::FilterOperations& backdrop_filters,
       uint32_t background_texture,
       const gfx::Rect& rect,
-      const gfx::Rect& unclipped_rect,
-      const float backdrop_filter_quality);
+      const gfx::Rect& unclipped_rect);
 
   const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
 
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index 5a16c99..90cf582a5b4 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -1351,7 +1351,7 @@
       pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
   quad->SetNew(pass->shared_quad_state_list.back(), kOverlayRect, kOverlayRect,
                render_pass_id, 0, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+               gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
 
   CreateFullscreenCandidateQuad(
       resource_provider_.get(), child_resource_provider_.get(),
@@ -2641,7 +2641,7 @@
   child_pass1_rpdq->SetNew(child_pass1_sqs, unit_rect, unit_rect,
                            child_pass1_id, 0, gfx::RectF(), gfx::Size(),
                            gfx::Vector2dF(), gfx::PointF(),
-                           gfx::RectF(0, 0, 1, 1), false, 1.0f);
+                           gfx::RectF(0, 0, 1, 1), false);
 
   SharedQuadState* child_pass2_sqs =
       root_pass->shared_quad_state_list.ElementAt(1);
@@ -2654,7 +2654,7 @@
   child_pass2_rpdq->SetNew(child_pass2_sqs, unit_rect, unit_rect,
                            child_pass2_id, 0, gfx::RectF(), gfx::Size(),
                            gfx::Vector2dF(), gfx::PointF(),
-                           gfx::RectF(0, 0, 1, 1), false, 1.0f);
+                           gfx::RectF(0, 0, 1, 1), false);
 
   root_pass->damage_rect = gfx::Rect();
 
@@ -3424,7 +3424,7 @@
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadNoFilters) {
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
 
   EXPECT_EQ(1U, ca_layer_list_.size());
@@ -3445,7 +3445,7 @@
   render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
 
   EXPECT_EQ(1U, ca_layer_list_.size());
@@ -3456,7 +3456,7 @@
   render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
   EXPECT_EQ(1U, ca_layer_list_.size());
 }
@@ -3466,7 +3466,7 @@
   render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
   EXPECT_EQ(1U, ca_layer_list_.size());
 }
@@ -3477,7 +3477,7 @@
   render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
   EXPECT_EQ(1U, ca_layer_list_.size());
 }
@@ -3487,7 +3487,7 @@
   render_pass_backdrop_filters_[render_pass_id_] = &backdrop_filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
   EXPECT_EQ(0U, ca_layer_list_.size());
 }
@@ -3495,7 +3495,7 @@
 TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadMask) {
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 2, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
   EXPECT_EQ(1U, ca_layer_list_.size());
 }
@@ -3505,7 +3505,7 @@
   render_pass_filters_[render_pass_id_] = &filters_;
   quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                 kOverlayRect, render_pass_id_, 0, gfx::RectF(), gfx::Size(),
-                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
+                gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
   ProcessForOverlays();
   EXPECT_EQ(0U, ca_layer_list_.size());
 }
@@ -3518,8 +3518,7 @@
     auto* quad = pass_->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
     quad->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
                  kOverlayRect, render_pass_id_, 2, gfx::RectF(), gfx::Size(),
-                 gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false,
-                 1.0f);
+                 gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false);
   }
 
   ProcessForOverlays();
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index f11650ad..22ff9e6e 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -179,8 +179,7 @@
                gfx::Vector2dF(),  // filters scale
                gfx::PointF(),     // filter origin
                gfx::RectF(rect),  // tex_coord_rect
-               false,             // force_anti_aliasing_off
-               1.0f);             // backdrop_filter_quality
+               false);            // force_anti_aliasing_off
 }
 
 void CreateTestTwoColoredTextureDrawQuad(
@@ -1965,7 +1964,7 @@
   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
                            gfx::Vector2dF(), gfx::PointF(),
-                           gfx::RectF(pass_rect), false, 1.0f);
+                           gfx::RectF(pass_rect), false);
 
   RenderPassList pass_list;
   pass_list.push_back(std::move(child_pass));
@@ -2025,7 +2024,7 @@
   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
                            gfx::Vector2dF(), gfx::PointF(),
-                           gfx::RectF(pass_rect), false, 1.0f);
+                           gfx::RectF(pass_rect), false);
 
   RenderPassList pass_list;
   pass_list.push_back(std::move(child_pass));
@@ -2086,7 +2085,7 @@
   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
                            gfx::Vector2dF(), gfx::PointF(),
-                           gfx::RectF(pass_rect), false, 1.0f);
+                           gfx::RectF(pass_rect), false);
 
   RenderPassList pass_list;
   pass_list.push_back(std::move(child_pass));
@@ -2168,7 +2167,7 @@
   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
                            gfx::Vector2dF(), gfx::PointF(),
-                           gfx::RectF(pass_rect), false, 1.0f);
+                           gfx::RectF(pass_rect), false);
 
   RenderPassList pass_list;
 
@@ -2361,8 +2360,7 @@
       gfx::Vector2dF(),                          // filters scale
       gfx::PointF(),                             // filter origin
       gfx::RectF(sub_rect),                      // tex_coord_rect
-      false,                                     // force_anti_aliasing_off
-      1.0f);                                     // backdrop_filter_quality
+      false);                                    // force_anti_aliasing_off
   // White background behind the masked render pass.
   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   white->SetNew(root_pass_shared_state, viewport_rect, viewport_rect,
@@ -2458,8 +2456,7 @@
       gfx::Vector2dF(),                          // filters scale
       gfx::PointF(),                             // filter origin
       gfx::RectF(sub_rect),                      // tex_coord_rect
-      false,                                     // force_anti_aliasing_off
-      1.0f);                                     // backdrop_filter_quality
+      false);                                    // force_anti_aliasing_off
   // White background behind the masked render pass.
   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   white->SetNew(root_pass_shared_state, viewport_rect, viewport_rect,
@@ -2519,8 +2516,7 @@
                                gfx::Vector2dF(1.0f, 1.0f),  // filters_scale
                                gfx::PointF(),               // filters_origin
                                gfx::RectF(),                // tex_coord_rect
-                               false,  // force_anti_aliasing_off
-                               1.0f);  // backdrop_filter_quality
+                               false);  // force_anti_aliasing_off
     }
 
     const int kColumnWidth = device_viewport_rect.width() / 3;
@@ -2860,7 +2856,6 @@
 
   bool needs_blending = false;
   bool force_anti_aliasing_off = true;
-  float backdrop_filter_quality = 1.0f;
   gfx::Transform hole_pass_to_target_transform;
   hole_pass_to_target_transform.Translate(50, 50);
   hole_pass_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f),
@@ -2872,7 +2867,7 @@
   pass_quad->SetAll(pass_shared_state, rect, rect, needs_blending,
                     child_pass_id, 0, gfx::RectF(), gfx::Size(),
                     gfx::Vector2dF(), gfx::PointF(), gfx::RectF(rect),
-                    force_anti_aliasing_off, backdrop_filter_quality);
+                    force_anti_aliasing_off);
 
   gfx::Transform green_quad_to_target_transform;
   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
@@ -3040,7 +3035,7 @@
   child_pass_quad->SetNew(child_pass_shared_state, child_pass_rect,
                           child_pass_rect, child_pass_id, 0, gfx::RectF(),
                           gfx::Size(), gfx::Vector2dF(), gfx::PointF(),
-                          gfx::RectF(child_pass_rect), false, 1.0f);
+                          gfx::RectF(child_pass_rect), false);
 
   RenderPassList pass_list;
   pass_list.push_back(std::move(child_pass));
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index a759fe59..4b770ef 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -425,8 +425,7 @@
     quad->SetNew(shared_quad_state, scaled_rect, scaled_visible_rect,
                  remapped_pass_id, 0, gfx::RectF(), gfx::Size(),
                  gfx::Vector2dF(), gfx::PointF(), gfx::RectF(scaled_rect),
-                 /*force_anti_aliasing_off=*/false,
-                 /* backdrop_filter_quality*/ 1.0f);
+                 /*force_anti_aliasing_off=*/false);
   }
 
   // Need to re-query since referenced_surfaces_ iterators are not stable.
@@ -535,8 +534,7 @@
   quad->SetNew(shared_quad_state, output_rect, output_rect,
                root_render_pass->id, 0, gfx::RectF(), gfx::Size(),
                gfx::Vector2dF(), gfx::PointF(), gfx::RectF(output_rect),
-               /*force_anti_aliasing_off=*/false,
-               /*backdrop_filter_quality*/ 1.0f);
+               /*force_anti_aliasing_off=*/false);
   dest_pass_list_->push_back(std::move(color_conversion_pass));
 }
 
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index d020d39..5b53cff 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -328,7 +328,7 @@
     auto* quad = pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
     quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, 0,
                  gfx::RectF(), gfx::Size(), gfx::Vector2dF(), gfx::PointF(),
-                 gfx::RectF(), false, 1.0f);
+                 gfx::RectF(), false);
   }
 
  protected:
diff --git a/components/viz/test/data/rasp-grayator-half.png b/components/viz/test/data/rasp-grayator-half.png
new file mode 100644
index 0000000..a5a8126
--- /dev/null
+++ b/components/viz/test/data/rasp-grayator-half.png
Binary files differ
diff --git a/components/viz/test/data/rasp-grayator.png b/components/viz/test/data/rasp-grayator.png
new file mode 100644
index 0000000..1ca92be
--- /dev/null
+++ b/components/viz/test/data/rasp-grayator.png
Binary files differ
diff --git a/components/viz/test/surface_hittest_test_helpers.cc b/components/viz/test/surface_hittest_test_helpers.cc
index 11ebfff..8f2d32b 100644
--- a/components/viz/test/surface_hittest_test_helpers.cc
+++ b/components/viz/test/surface_hittest_test_helpers.cc
@@ -44,7 +44,7 @@
   render_pass_quad->SetNew(pass->shared_quad_state_list.back(), quad_rect,
                            quad_rect, render_pass_id, ResourceId(),
                            gfx::RectF(), gfx::Size(), gfx::Vector2dF(),
-                           gfx::PointF(), gfx::RectF(), false, 1.0f);
+                           gfx::PointF(), gfx::RectF(), false);
 }
 
 void CreateSurfaceDrawQuad(RenderPass* pass,
diff --git a/components/webdata/common/BUILD.gn b/components/webdata/common/BUILD.gn
index 3545829..9f192d1 100644
--- a/components/webdata/common/BUILD.gn
+++ b/components/webdata/common/BUILD.gn
@@ -67,6 +67,7 @@
     "//components/test/data/web_database/version_77.sql",
     "//components/test/data/web_database/version_78.sql",
     "//components/test/data/web_database/version_79.sql",
+    "//components/test/data/web_database/version_80.sql",
   ]
   outputs = [
     "{{bundle_resources_dir}}/" +
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc
index 76fd1406..1b78846 100644
--- a/components/webdata/common/web_database.cc
+++ b/components/webdata/common/web_database.cc
@@ -13,7 +13,7 @@
 // corresponding changes must happen in the unit tests, and new migration test
 // added.  See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
 // static
-const int WebDatabase::kCurrentVersionNumber = 80;
+const int WebDatabase::kCurrentVersionNumber = 81;
 
 const int WebDatabase::kDeprecatedVersionNumber = 51;
 
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index ed7589e..2f0dcc0 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -126,7 +126,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
 };
 
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 80;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 81;
 
 void WebDatabaseMigrationTest::LoadDatabase(
     const base::FilePath::StringType& file) {
@@ -1584,27 +1584,20 @@
     // Check version.
     EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
 
-    // Check that the AUTOFILL metadata is still there.
+    // Note: The migration to version 78 (which added the model_type column)
+    // used the wrong integer ID for the model_type. As a consequence, the later
+    // migration to version 81 deletes all the badly-migrated data (at that
+    // point, it'll most likely have been re-downloaded and stored under the
+    // correct ID, so no point in trying to salvage anything). As a consequence,
+    // there should now be no sync metadata in the database.
     sql::Statement s1(connection.GetUniqueStatement(
         "SELECT model_type, storage_key, value FROM autofill_sync_metadata"));
-    ASSERT_TRUE(s1.Step());
-    EXPECT_EQ(syncer::ModelTypeToHistogramInt(syncer::AUTOFILL),
-              s1.ColumnInt(0));
-    EXPECT_EQ("storage_key1", s1.ColumnString(1));
-    EXPECT_EQ("blob1", s1.ColumnString(2));
-    ASSERT_TRUE(s1.Step());
-    EXPECT_EQ(syncer::ModelTypeToHistogramInt(syncer::AUTOFILL),
-              s1.ColumnInt(0));
-    EXPECT_EQ("storage_key2", s1.ColumnString(1));
-    EXPECT_EQ("blob2", s1.ColumnString(2));
+    EXPECT_FALSE(s1.Step());
 
-    // Check that the AUTOFILL model_type_state is still there.
+    // The same applies for model type state.
     sql::Statement s2(connection.GetUniqueStatement(
         "SELECT model_type, value FROM autofill_model_type_state"));
-    ASSERT_TRUE(s2.Step());
-    EXPECT_EQ(syncer::ModelTypeToHistogramInt(syncer::AUTOFILL),
-              s2.ColumnInt(0));
-    EXPECT_EQ("state", s2.ColumnString(1));
+    EXPECT_FALSE(s2.Step());
   }
 }
 
@@ -1687,3 +1680,81 @@
     ASSERT_FALSE(s_profiles.Step());
   }
 }
+
+TEST_F(WebDatabaseMigrationTest, MigrateVersion80ToCurrent) {
+  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_80.sql")));
+
+  // Verify pre-conditions.
+  {
+    sql::Database connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+    sql::MetaTable meta_table;
+    ASSERT_TRUE(meta_table.Init(&connection, 80, 79));
+
+    sql::Statement s1(connection.GetUniqueStatement(
+        "SELECT model_type, storage_key, value FROM autofill_sync_metadata"));
+    ASSERT_TRUE(s1.Step());
+    // Note: This is the *wrong* ID for AUTOFILL, simulating the botched
+    // migration in version 78. See crbug.com/895826.
+    ASSERT_EQ(syncer::ModelTypeToHistogramInt(syncer::AUTOFILL),
+              s1.ColumnInt(0));
+    ASSERT_EQ("storage_key1", s1.ColumnString(1));
+    ASSERT_EQ("blob1", s1.ColumnString(2));
+
+    ASSERT_TRUE(s1.Step());
+    // Note: This is the *correct* ID for AUTOFILL, simulating the data that got
+    // redownloaded after the bad migration, and stored under the correct ID.
+    ASSERT_EQ(syncer::ModelTypeToStableIdentifier(syncer::AUTOFILL),
+              s1.ColumnInt(0));
+    ASSERT_EQ("storage_key2", s1.ColumnString(1));
+    ASSERT_EQ("blob2", s1.ColumnString(2));
+
+    sql::Statement s2(connection.GetUniqueStatement(
+        "SELECT model_type, value FROM autofill_model_type_state"));
+    ASSERT_TRUE(s2.Step());
+    // Like above: Bad value.
+    ASSERT_EQ(syncer::ModelTypeToHistogramInt(syncer::AUTOFILL),
+              s2.ColumnInt(0));
+    ASSERT_EQ("state1", s2.ColumnString(1));
+    ASSERT_TRUE(s2.Step());
+    // Good value.
+    ASSERT_EQ(syncer::ModelTypeToStableIdentifier(syncer::AUTOFILL),
+              s2.ColumnInt(0));
+    ASSERT_EQ("state2", s2.ColumnString(1));
+  }
+
+  DoMigration();
+
+  // Verify post-conditions.
+  {
+    sql::Database connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+    // Check version.
+    EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+    // Check that the badly-migrated AUTOFILL data from version 78 is gone, but
+    // the correct redownloaded data is still here.
+    sql::Statement s1(connection.GetUniqueStatement(
+        "SELECT model_type, storage_key, value FROM autofill_sync_metadata"));
+    ASSERT_TRUE(s1.Step());
+    EXPECT_EQ(syncer::ModelTypeToStableIdentifier(syncer::AUTOFILL),
+              s1.ColumnInt(0));
+    EXPECT_EQ("storage_key2", s1.ColumnString(1));
+    EXPECT_EQ("blob2", s1.ColumnString(2));
+    EXPECT_FALSE(s1.Step());
+
+    // Check that the badly-migrated AUTOFILL model type state from version 78
+    // is gone, but the correct redownloaded state is still here.
+    sql::Statement s2(connection.GetUniqueStatement(
+        "SELECT model_type, value FROM autofill_model_type_state"));
+    ASSERT_TRUE(s2.Step());
+    EXPECT_EQ(syncer::ModelTypeToStableIdentifier(syncer::AUTOFILL),
+              s2.ColumnInt(0));
+    EXPECT_EQ("state2", s2.ColumnString(1));
+    EXPECT_FALSE(s2.Step());
+  }
+}
diff --git a/content/browser/android/tracing_controller_android.cc b/content/browser/android/tracing_controller_android.cc
index 406bc01..b1b34ee 100644
--- a/content/browser/android/tracing_controller_android.cc
+++ b/content/browser/android/tracing_controller_android.cc
@@ -14,7 +14,7 @@
 #include "base/trace_event/trace_event.h"
 #include "content/browser/tracing/tracing_controller_impl.h"
 #include "content/public/browser/tracing_controller.h"
-#include "jni/TracingControllerAndroid_jni.h"
+#include "jni/TracingControllerAndroidImpl_jni.h"
 
 using base::android::JavaParamRef;
 using base::android::ScopedJavaLocalRef;
@@ -22,7 +22,7 @@
 
 namespace content {
 
-static jlong JNI_TracingControllerAndroid_Init(
+static jlong JNI_TracingControllerAndroidImpl_Init(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
   TracingControllerAndroid* profiler = new TracingControllerAndroid(env, obj);
@@ -85,7 +85,7 @@
     base::FilePath* file_path) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jstring> jfilename =
-      Java_TracingControllerAndroid_generateTracingFilePath(env);
+      Java_TracingControllerAndroidImpl_generateTracingFilePath(env);
   *file_path = base::FilePath(
       base::android::ConvertJavaStringToUTF8(env, jfilename.obj()));
 }
@@ -95,7 +95,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
   if (obj.obj())
-    Java_TracingControllerAndroid_onTracingStopped(env, obj, callback);
+    Java_TracingControllerAndroidImpl_onTracingStopped(env, obj, callback);
 }
 
 bool TracingControllerAndroid::GetKnownCategoriesAsync(
@@ -128,13 +128,13 @@
                                              categories_received.end());
     base::android::ScopedJavaLocalRef<jobjectArray> jcategories =
         base::android::ToJavaArrayOfStrings(env, category_vector);
-    Java_TracingControllerAndroid_onKnownCategoriesReceived(
+    Java_TracingControllerAndroidImpl_onKnownCategoriesReceived(
         env, obj, jcategories, callback);
   }
 }
 
 static ScopedJavaLocalRef<jstring>
-JNI_TracingControllerAndroid_GetDefaultCategories(
+JNI_TracingControllerAndroidImpl_GetDefaultCategories(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
   base::trace_event::TraceConfig trace_config;
@@ -159,7 +159,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
   if (obj.obj()) {
-    Java_TracingControllerAndroid_onTraceBufferUsageReceived(
+    Java_TracingControllerAndroidImpl_onTraceBufferUsageReceived(
         env, obj, percent_full, approximate_event_count, callback);
   }
 }
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index fb8756e7..17336c9 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -338,18 +338,6 @@
   return platform_view_->GetSelectedText();
 }
 
-base::string16 RenderWidgetHostViewGuest::GetSurroundingText() {
-  return platform_view_->GetSurroundingText();
-}
-
-gfx::Range RenderWidgetHostViewGuest::GetSelectedRange() {
-  return platform_view_->GetSelectedRange();
-}
-
-size_t RenderWidgetHostViewGuest::GetOffsetForSurroundingText() {
-  return platform_view_->GetOffsetForSurroundingText();
-}
-
 void RenderWidgetHostViewGuest::SetNeedsBeginFrames(bool needs_begin_frames) {
   if (platform_view_)
     platform_view_->SetNeedsBeginFrames(needs_begin_frames);
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h
index dc91081..d78f279 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -79,9 +79,6 @@
   gfx::Rect GetBoundsInRootWindow() override;
   gfx::Size GetCompositorViewportPixelSize() const override;
   base::string16 GetSelectedText() override;
-  base::string16 GetSurroundingText() override;
-  gfx::Range GetSelectedRange() override;
-  size_t GetOffsetForSurroundingText() override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override;
   TouchSelectionControllerClientManager*
   GetTouchSelectionControllerClientManager() override;
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc
index 835b0d6..dca7e67 100644
--- a/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -319,6 +319,42 @@
                       expected_scroll_position_after_scroll);
   }
 
+  void DoTwoFingerPan() {
+    DCHECK(URLLoaded());
+
+    const std::string pointer_actions_json = R"HTML(
+        [{"source": "touch", "id": 0,
+              "actions": [
+                { "name": "pointerDown", "x": 10, "y": 125 },
+                { "name": "pointerMove", "x": 10, "y": 155 },
+                { "name": "pointerUp" }]},
+             {"source": "touch", "id": 1,
+              "actions": [
+                { "name": "pointerDown", "x": 15, "y": 125 },
+                { "name": "pointerMove", "x": 15, "y": 155 },
+                { "name": "pointerUp"}]}]
+        )HTML";
+
+    base::JSONReader json_reader;
+    std::unique_ptr<base::Value> params =
+        json_reader.ReadToValue(pointer_actions_json);
+    ASSERT_TRUE(params.get()) << json_reader.GetErrorMessage();
+    ActionsParser actions_parser(params.get());
+
+    ASSERT_TRUE(actions_parser.ParsePointerActionSequence());
+
+    run_loop_ = std::make_unique<base::RunLoop>();
+
+    GetWidgetHost()->QueueSyntheticGesture(
+        SyntheticGesture::Create(actions_parser.gesture_params()),
+        base::BindOnce(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
+                       base::Unretained(this)));
+
+    // Runs until we get the OnSyntheticGestureCompleted callback
+    run_loop_->Run();
+    run_loop_.reset();
+  }
+
   // Generate touch events for a double tap and drag zoom gesture at
   // coordinates (50, 50).
   void DoDoubleTapDragZoom() {
@@ -358,7 +394,6 @@
     run_loop_.reset();
   }
 
- private:
   void CheckScrollOffset(
       bool wait_until_scrolled,
       const gfx::Vector2d& expected_scroll_position_after_scroll) {
@@ -390,6 +425,7 @@
     EXPECT_LE(expected_scroll_position_after_scroll.x() / 2, scroll_left);
   }
 
+ private:
   std::unique_ptr<RenderFrameSubmissionObserver> frame_observer_;
   std::unique_ptr<base::RunLoop> run_loop_;
 
@@ -574,6 +610,21 @@
                 gfx::Vector2d(45, 0), kShortJankTime);
 }
 
+// TODO(crbug.com/899005): Make this test work on Android.
+#if defined(OS_ANDROID)
+#define MAYBE_TwoFingerPanYDisallowed DISABLED_TwoFingerPanYDisallowed
+#else
+#define MAYBE_TwoFingerPanYDisallowed TwoFingerPanYDisallowed
+#endif
+// Test that two finger panning is treated as pinch zoom and is disallowed when
+// touching the pan-y area.
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TwoFingerPanYDisallowed) {
+  LoadURL(kTouchActionURLWithOverlapArea);
+
+  DoTwoFingerPan();
+  CheckScrollOffset(true, gfx::Vector2d(0, 0));
+}
+
 namespace {
 
 const std::string kDoubleTapZoomDataURL = R"HTML(
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc
index d4d3134..2010ea3c 100644
--- a/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -36,11 +36,7 @@
 
 }  // namespace
 
-TouchActionFilter::TouchActionFilter()
-    : suppress_manipulation_events_(false),
-      drop_current_tap_ending_event_(false),
-      allow_current_double_tap_event_(true),
-      force_enable_zoom_(false) {
+TouchActionFilter::TouchActionFilter() {
   ResetTouchAction();
 }
 
@@ -55,31 +51,29 @@
   // can decide to send a touch cancel event).
   switch (gesture_event->GetType()) {
     case WebInputEvent::kGestureScrollBegin: {
-      DCHECK(!suppress_manipulation_events_);
+      DCHECK(!drop_scroll_events_);
       // In VR or virtual keyboard (https://crbug.com/880701),
       // GestureScrollBegin could come without GestureTapDown.
       if (!gesture_sequence_in_progress_) {
         gesture_sequence_in_progress_ = true;
-        if (!scrolling_touch_action_.has_value())
+        if (!active_touch_action_.has_value())
           SetTouchAction(cc::kTouchActionAuto);
       }
-      gesture_scroll_in_progress_ = true;
       gesture_sequence_.append("B");
-      if (!scrolling_touch_action_.has_value()) {
+      if (!active_touch_action_.has_value()) {
         static auto* crash_key = base::debug::AllocateCrashKeyString(
             "scrollbegin-gestures", base::debug::CrashKeySize::Size256);
         base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
         gesture_sequence_.clear();
       }
-      suppress_manipulation_events_ =
-          ShouldSuppressManipulation(*gesture_event);
-      return suppress_manipulation_events_
+      drop_scroll_events_ = ShouldSuppressScrolling(*gesture_event);
+      return drop_scroll_events_
                  ? FilterGestureEventResult::kFilterGestureEventFiltered
                  : FilterGestureEventResult::kFilterGestureEventAllowed;
     }
 
     case WebInputEvent::kGestureScrollUpdate: {
-      if (suppress_manipulation_events_)
+      if (drop_scroll_events_)
         return FilterGestureEventResult::kFilterGestureEventFiltered;
 
       gesture_sequence_.append("U");
@@ -91,16 +85,16 @@
       // two-finger scrolling but a "touch-action: pan-x pinch-zoom" region
       // doesn't.
       // TODO(mustaq): Add it to spec?
-      if (!scrolling_touch_action_.has_value()) {
+      if (!active_touch_action_.has_value()) {
         static auto* crash_key = base::debug::AllocateCrashKeyString(
             "scrollupdate-gestures", base::debug::CrashKeySize::Size256);
         base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
         gesture_sequence_.clear();
       }
-      if (IsYAxisActionDisallowed(scrolling_touch_action_.value())) {
+      if (IsYAxisActionDisallowed(active_touch_action_.value())) {
         gesture_event->data.scroll_update.delta_y = 0;
         gesture_event->data.scroll_update.velocity_y = 0;
-      } else if (IsXAxisActionDisallowed(scrolling_touch_action_.value())) {
+      } else if (IsXAxisActionDisallowed(active_touch_action_.value())) {
         gesture_event->data.scroll_update.delta_x = 0;
         gesture_event->data.scroll_update.velocity_x = 0;
       }
@@ -115,40 +109,24 @@
 
     case WebInputEvent::kGestureScrollEnd:
       gesture_sequence_.clear();
-      gesture_scroll_in_progress_ = false;
       gesture_sequence_in_progress_ = false;
-      ReportGestureEventFiltered(suppress_manipulation_events_);
-      return FilterManipulationEventAndResetState()
-                 ? FilterGestureEventResult::kFilterGestureEventFiltered
-                 : FilterGestureEventResult::kFilterGestureEventAllowed;
+      ReportGestureEventFiltered(drop_scroll_events_);
+      return FilterScrollEventAndResetState();
 
+    // Evaluate the |drop_pinch_events_| here instead of GSB because pinch
+    // events could arrive without GSB, e.g. double-tap-drag.
     case WebInputEvent::kGesturePinchBegin:
-      if (!gesture_scroll_in_progress_) {
-        suppress_manipulation_events_ =
-            ShouldSuppressManipulation(*gesture_event);
-      }
+      drop_pinch_events_ =
+          (active_touch_action_.value() & cc::kTouchActionPinchZoom) == 0;
       FALLTHROUGH;
     case WebInputEvent::kGesturePinchUpdate:
       gesture_sequence_.append("P");
-      ReportGestureEventFiltered(suppress_manipulation_events_);
-      return suppress_manipulation_events_
+      return drop_pinch_events_
                  ? FilterGestureEventResult::kFilterGestureEventFiltered
                  : FilterGestureEventResult::kFilterGestureEventAllowed;
     case WebInputEvent::kGesturePinchEnd:
-      ReportGestureEventFiltered(suppress_manipulation_events_);
-      // If we're in a double-tap and drag zoom, we won't be bracketed between
-      // a GSB/GSE pair so end the sequence now. Otherwise this will happen
-      // when we get the GSE.
-      if (!gesture_scroll_in_progress_) {
-        gesture_sequence_.clear();
-        gesture_sequence_in_progress_ = false;
-        return FilterManipulationEventAndResetState()
-                   ? FilterGestureEventResult::kFilterGestureEventFiltered
-                   : FilterGestureEventResult::kFilterGestureEventAllowed;
-      }
-      return suppress_manipulation_events_
-                 ? FilterGestureEventResult::kFilterGestureEventFiltered
-                 : FilterGestureEventResult::kFilterGestureEventAllowed;
+      ReportGestureEventFiltered(drop_pinch_events_);
+      return FilterPinchEventAndResetState();
 
     // The double tap gesture is a tap ending event. If a double-tap gesture is
     // filtered out, replace it with a tap event but preserve the tap-count to
@@ -174,14 +152,14 @@
     case WebInputEvent::kGestureTapUnconfirmed: {
       gesture_sequence_.append("C");
       DCHECK_EQ(1, gesture_event->data.tap.tap_count);
-      if (!scrolling_touch_action_.has_value()) {
+      if (!active_touch_action_.has_value()) {
         static auto* crash_key = base::debug::AllocateCrashKeyString(
             "tapunconfirmed-gestures", base::debug::CrashKeySize::Size256);
         base::debug::SetCrashKeyString(crash_key, gesture_sequence_);
         gesture_sequence_.clear();
       }
-      allow_current_double_tap_event_ = (scrolling_touch_action_.value() &
-                                         cc::kTouchActionDoubleTapZoom) != 0;
+      allow_current_double_tap_event_ =
+          (active_touch_action_.value() & cc::kTouchActionDoubleTapZoom) != 0;
       if (!allow_current_double_tap_event_) {
         gesture_event->SetType(WebInputEvent::kGestureTap);
         drop_current_tap_ending_event_ = true;
@@ -215,8 +193,8 @@
       if (gesture_event->is_source_touch_event_set_non_blocking ||
           num_of_active_touches_ <= 0)
         SetTouchAction(cc::kTouchActionAuto);
-      scrolling_touch_action_ = allowed_touch_action_;
-      if (scrolling_touch_action_.has_value())
+      active_touch_action_ = allowed_touch_action_;
+      if (active_touch_action_.has_value())
         gesture_sequence_.append("OY");
       else
         gesture_sequence_.append("ON");
@@ -241,20 +219,28 @@
 
 void TouchActionFilter::SetTouchAction(cc::TouchAction touch_action) {
   allowed_touch_action_ = touch_action;
-  scrolling_touch_action_ = allowed_touch_action_;
+  active_touch_action_ = allowed_touch_action_;
 }
 
-bool TouchActionFilter::FilterManipulationEventAndResetState() {
-  if (suppress_manipulation_events_) {
-    suppress_manipulation_events_ = false;
-    return true;
+FilterGestureEventResult TouchActionFilter::FilterPinchEventAndResetState() {
+  if (drop_pinch_events_) {
+    drop_pinch_events_ = false;
+    return FilterGestureEventResult::kFilterGestureEventFiltered;
   }
-  return false;
+  return FilterGestureEventResult::kFilterGestureEventAllowed;
+}
+
+FilterGestureEventResult TouchActionFilter::FilterScrollEventAndResetState() {
+  if (drop_scroll_events_) {
+    drop_scroll_events_ = false;
+    return FilterGestureEventResult::kFilterGestureEventFiltered;
+  }
+  return FilterGestureEventResult::kFilterGestureEventAllowed;
 }
 
 void TouchActionFilter::ForceResetTouchActionForTest() {
   allowed_touch_action_.reset();
-  scrolling_touch_action_.reset();
+  active_touch_action_.reset();
 }
 
 void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) {
@@ -280,7 +266,7 @@
     allowed_touch_action_ =
         allowed_touch_action_.value() | cc::kTouchActionPinchZoom;
   }
-  scrolling_touch_action_ = allowed_touch_action_;
+  active_touch_action_ = allowed_touch_action_;
 }
 
 void TouchActionFilter::IncreaseActiveTouches() {
@@ -308,11 +294,11 @@
   // must add one to the upper bound to be able to visualize the number of
   // times |cc::kTouchActionAuto| is hit.
   // https://crbug.com/879511, remove this temporary fix.
-  if (!scrolling_touch_action_.has_value())
+  if (!active_touch_action_.has_value())
     return;
 
   UMA_HISTOGRAM_ENUMERATION("TouchAction.EffectiveTouchAction",
-                            scrolling_touch_action_.value(),
+                            active_touch_action_.value(),
                             cc::kTouchActionMax + 1);
 
   // Report how often the effective touch action computed by blink is or is
@@ -321,7 +307,7 @@
   if (white_listed_touch_action_.has_value()) {
     UMA_HISTOGRAM_BOOLEAN(
         "TouchAction.EquivalentEffectiveAndWhiteListed",
-        scrolling_touch_action_.value() == white_listed_touch_action_.value());
+        active_touch_action_.value() == white_listed_touch_action_.value());
   }
 }
 
@@ -358,20 +344,15 @@
   }
 }
 
-bool TouchActionFilter::ShouldSuppressManipulation(
+bool TouchActionFilter::ShouldSuppressScrolling(
     const blink::WebGestureEvent& gesture_event) {
-  DCHECK(gesture_event.GetType() == WebInputEvent::kGestureScrollBegin ||
-         WebInputEvent::IsPinchGestureEventType(gesture_event.GetType()));
-
-  if (WebInputEvent::IsPinchGestureEventType(gesture_event.GetType())) {
-    return (scrolling_touch_action_.value() & cc::kTouchActionPinchZoom) == 0;
-  }
+  DCHECK(gesture_event.GetType() == WebInputEvent::kGestureScrollBegin);
 
   if (gesture_event.data.scroll_begin.pointer_count >= 2) {
     // Any GestureScrollBegin with more than one fingers is like a pinch-zoom
     // for touch-actions, see crbug.com/632525. Therefore, we switch to
     // blocked-manipulation mode iff pinch-zoom is disallowed.
-    return (scrolling_touch_action_.value() & cc::kTouchActionPinchZoom) == 0;
+    return (active_touch_action_.value() & cc::kTouchActionPinchZoom) == 0;
   }
 
   const float& deltaXHint = gesture_event.data.scroll_begin.delta_x_hint;
@@ -398,8 +379,7 @@
   }
   DCHECK(minimal_conforming_touch_action != cc::kTouchActionNone);
 
-  return (scrolling_touch_action_.value() & minimal_conforming_touch_action) ==
-         0;
+  return (active_touch_action_.value() & minimal_conforming_touch_action) == 0;
 }
 
 void TouchActionFilter::OnHasTouchEventHandlers(bool has_handlers) {
@@ -419,7 +399,7 @@
   if (!gesture_sequence_in_progress_ && num_of_active_touches_ <= 0) {
     ResetTouchAction();
     if (has_touch_event_handler_)
-      scrolling_touch_action_.reset();
+      active_touch_action_.reset();
   }
 }
 
diff --git a/content/browser/renderer_host/input/touch_action_filter.h b/content/browser/renderer_host/input/touch_action_filter.h
index 5796ae035..b7a76a5 100644
--- a/content/browser/renderer_host/input/touch_action_filter.h
+++ b/content/browser/renderer_host/input/touch_action_filter.h
@@ -75,27 +75,31 @@
   friend class TouchActionFilterPinchTest;
   friend class SitePerProcessBrowserTouchActionTest;
 
-  bool ShouldSuppressManipulation(const blink::WebGestureEvent&);
-  bool FilterManipulationEventAndResetState();
+  bool ShouldSuppressScrolling(const blink::WebGestureEvent&);
+  FilterGestureEventResult FilterScrollEventAndResetState();
+  FilterGestureEventResult FilterPinchEventAndResetState();
   void ReportTouchAction();
   void ResetTouchAction();
   void SetTouchAction(cc::TouchAction touch_action);
 
-  // Whether scroll and pinch gestures should be discarded due to touch-action.
-  bool suppress_manipulation_events_;
+  // Whether scroll gestures should be discarded due to touch-action.
+  bool drop_scroll_events_ = false;
+
+  // Whether pinch gestures should be discarded due to touch-action.
+  bool drop_pinch_events_ = false;
 
   // Whether a tap ending event in this sequence should be discarded because a
   // previous GestureTapUnconfirmed event was turned into a GestureTap.
-  bool drop_current_tap_ending_event_;
+  bool drop_current_tap_ending_event_ = false;
 
   // True iff the touch action of the last TapUnconfirmed or Tap event was
   // TOUCH_ACTION_AUTO. The double tap event depends on the touch action of the
   // previous tap or tap unconfirmed. Only valid between a TapUnconfirmed or Tap
   // and the next DoubleTap.
-  bool allow_current_double_tap_event_;
+  bool allow_current_double_tap_event_ = true;
 
   // Force enable zoom for Accessibility.
-  bool force_enable_zoom_;
+  bool force_enable_zoom_ = false;
 
   // Indicates whether this page has touch event handler or not. Set by
   // InputRouterImpl::OnHasTouchEventHandlers. Default to false because one
@@ -107,20 +111,17 @@
   // before GSE.
   bool gesture_sequence_in_progress_ = false;
 
-  // True if we're between a GSB and a GSE.
-  bool gesture_scroll_in_progress_ = false;
-
   // Increment at receiving ACK for touch start and decrement at touch end.
   int num_of_active_touches_ = 0;
 
   // What touch actions are currently permitted.
   base::Optional<cc::TouchAction> allowed_touch_action_;
 
-  // The touch action that is used for the current scrolling gesture sequence.
-  // At the touch sequence end, the |allowed_touch_action| is reset while this
-  // remains set as the effective touch action, for the still in progress scroll
+  // The touch action that is used for the current gesture sequence. At the
+  // touch sequence end, the |allowed_touch_action_| is reset while this remains
+  // set as the effective touch action, for the still in progress gesture
   // sequence due to fling.
-  base::Optional<cc::TouchAction> scrolling_touch_action_;
+  base::Optional<cc::TouchAction> active_touch_action_;
 
   // Whitelisted touch action received from the compositor.
   base::Optional<cc::TouchAction> white_listed_touch_action_;
diff --git a/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/content/browser/renderer_host/input/touch_action_filter_unittest.cc
index c7abd1c..a1ba212 100644
--- a/content/browser/renderer_host/input/touch_action_filter_unittest.cc
+++ b/content/browser/renderer_host/input/touch_action_filter_unittest.cc
@@ -27,7 +27,7 @@
 
  protected:
   base::Optional<cc::TouchAction> ScrollingTouchAction() const {
-    return filter_.scrolling_touch_action_;
+    return filter_.active_touch_action_;
   }
   void ResetTouchAction() { filter_.ResetTouchAction(); }
   void PanTest(cc::TouchAction action,
@@ -635,6 +635,14 @@
               FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
               FilterGestureEventResult::kFilterGestureEventAllowed);
+    EXPECT_FALSE(filter_.drop_pinch_events_);
+    // The pinch gesture is always re-evaluated on pinch begin.
+    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
+              FilterGestureEventResult::kFilterGestureEventAllowed);
+    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
+              FilterGestureEventResult::kFilterGestureEventAllowed);
+    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
+              FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
               FilterGestureEventResult::kFilterGestureEventAllowed);
     filter_.DecreaseActiveTouches();
@@ -657,62 +665,15 @@
               FilterGestureEventResult::kFilterGestureEventAllowed);
     filter_.DecreaseActiveTouches();
 
-    // Pinching is only computed at GestureScrollBegin time.
     filter_.ResetTouchAction();
     filter_.OnSetTouchAction(cc::kTouchActionAuto);
     filter_.IncreaseActiveTouches();
-    EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
               FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
               FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
               FilterGestureEventResult::kFilterGestureEventAllowed);
-    filter_.OnSetTouchAction(cc::kTouchActionNone);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    filter_.OnSetTouchAction(cc::kTouchActionAuto);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    filter_.DecreaseActiveTouches();
-
-    // Once a pinch has started, any change in state won't affect the pinch
-    // gestures since it is computed in GestureScrollBegin.
-    filter_.ResetTouchAction();
-    filter_.OnSetTouchAction(cc::kTouchActionAuto);
-    filter_.IncreaseActiveTouches();
-    EXPECT_EQ(filter_.FilterGestureEvent(&tap_down),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    filter_.OnSetTouchAction(cc::kTouchActionNone);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
-    EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
-              FilterGestureEventResult::kFilterGestureEventAllowed);
     filter_.DecreaseActiveTouches();
 
     // Scrolling is allowed when two fingers are down.
@@ -733,8 +694,9 @@
               FilterGestureEventResult::kFilterGestureEventAllowed);
     filter_.DecreaseActiveTouches();
 
-    // A pinch event sequence with only one pointer is equivalent to a scroll
-    // gesture, so disallowed as a pinch gesture.
+    // At double-tap-drag-zoom case, the pointer_count is 1 at GesturePinchBegin
+    // and we need to evaluate whether the gesture is allowed or not at that
+    // time.
     scroll_begin.data.scroll_begin.pointer_count = 1;
     filter_.ResetTouchAction();
     filter_.OnSetTouchAction(cc::kTouchActionPinchZoom);
@@ -744,11 +706,11 @@
     EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
               FilterGestureEventResult::kFilterGestureEventFiltered);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
-              FilterGestureEventResult::kFilterGestureEventFiltered);
+              FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
-              FilterGestureEventResult::kFilterGestureEventFiltered);
+              FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
-              FilterGestureEventResult::kFilterGestureEventFiltered);
+              FilterGestureEventResult::kFilterGestureEventAllowed);
     EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
               FilterGestureEventResult::kFilterGestureEventFiltered);
     filter_.DecreaseActiveTouches();
@@ -1235,6 +1197,46 @@
   EXPECT_EQ(ScrollingTouchAction().value(), cc::kTouchActionAuto);
 }
 
+// Regression test for crbug.com/771330. One can start one finger panning y, and
+// add another finger to pinch zooming. The pinch zooming should not be allowed
+// if the allowed touch action doesn't allow it.
+TEST_F(TouchActionFilterTest, PinchZoomStartsWithOneFingerPanDisallowed) {
+  filter_.OnHasTouchEventHandlers(true);
+  filter_.OnSetTouchAction(cc::kTouchActionPanY);
+  WebGestureEvent scroll_begin =
+      SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 3, kSourceDevice);
+  WebGestureEvent scroll_update =
+      SyntheticWebGestureEventBuilder::BuildScrollUpdate(5, 10, 0,
+                                                         kSourceDevice);
+  WebGestureEvent pinch_begin = SyntheticWebGestureEventBuilder::Build(
+      WebInputEvent::kGesturePinchBegin, kSourceDevice);
+  WebGestureEvent pinch_update =
+      SyntheticWebGestureEventBuilder::BuildPinchUpdate(1.2f, 5, 5, 0,
+                                                        kSourceDevice);
+  WebGestureEvent pinch_end = SyntheticWebGestureEventBuilder::Build(
+      WebInputEvent::kGesturePinchEnd, kSourceDevice);
+  WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build(
+      WebInputEvent::kGestureScrollEnd, kSourceDevice);
+  EXPECT_EQ(filter_.FilterGestureEvent(&scroll_begin),
+            FilterGestureEventResult::kFilterGestureEventAllowed);
+  EXPECT_EQ(filter_.FilterGestureEvent(&scroll_update),
+            FilterGestureEventResult::kFilterGestureEventAllowed);
+  EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
+            FilterGestureEventResult::kFilterGestureEventFiltered);
+  EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
+            FilterGestureEventResult::kFilterGestureEventFiltered);
+  EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
+            FilterGestureEventResult::kFilterGestureEventFiltered);
+  EXPECT_EQ(filter_.FilterGestureEvent(&pinch_begin),
+            FilterGestureEventResult::kFilterGestureEventFiltered);
+  EXPECT_EQ(filter_.FilterGestureEvent(&pinch_update),
+            FilterGestureEventResult::kFilterGestureEventFiltered);
+  EXPECT_EQ(filter_.FilterGestureEvent(&pinch_end),
+            FilterGestureEventResult::kFilterGestureEventFiltered);
+  EXPECT_EQ(filter_.FilterGestureEvent(&scroll_end),
+            FilterGestureEventResult::kFilterGestureEventAllowed);
+}
+
 TEST_F(TouchActionFilterTest, ScrollBeginWithoutTapDownWithKnownTouchAction) {
   filter_.OnHasTouchEventHandlers(true);
   EXPECT_FALSE(ScrollingTouchAction().has_value());
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index ae9853a66..79ac33c 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -21,7 +21,6 @@
 #include "third_party/blink/public/platform/web_drag_operation.h"
 #include "third_party/blink/public/platform/web_input_event.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/range/range.h"
 
 namespace blink {
 class WebMouseEvent;
@@ -157,12 +156,6 @@
   // currently focused frame.
   virtual void SelectRange(const gfx::Point& base, const gfx::Point& extent) {}
 
-#if defined(OS_MACOSX)
-  virtual void DidChangeTextSelection(const base::string16& text,
-                                      const gfx::Range& range,
-                                      size_t offset) {}
-#endif
-
   // Request the renderer to Move the caret to the new position.
   virtual void MoveCaret(const gfx::Point& extent) {}
 
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 4163b36..986a78b 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -299,24 +299,6 @@
   return GetTextInputManager()->GetTextSelection(this)->selected_text();
 }
 
-base::string16 RenderWidgetHostViewBase::GetSurroundingText() {
-  if (!GetTextInputManager())
-    return base::string16();
-  return GetTextInputManager()->GetTextSelection(this)->text();
-}
-
-gfx::Range RenderWidgetHostViewBase::GetSelectedRange() {
-  if (!GetTextInputManager())
-    return gfx::Range();
-  return GetTextInputManager()->GetTextSelection(this)->range();
-}
-
-size_t RenderWidgetHostViewBase::GetOffsetForSurroundingText() {
-  if (!GetTextInputManager())
-    return 0;
-  return GetTextInputManager()->GetTextSelection(this)->offset();
-}
-
 void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
   DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
          SkColorGetA(color) == SK_AlphaTRANSPARENT);
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 7163d2b..0dd9895 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -116,9 +116,6 @@
   void WasOccluded() override {}
   void SetIsInVR(bool is_in_vr) override;
   base::string16 GetSelectedText() override;
-  base::string16 GetSurroundingText() override;
-  gfx::Range GetSelectedRange() override;
-  size_t GetOffsetForSurroundingText() override;
   bool IsMouseLocked() override;
   bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
   void SetBackgroundColor(SkColor color) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.h b/content/browser/renderer_host/render_widget_host_view_cocoa.h
index fc0105d..12e531d 100644
--- a/content/browser/renderer_host/render_widget_host_view_cocoa.h
+++ b/content/browser/renderer_host/render_widget_host_view_cocoa.h
@@ -55,6 +55,7 @@
 @interface RenderWidgetHostViewCocoa
     : ToolTipBaseView<CommandDispatcherTarget,
                       RenderWidgetHostNSViewClientOwner,
+                      NSCandidateListTouchBarItemDelegate,
                       NSTextInputClient> {
  @private
   // The communications channel to the RenderWidgetHostViewMac. This pointer is
@@ -198,6 +199,8 @@
 @property(nonatomic, assign) NSRange markedRange;
 @property(nonatomic, assign) ui::TextInputType textInputType;
 
+@property(nonatomic, assign) NSSpellChecker* spellCheckerForTesting;
+
 // Common code path for handling begin gesture events. This helper method is
 // called via different codepaths based on OS version and SDK:
 // - On 10.11 and later, when linking with the 10.11 SDK, it is called from
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index ee6cde81..4e8fd15 100644
--- a/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -21,10 +21,12 @@
 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
 #import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
 #import "content/public/browser/render_widget_host_view_mac_delegate.h"
+#include "content/public/common/content_features.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #import "ui/base/clipboard/clipboard_util_mac.h"
 #import "ui/base/cocoa/appkit_utils.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
+#import "ui/base/cocoa/touch_bar_util.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/display/screen.h"
 #include "ui/events/event_utils.h"
@@ -52,6 +54,9 @@
 
 namespace {
 
+// Touch bar identifier.
+NSString* const kWebContentTouchBarId = @"web-content";
+
 // Whether a keyboard event has been reserved by OSX.
 BOOL EventIsReservedBySystem(NSEvent* event) {
   content::SystemHotkeyHelperMac* helper =
@@ -119,6 +124,10 @@
 @interface RenderWidgetHostViewCocoa () {
   bool keyboardLockActive_;
   base::Optional<base::flat_set<ui::DomCode>> lockedKeys_;
+
+  API_AVAILABLE(macos(10.12.2))
+  base::scoped_nsobject<NSCandidateListTouchBarItem> candidateListTouchBarItem_;
+  NSInteger textSuggestionsSequenceNumber_;
 }
 - (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
                    consumed:(BOOL)consumed;
@@ -128,13 +137,24 @@
 - (void)windowDidBecomeKey:(NSNotification*)notification;
 - (void)windowDidResignKey:(NSNotification*)notification;
 - (void)sendViewBoundsInWindowToClient;
+- (void)requestTextSuggestions API_AVAILABLE(macos(10.12.2));
 - (void)sendWindowFrameInScreenToClient;
 - (bool)clientIsDisconnected;
+- (void)invalidateTouchBar API_AVAILABLE(macos(10.12.2));
+
+// NSCandidateListTouchBarItemDelegate implementation
+- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
+     endSelectingCandidateAtIndex:(NSInteger)index
+    API_AVAILABLE(macos(10.12.2));
+- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
+    changedCandidateListVisibility:(BOOL)isVisible
+    API_AVAILABLE(macos(10.12.2));
 @end
 
 @implementation RenderWidgetHostViewCocoa
 @synthesize markedRange = markedRange_;
 @synthesize textInputType = textInputType_;
+@synthesize spellCheckerForTesting = spellCheckerForTesting_;
 
 - (id)initWithClient:(RenderWidgetHostNSViewClient*)client
     withClientHelper:(RenderWidgetHostNSViewClientHelper*)clientHelper {
@@ -191,12 +211,82 @@
   client_->OnBoundsInWindowChanged(gfxViewBoundsInWindow, true);
 }
 
+- (void)requestTextSuggestions {
+  auto* touchBarItem = candidateListTouchBarItem_.get();
+  if (!touchBarItem)
+    return;
+  [touchBarItem
+      updateWithInsertionPointVisibility:textSelectionRange_.is_empty()];
+  if (!touchBarItem.candidateListVisible)
+    return;
+  if (!textSelectionRange_.IsValid()) {
+    [touchBarItem setCandidates:@[]
+               forSelectedRange:NSMakeRange(NSNotFound, 0)
+                       inString:nil];
+
+    // Bump the sequence number so that any request in flight is ignored.
+    textSuggestionsSequenceNumber_ += 1;
+    return;
+  }
+
+  NSRange selectionRange = textSelectionRange_.ToNSRange();
+  NSString* selectionText = base::SysUTF16ToNSString(textSelectionText_);
+  selectionRange.location -= textSelectionOffset_;
+  NSSpellChecker* spell_checker = spellCheckerForTesting_
+                                      ? spellCheckerForTesting_
+                                      : [NSSpellChecker sharedSpellChecker];
+  textSuggestionsSequenceNumber_ = [spell_checker
+      requestCandidatesForSelectedRange:selectionRange
+                               inString:selectionText
+                                  types:NSTextCheckingAllSystemTypes
+                                options:nil
+                 inSpellDocumentWithTag:0
+                      completionHandler:^(
+                          NSInteger sequenceNumber,
+                          NSArray<NSTextCheckingResult*>* candidates) {
+                        dispatch_async(dispatch_get_main_queue(), ^{
+                          if (sequenceNumber != textSuggestionsSequenceNumber_)
+                            return;
+                          [touchBarItem setCandidates:candidates
+                                     forSelectedRange:selectionRange
+                                             inString:selectionText];
+                        });
+                      }];
+}
+
 - (void)setTextSelectionText:(base::string16)text
                       offset:(size_t)offset
                        range:(gfx::Range)range {
   textSelectionText_ = text;
   textSelectionOffset_ = offset;
   textSelectionRange_ = range;
+  if (@available(macOS 10.12.2, *))
+    [self requestTextSuggestions];
+}
+
+- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
+     endSelectingCandidateAtIndex:(NSInteger)index {
+  if (index == NSNotFound)
+    return;
+  NSTextCheckingResult* selectedResult = anItem.candidates[index];
+  NSRange replacementRange = selectedResult.range;
+  replacementRange.location += textSelectionOffset_;
+  [self insertText:selectedResult.replacementString
+      replacementRange:replacementRange];
+}
+
+- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
+    changedCandidateListVisibility:(BOOL)isVisible {
+  [self requestTextSuggestions];
+}
+
+- (void)setTextInputType:(ui::TextInputType)textInputType {
+  if (textInputType_ == textInputType)
+    return;
+  textInputType_ = textInputType;
+
+  if (@available(macOS 10.12.2, *))
+    [self invalidateTouchBar];
 }
 
 - (base::string16)selectedText {
@@ -1842,6 +1932,36 @@
   client_->RequestShutdown();
 }
 
+- (void)invalidateTouchBar {
+  candidateListTouchBarItem_.reset();
+  self.touchBar = nil;
+}
+
+- (NSTouchBar*)makeTouchBar {
+  if (textInputType_ != ui::TEXT_INPUT_TYPE_NONE &&
+      textInputType_ != ui::TEXT_INPUT_TYPE_PASSWORD &&
+      (base::FeatureList::IsEnabled(features::kTextSuggestionsTouchBar) ||
+       base::FeatureList::IsEnabled(features::kExperimentalUi))) {
+    candidateListTouchBarItem_.reset([[NSCandidateListTouchBarItem alloc]
+        initWithIdentifier:NSTouchBarItemIdentifierCandidateList]);
+    auto* candidateListItem = candidateListTouchBarItem_.get();
+
+    candidateListItem.delegate = self;
+    candidateListItem.client = self;
+    [self requestTextSuggestions];
+
+    base::scoped_nsobject<NSTouchBar> scopedTouchBar([[NSTouchBar alloc] init]);
+    auto* touchBar = scopedTouchBar.get();
+    touchBar.customizationIdentifier = ui::GetTouchBarId(kWebContentTouchBarId);
+    touchBar.templateItems = [NSSet setWithObject:candidateListTouchBarItem_];
+    touchBar.defaultItemIdentifiers =
+        @[ NSTouchBarItemIdentifierCandidateList ];
+    return scopedTouchBar.autorelease();
+  }
+
+  return [super makeTouchBar];
+}
+
 @end
 
 //
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index fc1045c..00dfa7f8 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -626,9 +626,6 @@
     return;
   ns_view_bridge_->SetTextSelection(selection->text(), selection->offset(),
                                     selection->range());
-  if (host() && host()->delegate())
-    host()->delegate()->DidChangeTextSelection(
-        selection->text(), selection->range(), selection->offset());
 }
 
 bool RenderWidgetHostViewMac::ShouldWaitInPreCommit() {
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 15c88d3..c141008b 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
@@ -128,6 +128,72 @@
 
 @end
 
+@interface FakeTextCheckingResult : NSObject<NSCopying>
+@property(readonly) NSRange range;
+@property(readonly) NSString* replacementString;
+@end
+
+@implementation FakeTextCheckingResult {
+  base::scoped_nsobject<NSString> replacementString_;
+}
+@synthesize range = range_;
+
++ (FakeTextCheckingResult*)resultWithRange:(NSRange)range
+                         replacementString:(NSString*)replacementString {
+  FakeTextCheckingResult* result =
+      [[[FakeTextCheckingResult alloc] init] autorelease];
+  result->range_ = range;
+  result->replacementString_.reset([replacementString retain]);
+  return result;
+}
+
+- (id)copyWithZone:(NSZone*)zone {
+  return
+      [[FakeTextCheckingResult resultWithRange:self.range
+                             replacementString:self.replacementString] retain];
+}
+
+- (NSString*)replacementString {
+  return replacementString_;
+}
+@end
+
+@interface FakeSpellChecker : NSObject
+@property NSInteger sequenceNumber;
+@end
+
+@implementation FakeSpellChecker {
+  base::mac::ScopedBlock<void (^)(NSInteger sequenceNumber,
+                                  NSArray<NSTextCheckingResult*>* candidates)>
+      lastCompletionHandler_;
+}
+@synthesize sequenceNumber = sequenceNumber_;
+
+- (NSInteger)
+requestCandidatesForSelectedRange:(NSRange)selectedRange
+                         inString:(NSString*)stringToCheck
+                            types:(NSTextCheckingTypes)checkingTypes
+                          options:
+                              (nullable NSDictionary<NSTextCheckingOptionKey,
+                                                     id>*)options
+           inSpellDocumentWithTag:(NSInteger)tag
+                completionHandler:
+                    (void (^__nullable)(NSInteger sequenceNumber,
+                                        NSArray<NSTextCheckingResult*>*
+                                            candidates))completionHandler
+    NS_AVAILABLE_MAC(10_12_2) {
+  sequenceNumber_ += 1;
+  lastCompletionHandler_.reset([completionHandler copy]);
+  return sequenceNumber_;
+}
+
+- (void (^)(NSInteger sequenceNumber,
+            NSArray<NSTextCheckingResult*>* candidates))lastCompletionHandler {
+  return lastCompletionHandler_;
+}
+
+@end
+
 namespace content {
 
 namespace {
@@ -1725,6 +1791,12 @@
   RenderWidgetHostImpl* tab_widget() { return widget_; }
   RenderWidgetHostViewCocoa* tab_cocoa_view() { return view_->cocoa_view(); }
 
+  API_AVAILABLE(macos(10.12.2))
+  NSCandidateListTouchBarItem* candidate_list_item() {
+    return [tab_cocoa_view().touchBar
+        itemForIdentifier:NSTouchBarItemIdentifierCandidateList];
+  }
+
  protected:
   MockRenderProcessHost* process_host_;
   MockRenderWidgetHostImpl* widget_;
@@ -2011,6 +2083,125 @@
   EXPECT_FALSE(message->monitor_request());
 }
 
+TEST_F(InputMethodMacTest, TouchBarTextSuggestionsDisabled) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kTextSuggestionsTouchBar);
+  if (@available(macOS 10.12.2, *)) {
+    EXPECT_NSEQ(nil, candidate_list_item());
+    SetTextInputType(tab_view(), ui::TEXT_INPUT_TYPE_TEXT);
+    EXPECT_NSEQ(nil, candidate_list_item());
+  }
+}
+
+TEST_F(InputMethodMacTest, TouchBarTextSuggestionsPresence) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kTextSuggestionsTouchBar);
+  if (@available(macOS 10.12.2, *)) {
+    EXPECT_NSEQ(nil, candidate_list_item());
+    SetTextInputType(tab_view(), ui::TEXT_INPUT_TYPE_PASSWORD);
+    EXPECT_NSEQ(nil, candidate_list_item());
+    SetTextInputType(tab_view(), ui::TEXT_INPUT_TYPE_TEXT);
+    EXPECT_NSNE(nil, candidate_list_item());
+  }
+}
+
+TEST_F(InputMethodMacTest, TouchBarTextSuggestionsReplacement) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kTextSuggestionsTouchBar);
+  if (@available(macOS 10.12.2, *)) {
+    base::scoped_nsobject<FakeSpellChecker> spellChecker(
+        [[FakeSpellChecker alloc] init]);
+    tab_cocoa_view().spellCheckerForTesting =
+        static_cast<NSSpellChecker*>(spellChecker.get());
+
+    SetTextInputType(tab_view(), ui::TEXT_INPUT_TYPE_TEXT);
+    EXPECT_NSNE(nil, candidate_list_item());
+    candidate_list_item().allowsCollapsing = NO;
+
+    FakeTextCheckingResult* fakeResult =
+        [FakeTextCheckingResult resultWithRange:NSMakeRange(0, 3)
+                              replacementString:@"foo"];
+
+    const base::string16 kOriginalString = base::UTF8ToUTF16("abcxxxghi");
+
+    // Change the selection once; requests completions from the spell checker.
+    tab_view()->SelectionChanged(kOriginalString, 3, gfx::Range(3, 3));
+
+    NSInteger firstSequenceNumber = [spellChecker sequenceNumber];
+    base::mac::ScopedBlock<void (^)(NSInteger sequenceNumber,
+                                    NSArray<NSTextCheckingResult*>* candidates)>
+        firstCompletionHandler([[spellChecker lastCompletionHandler] retain]);
+
+    EXPECT_NE(nil, (id)firstCompletionHandler.get());
+    EXPECT_EQ(0U, candidate_list_item().candidates.count);
+
+    // Instead of replying right away, change the selection again!
+    tab_view()->SelectionChanged(kOriginalString, 3, gfx::Range(5, 5));
+
+    EXPECT_NE(firstSequenceNumber, [spellChecker sequenceNumber]);
+
+    // Make sure that calling the stale completion handler is a no-op.
+    firstCompletionHandler.get()(
+        firstSequenceNumber,
+        @[ static_cast<NSTextCheckingResult*>(fakeResult) ]);
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(0U, candidate_list_item().candidates.count);
+
+    // But calling the current handler should work.
+    [spellChecker lastCompletionHandler](
+        [spellChecker sequenceNumber],
+        @[ static_cast<NSTextCheckingResult*>(fakeResult) ]);
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(1U, candidate_list_item().candidates.count);
+
+    base::RunLoop().RunUntilIdle();
+    MockWidgetInputHandler::MessageVector events =
+        host_->GetAndResetDispatchedMessages();
+    ASSERT_EQ("", GetMessageNames(events));
+
+    // Now, select that result.
+    [tab_cocoa_view() candidateListTouchBarItem:candidate_list_item()
+                   endSelectingCandidateAtIndex:0];
+    base::RunLoop().RunUntilIdle();
+    events = widget_->GetAndResetDispatchedMessages();
+    ASSERT_EQ("CommitText", GetMessageNames(events));
+  }
+}
+
+// https://crbug.com/893038: There exist code paths which set the selection
+// range to gfx::Range::InvalidRange(). I'm not sure how to exercise them in
+// practice, but this has caused crashes in the field.
+TEST_F(InputMethodMacTest, TouchBarTextSuggestionsInvalidSelection) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kTextSuggestionsTouchBar);
+  if (@available(macOS 10.12.2, *)) {
+    base::scoped_nsobject<FakeSpellChecker> spellChecker(
+        [[FakeSpellChecker alloc] init]);
+    tab_cocoa_view().spellCheckerForTesting =
+        static_cast<NSSpellChecker*>(spellChecker.get());
+
+    SetTextInputType(tab_view(), ui::TEXT_INPUT_TYPE_TEXT);
+    candidate_list_item().allowsCollapsing = NO;
+
+    FakeTextCheckingResult* fakeResult =
+        [FakeTextCheckingResult resultWithRange:NSMakeRange(0, 3)
+                              replacementString:@"foo"];
+
+    const base::string16 kOriginalString = base::UTF8ToUTF16("abcxxxghi");
+
+    tab_view()->SelectionChanged(kOriginalString, 3,
+                                 gfx::Range::InvalidRange());
+
+    [spellChecker lastCompletionHandler](
+        [spellChecker sequenceNumber],
+        @[ static_cast<NSTextCheckingResult*>(fakeResult) ]);
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_NE(nil, candidate_list_item().candidates);
+    EXPECT_EQ(0U, candidate_list_item().candidates.count);
+  }
+}
+
 TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) {
   BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor();
   ui::Compositor* ui_compositor = browser_compositor->GetCompositor();
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index c5ae682b..17ee17d 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3244,15 +3244,6 @@
   focused_frame->GetFrameInputHandler()->SelectRange(base, extent);
 }
 
-#if defined(OS_MACOSX)
-void WebContentsImpl::DidChangeTextSelection(const base::string16& text,
-                                             const gfx::Range& range,
-                                             size_t offset) {
-  for (auto& observer : observers_)
-    observer.DidChangeTextSelection(text, range, offset);
-}
-#endif
-
 void WebContentsImpl::MoveCaret(const gfx::Point& extent) {
   RenderFrameHostImpl* focused_frame = GetFocusedFrame();
   if (!focused_frame)
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index ac4e414..aa5700d 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -731,11 +731,6 @@
                           const base::Optional<base::string16>& value) override;
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
   void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
-#if defined(OS_MACOSX)
-  void DidChangeTextSelection(const base::string16& text,
-                              const gfx::Range& range,
-                              size_t offset) override;
-#endif
   void MoveCaret(const gfx::Point& extent) override;
   void AdjustSelectionByCharacterOffset(int start_adjust,
                                         int end_adjust,
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index c2eef0d..ab36d92e 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -144,7 +144,7 @@
     "java/src/org/chromium/content/browser/SpareChildConnection.java",
     "java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
     "java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
-    "java/src/org/chromium/content/browser/TracingControllerAndroid.java",
+    "java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java",
     "java/src/org/chromium/content/browser/ViewEventSinkImpl.java",
     "java/src/org/chromium/content/browser/WindowEventObserver.java",
     "java/src/org/chromium/content/browser/WindowEventObserverManager.java",
@@ -255,6 +255,7 @@
     "java/src/org/chromium/content_public/browser/NavigationController.java",
     "java/src/org/chromium/content_public/browser/NavigationEntry.java",
     "java/src/org/chromium/content_public/browser/NavigationHistory.java",
+    "java/src/org/chromium/content_public/browser/RenderCoordinates.java",
     "java/src/org/chromium/content_public/browser/RenderFrameHost.java",
     "java/src/org/chromium/content_public/browser/ScreenOrientationDelegate.java",
     "java/src/org/chromium/content_public/browser/ScreenOrientationProvider.java",
@@ -263,7 +264,7 @@
     "java/src/org/chromium/content_public/browser/SelectionPopupController.java",
     "java/src/org/chromium/content_public/browser/SmartClipProvider.java",
     "java/src/org/chromium/content_public/browser/SpeechRecognition.java",
-    "java/src/org/chromium/content_public/browser/RenderCoordinates.java",
+    "java/src/org/chromium/content_public/browser/TracingControllerAndroid.java",
     "java/src/org/chromium/content_public/browser/UiThreadTaskTraits.java",
     "java/src/org/chromium/content_public/browser/ViewEventSink.java",
     "java/src/org/chromium/content_public/browser/WebContents.java",
@@ -380,7 +381,7 @@
     "java/src/org/chromium/content/browser/ScreenOrientationProviderImpl.java",
     "java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
     "java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
-    "java/src/org/chromium/content/browser/TracingControllerAndroid.java",
+    "java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java",
     "java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java",
     "java/src/org/chromium/content/browser/accessibility/captioning/CaptioningController.java",
     "java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java",
@@ -484,7 +485,7 @@
     "javatests/src/org/chromium/content/browser/NavigationTest.java",
     "javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java",
     "javatests/src/org/chromium/content/browser/TestsJavaScriptEvalTest.java",
-    "javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java",
+    "javatests/src/org/chromium/content/browser/TracingControllerAndroidImplTest.java",
     "javatests/src/org/chromium/content/browser/VideoFullscreenOrientationLockTest.java",
     "javatests/src/org/chromium/content/browser/VideoRotateToFullscreenTest.java",
     "javatests/src/org/chromium/content/browser/VSyncPausedTest.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
index a8208c1..c45ad74 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
@@ -21,7 +21,6 @@
 import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.content.app.ContentMain;
 import org.chromium.content_public.browser.BrowserStartupController;
-import org.chromium.content_public.browser.BrowserStartupController.StartupCallback;
 import org.chromium.ui.resources.ResourceExtractor;
 
 import java.lang.annotation.Retention;
@@ -121,7 +120,7 @@
     // Whether ServiceManager is started.
     private boolean mServiceManagerStarted;
 
-    private TracingControllerAndroid mTracingController;
+    private TracingControllerAndroidImpl mTracingController;
 
     BrowserStartupControllerImpl(int libraryProcessType) {
         mAsyncStartupCallbacks = new ArrayList<>();
@@ -135,7 +134,7 @@
                     public void onSuccess() {
                         assert mTracingController == null;
                         Context context = ContextUtils.getApplicationContext();
-                        mTracingController = new TracingControllerAndroid(context);
+                        mTracingController = new TracingControllerAndroidImpl(context);
                         mTracingController.registerReceiver(context);
                     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java b/content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java
similarity index 84%
rename from content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java
rename to content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java
index 6bafaa5..9742a958 100644
--- a/content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java
+++ b/content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java
@@ -18,6 +18,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.R;
+import org.chromium.content_public.browser.TracingControllerAndroid;
 import org.chromium.ui.widget.Toast;
 
 import java.io.File;
@@ -43,7 +44,7 @@
  * is being traced, but the general form is [app package name].GPU_PROFILER_{START,STOP}.
  */
 @JNINamespace("content")
-public class TracingControllerAndroid {
+public class TracingControllerAndroidImpl implements TracingControllerAndroid {
     private static final String TAG = "cr.TracingController";
 
     private static final String ACTION_START = "GPU_PROFILER_START";
@@ -72,7 +73,7 @@
     private String mFilename;
     private boolean mCompressFile;
 
-    public TracingControllerAndroid(Context context) {
+    public TracingControllerAndroidImpl(Context context) {
         mContext = context;
         mBroadcastReceiver = new TracingBroadcastReceiver();
         mIntentFilter = new TracingIntentFilter(context);
@@ -107,16 +108,12 @@
         context.unregisterReceiver(getBroadcastReceiver());
     }
 
-    /**
-     * Returns true if we're currently profiling.
-     */
+    @Override
     public boolean isTracing() {
         return mIsTracing;
     }
 
-    /**
-     * Returns the path of the current output file. Null if isTracing() false.
-     */
+    @Override
     public String getOutputPath() {
         return mFilename;
     }
@@ -161,26 +158,7 @@
         }
     }
 
-    /**
-     * Start profiling to the specified file (if not null) or to a new file in the Downloads
-     * directory.
-     *
-     * Only one TracingControllerAndroid can be running at the same time. If another profiler
-     * is running when this method is called, it will be cancelled. If this
-     * profiler is already running, this method does nothing and returns false.
-     *
-     * @param filename The name of the file to output the profile data to, or null.
-     * @param showToasts Whether or not we want to show toasts during this profiling session.
-     * When we are timing the profile run we might not want to incur extra draw overhead of showing
-     * notifications about the profiling system.
-     * @param categories Which categories to trace. See TracingControllerAndroid::BeginTracing()
-     * (in content/public/browser/trace_controller.h) for the format.
-     * @param traceOptions Which trace options to use. See
-     * TraceOptions::TraceOptions(const std::string& options_string)
-     * (in base/trace_event/trace_event_impl.h) for the format.
-     * @param compressFile Whether the trace file should be compressed (gzip).
-     * @return Whether tracing was started successfully.
-     */
+    @Override
     public boolean startTracing(String filename, boolean showToasts, String categories,
             String traceOptions, boolean compressFile) {
         mShowToasts = showToasts;
@@ -214,12 +192,7 @@
         return true;
     }
 
-    /**
-     * Stop profiling and run |callback| when stopped. This won't take effect until Chrome has
-     * flushed its file.
-     *
-     * @param callback The Callback executed when tracing has stopped.
-     */
+    @Override
     public void stopTracing(Callback<Void> callback) {
         if (isTracing()) {
             nativeStopTracing(mNativeTracingControllerAndroid, mFilename, mCompressFile, callback);
@@ -248,7 +221,7 @@
     }
 
     /**
-     * Get known categories.
+     * Get known categories and log them for the profiler.
      */
     public void getKnownCategories() {
         if (!getKnownCategories(null)) {
@@ -256,12 +229,7 @@
         }
     }
 
-    /**
-     * Get known categories and run |callback| with the set of known categories.
-     *
-     * @param callback The callback that receives the result.
-     * @return Whether initiating the request was successful.
-     */
+    @Override
     public boolean getKnownCategories(Callback<String[]> callback) {
         // Lazy initialize the native side, to allow construction before the library is loaded.
         initializeNativeControllerIfNeeded();
@@ -282,13 +250,7 @@
         }
     }
 
-    /**
-     * Get the current estimated trace buffer usage and approximate total event count in the buffer.
-     *
-     * @param callback The callback that receives the result as a Pair of (percentage_full,
-     * approximate_event_count).
-     * @return Whether initiating the request was successful.
-     */
+    @Override
     public boolean getTraceBufferUsage(Callback<Pair<Float, Long>> callback) {
         assert callback != null;
         // Lazy initialize the native side, to allow construction before the library is loaded.
@@ -304,10 +266,7 @@
                 .onResult(new Pair<>(percentFull, approximateEventCount));
     }
 
-    /**
-     * Clean up the C++ side of this class.
-     * After the call, this class instance shouldn't be used.
-     */
+    @Override
     public void destroy() {
         if (mNativeTracingControllerAndroid != 0) {
             nativeDestroy(mNativeTracingControllerAndroid);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/TracingControllerAndroid.java b/content/public/android/java/src/org/chromium/content_public/browser/TracingControllerAndroid.java
new file mode 100644
index 0000000..f6b8b49
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content_public/browser/TracingControllerAndroid.java
@@ -0,0 +1,91 @@
+// 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.
+
+package org.chromium.content_public.browser;
+
+import android.content.Context;
+import android.util.Pair;
+
+import org.chromium.base.Callback;
+import org.chromium.content.browser.TracingControllerAndroidImpl;
+
+/**
+ * Controller for Chrome's tracing feature. The embedder may use this class to implement a UI for
+ * recording and sharing Chrome performance traces.
+ */
+public interface TracingControllerAndroid {
+    /**
+     * Creates a new TracingControllerAndroid instance.
+     *
+     * @param context the Context in which to create the controller.
+     * @return the controller.
+     */
+    public static TracingControllerAndroid create(Context context) {
+        return new TracingControllerAndroidImpl(context);
+    }
+
+    /**
+     * @return true if a trace is being recorded.
+     */
+    boolean isTracing();
+
+    /**
+     * @return the path of the current output file. Null if isTracing() false.
+     */
+    String getOutputPath();
+
+    /**
+     * Start recording a trace to the specified file (if not null) or to a new file in the Downloads
+     * directory.
+     *
+     * Only one TracingControllerAndroid can be running at the same time. If another profiler is
+     * running when this method is called, it will be cancelled. If this profiler is already
+     * running, this method does nothing and returns false.
+     *
+     * @param filename The name of the file to output the profile data to, or null.
+     * @param showToasts Whether or not we want to show toasts during this profiling session.
+     * When we are timing the profile run we might not want to incur extra draw overhead of showing
+     * notifications about the profiling system, or the embedder may want to show such notifications
+     * themselves.
+     * @param categories Which categories to trace. See TracingController::StartTracing()
+     * (in content/public/browser/tracing_controller.h) for the format.
+     * @param traceOptions Which trace options to use. See
+     * TraceOptions::TraceOptions(const std::string& options_string)
+     * (in base/trace_event/trace_event_impl.h) for the format.
+     * @param compressFile Whether the trace file should be compressed (gzip).
+     * @return Whether tracing was started successfully.
+     */
+    boolean startTracing(String filename, boolean showToasts, String categories,
+            String traceOptions, boolean compressFile);
+
+    /**
+     * Stop recording and run |callback| when stopped.
+     *
+     * @param callback the Callback executed when tracing has stopped.
+     */
+    void stopTracing(Callback<Void> callback);
+
+    /**
+     * Get known tracing categories and run |callback| with the set of known categories.
+     *
+     * @param callback the callback that receives the result.
+     * @return whether initiating the request was successful.
+     */
+    boolean getKnownCategories(Callback<String[]> callback);
+
+    /**
+     * Get the current estimated trace buffer usage and approximate total event count in the buffer.
+     *
+     * @param callback the callback that receives the result as a Pair of (percentage_full,
+     * approximate_event_count).
+     * @return whether initiating the request was successful.
+     */
+    boolean getTraceBufferUsage(Callback<Pair<Float, Long>> callback);
+
+    /**
+     * Clean any native dependencies of the controller. After the call, this class instance
+     * shouldn't be used.
+     */
+    void destroy();
+}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java b/content/public/android/javatests/src/org/chromium/content/browser/TracingControllerAndroidImplTest.java
similarity index 90%
rename from content/public/android/javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java
rename to content/public/android/javatests/src/org/chromium/content/browser/TracingControllerAndroidImplTest.java
index 46b75ca8..b87023f 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/TracingControllerAndroidImplTest.java
@@ -29,10 +29,10 @@
 import java.util.Arrays;
 
 /**
- * Test suite for TracingControllerAndroid.
+ * Test suite for TracingControllerAndroidImpl.
  */
 @RunWith(BaseJUnit4ClassRunner.class)
-public class TracingControllerAndroidTest {
+public class TracingControllerAndroidImplTest {
     @Rule
     public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule();
 
@@ -45,7 +45,8 @@
         ContentShellActivity activity = mActivityTestRule.launchContentShellWithUrl("about:blank");
         mActivityTestRule.waitForActiveShellToBeDoneLoading();
 
-        final TracingControllerAndroid tracingController = new TracingControllerAndroid(activity);
+        final TracingControllerAndroidImpl tracingController =
+                new TracingControllerAndroidImpl(activity);
         Assert.assertFalse(tracingController.isTracing());
         Assert.assertNull(tracingController.getOutputPath());
 
@@ -88,7 +89,8 @@
         ContentShellActivity activity = mActivityTestRule.launchContentShellWithUrl("about:blank");
         mActivityTestRule.waitForActiveShellToBeDoneLoading();
 
-        final TracingControllerAndroid tracingController = new TracingControllerAndroid(activity);
+        final TracingControllerAndroidImpl tracingController =
+                new TracingControllerAndroidImpl(activity);
         Assert.assertFalse(tracingController.isTracing());
 
         TestCallback<String[]> callback = new TestCallback<>();
@@ -107,7 +109,8 @@
         ContentShellActivity activity = mActivityTestRule.launchContentShellWithUrl("about:blank");
         mActivityTestRule.waitForActiveShellToBeDoneLoading();
 
-        final TracingControllerAndroid tracingController = new TracingControllerAndroid(activity);
+        final TracingControllerAndroidImpl tracingController =
+                new TracingControllerAndroidImpl(activity);
         Assert.assertFalse(tracingController.isTracing());
 
         // This should obtain an empty buffer usage, since we aren't tracing.
@@ -128,7 +131,8 @@
         ContentShellActivity activity = mActivityTestRule.launchContentShellWithUrl("about:blank");
         mActivityTestRule.waitForActiveShellToBeDoneLoading();
 
-        final TracingControllerAndroid tracingController = new TracingControllerAndroid(activity);
+        final TracingControllerAndroidImpl tracingController =
+                new TracingControllerAndroidImpl(activity);
         Assert.assertFalse(tracingController.isTracing());
         Assert.assertNull(tracingController.getOutputPath());
 
diff --git a/content/public/browser/render_widget_host_view.h b/content/public/browser/render_widget_host_view.h
index c662115..b691dd6 100644
--- a/content/public/browser/render_widget_host_view.h
+++ b/content/public/browser/render_widget_host_view.h
@@ -141,16 +141,6 @@
   // Returns the currently selected text.
   virtual base::string16 GetSelectedText() = 0;
 
-  // Returns part of the text on the page which includes the selected text plus
-  // possibly several characters before and after it.
-  virtual base::string16 GetSurroundingText() = 0;
-
-  // Returns the range of the selection in the page.
-  virtual gfx::Range GetSelectedRange() = 0;
-
-  // The offset of the surrounding text relative to the start of the total text.
-  virtual size_t GetOffsetForSurroundingText() = 0;
-
   // This only returns non-null on platforms that implement touch
   // selection editing (TSE), currently Aura and (soon) Android.
   // TODO(wjmaclean): update this comment when OOPIF TSE is implemented on
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h
index 89ff658d..3cb21f578 100644
--- a/content/public/browser/web_contents_observer.h
+++ b/content/public/browser/web_contents_observer.h
@@ -25,7 +25,6 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
-#include "ui/gfx/range/range.h"
 
 namespace blink {
 namespace mojom {
@@ -455,11 +454,6 @@
   // Invoked when theme color is changed to |theme_color|.
   virtual void DidChangeThemeColor(SkColor theme_color) {}
 
-  // Invoked when text selection is changed.
-  virtual void DidChangeTextSelection(const base::string16& text,
-                                      const gfx::Range& range,
-                                      size_t offset) {}
-
   // Invoked when media is playing or paused.  |id| is unique per player and per
   // RenderFrameHost.  There may be multiple players within a RenderFrameHost
   // and subsequently within a WebContents.  MediaStartedPlaying() will always
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 7aeb6bd..7e0dcc6 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -678,6 +678,10 @@
 // entire life of the process.
 const base::Feature kMacV2Sandbox{"MacV2Sandbox",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
+//
+// Enables the suggested text touch bar for autocomplete in textfields.
+const base::Feature kTextSuggestionsTouchBar{"TextSuggestionsTouchBar",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_MACOSX)
 
 enum class VideoCaptureServiceConfiguration {
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index df9ae24..ed2d6c1 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -162,6 +162,7 @@
 CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac;
 CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer;
 CONTENT_EXPORT extern const base::Feature kMacV2Sandbox;
+CONTENT_EXPORT extern const base::Feature kTextSuggestionsTouchBar;
 #endif  // defined(OS_MACOSX)
 
 // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index 86f3b6f..7283df0 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -131,8 +131,7 @@
       expected_exit_code_(0),
       enable_pixel_output_(false),
       use_software_compositing_(false),
-      set_up_called_(false),
-      disable_io_checks_(false) {
+      set_up_called_(false) {
   ui::test::EnableTestConfigForPlatformWindows();
 
 #if defined(OS_POSIX)
@@ -419,11 +418,9 @@
     InitializeNetworkProcess();
 
     bool old_io_allowed_value = false;
-    if (!disable_io_checks_)
-      old_io_allowed_value = base::ThreadRestrictions::SetIOAllowed(false);
+    old_io_allowed_value = base::ThreadRestrictions::SetIOAllowed(false);
     RunTestOnMainThread();
-    if (!disable_io_checks_)
-      base::ThreadRestrictions::SetIOAllowed(old_io_allowed_value);
+    base::ThreadRestrictions::SetIOAllowed(old_io_allowed_value);
     TearDownOnMainThread();
   }
 
diff --git a/content/public/test/browser_test_base.h b/content/public/test/browser_test_base.h
index a8e6959..b7bc20a 100644
--- a/content/public/test/browser_test_base.h
+++ b/content/public/test/browser_test_base.h
@@ -151,10 +151,6 @@
   // code necessary.
   void SetInitialWebContents(WebContents* web_contents);
 
-  // Temporary
-  // TODO(jam): remove this.
-  void disable_io_checks() { disable_io_checks_ = true; }
-
  private:
   void ProxyRunTestOnMainThreadLoop();
 
@@ -193,11 +189,6 @@
   // not run and report a false positive result.
   bool set_up_called_;
 
-  // Tests should keep on the IO thread checks to test that production code
-  // paths don't make file access. Keep this for now since src/chrome didn't
-  // check this.
-  bool disable_io_checks_;
-
   bool initialized_network_process_ = false;
 
 #if defined(OS_POSIX)
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 9ed86e1..005311f 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -141,6 +141,20 @@
     "ime_event_guard.h",
     "in_process_renderer_thread.cc",
     "in_process_renderer_thread.h",
+    "indexed_db/indexed_db_callbacks_impl.cc",
+    "indexed_db/indexed_db_callbacks_impl.h",
+    "indexed_db/indexed_db_database_callbacks_impl.cc",
+    "indexed_db/indexed_db_database_callbacks_impl.h",
+    "indexed_db/indexed_db_dispatcher.cc",
+    "indexed_db/indexed_db_dispatcher.h",
+    "indexed_db/indexed_db_key_builders.cc",
+    "indexed_db/indexed_db_key_builders.h",
+    "indexed_db/webidbcursor_impl.cc",
+    "indexed_db/webidbcursor_impl.h",
+    "indexed_db/webidbdatabase_impl.cc",
+    "indexed_db/webidbdatabase_impl.h",
+    "indexed_db/webidbfactory_impl.cc",
+    "indexed_db/webidbfactory_impl.h",
     "input/frame_input_handler_impl.cc",
     "input/frame_input_handler_impl.h",
     "input/input_event_prediction.cc",
diff --git a/content/renderer/indexed_db/OWNERS b/content/renderer/indexed_db/OWNERS
new file mode 100644
index 0000000..a740487
--- /dev/null
+++ b/content/renderer/indexed_db/OWNERS
@@ -0,0 +1,4 @@
+file://content/browser/indexed_db/OWNERS
+
+# TEAM: storage-dev@chromium.org
+# COMPONENT: Blink>Storage>IndexedDB
diff --git a/content/renderer/indexed_db/indexed_db_callbacks_impl.cc b/content/renderer/indexed_db/indexed_db_callbacks_impl.cc
new file mode 100644
index 0000000..792237fa
--- /dev/null
+++ b/content/renderer/indexed_db/indexed_db_callbacks_impl.cc
@@ -0,0 +1,257 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+
+#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
+#include "content/renderer/indexed_db/webidbcursor_impl.h"
+#include "content/renderer/indexed_db/webidbdatabase_impl.h"
+#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_name_and_version.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
+
+using blink::IndexedDBDatabaseMetadata;
+using blink::WebBlobInfo;
+using blink::WebData;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBMetadata;
+using blink::WebIDBNameAndVersion;
+using blink::WebIDBValue;
+using blink::WebString;
+using blink::WebVector;
+using blink::mojom::IDBDatabaseAssociatedPtrInfo;
+
+namespace content {
+
+namespace {
+
+void ConvertIndexMetadata(const blink::IndexedDBIndexMetadata& metadata,
+                          WebIDBMetadata::Index* output) {
+  output->id = metadata.id;
+  output->name = WebString::FromUTF16(metadata.name);
+  output->key_path = WebIDBKeyPathBuilder::Build(metadata.key_path);
+  output->unique = metadata.unique;
+  output->multi_entry = metadata.multi_entry;
+}
+
+void ConvertObjectStoreMetadata(
+    const blink::IndexedDBObjectStoreMetadata& metadata,
+    WebIDBMetadata::ObjectStore* output) {
+  output->id = metadata.id;
+  output->name = WebString::FromUTF16(metadata.name);
+  output->key_path = WebIDBKeyPathBuilder::Build(metadata.key_path);
+  output->auto_increment = metadata.auto_increment;
+  output->max_index_id = metadata.max_index_id;
+  output->indexes = WebVector<WebIDBMetadata::Index>(metadata.indexes.size());
+  size_t i = 0;
+  for (const auto& iter : metadata.indexes)
+    ConvertIndexMetadata(iter.second, &output->indexes[i++]);
+}
+
+void ConvertDatabaseMetadata(const IndexedDBDatabaseMetadata& metadata,
+                             WebIDBMetadata* output) {
+  output->id = metadata.id;
+  output->name = WebString::FromUTF16(metadata.name);
+  output->version = metadata.version;
+  output->max_object_store_id = metadata.max_object_store_id;
+  output->object_stores =
+      WebVector<WebIDBMetadata::ObjectStore>(metadata.object_stores.size());
+  size_t i = 0;
+  for (const auto& iter : metadata.object_stores)
+    ConvertObjectStoreMetadata(iter.second, &output->object_stores[i++]);
+}
+
+WebIDBValue ConvertReturnValue(const blink::mojom::IDBReturnValuePtr& value) {
+  if (!value)
+    return WebIDBValue(WebData(), WebVector<WebBlobInfo>());
+
+  WebIDBValue web_value = IndexedDBCallbacksImpl::ConvertValue(value->value);
+  web_value.SetInjectedPrimaryKey(WebIDBKeyBuilder::Build(value->primary_key),
+                                  WebIDBKeyPathBuilder::Build(value->key_path));
+  return web_value;
+}
+
+WebIDBNameAndVersion ConvertNameVersion(
+    const blink::mojom::IDBNameAndVersionPtr& name_and_version) {
+  return WebIDBNameAndVersion(WebString::FromUTF16(name_and_version->name),
+                              name_and_version->version);
+}
+
+}  // namespace
+
+// static
+WebIDBValue IndexedDBCallbacksImpl::ConvertValue(
+    const blink::mojom::IDBValuePtr& value) {
+  if (!value || value->bits.empty())
+    return WebIDBValue(WebData(), WebVector<WebBlobInfo>());
+
+  WebVector<WebBlobInfo> local_blob_info;
+  local_blob_info.reserve(value->blob_or_file_info.size());
+  for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) {
+    const auto& info = value->blob_or_file_info[i];
+    if (info->file) {
+      local_blob_info.emplace_back(WebString::FromUTF8(info->uuid),
+                                   blink::FilePathToWebString(info->file->path),
+                                   WebString::FromUTF16(info->file->name),
+                                   WebString::FromUTF16(info->mime_type),
+                                   info->file->last_modified.ToDoubleT(),
+                                   info->size, info->blob.PassHandle());
+    } else {
+      local_blob_info.emplace_back(WebString::FromUTF8(info->uuid),
+                                   WebString::FromUTF16(info->mime_type),
+                                   info->size, info->blob.PassHandle());
+    }
+  }
+
+  return WebIDBValue(WebData(&*value->bits.begin(), value->bits.size()),
+                     std::move(local_blob_info));
+}
+
+IndexedDBCallbacksImpl::IndexedDBCallbacksImpl(
+    std::unique_ptr<WebIDBCallbacks> callbacks,
+    int64_t transaction_id,
+    const base::WeakPtr<WebIDBCursorImpl>& cursor)
+    : callbacks_(std::move(callbacks)),
+      cursor_(cursor),
+      transaction_id_(transaction_id) {}
+
+IndexedDBCallbacksImpl::~IndexedDBCallbacksImpl() = default;
+
+void IndexedDBCallbacksImpl::Error(int32_t code,
+                                   const base::string16& message) {
+  callbacks_->OnError(
+      blink::WebIDBDatabaseError(code, WebString::FromUTF16(message)));
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessNamesAndVersionsList(
+    std::vector<blink::mojom::IDBNameAndVersionPtr> names_and_versions) {
+  WebVector<WebIDBNameAndVersion> web_names_and_versions;
+  web_names_and_versions.reserve(names_and_versions.size());
+  for (const blink::mojom::IDBNameAndVersionPtr& name_version :
+       names_and_versions)
+    web_names_and_versions.emplace_back(ConvertNameVersion(name_version));
+  callbacks_->OnSuccess(web_names_and_versions);
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessStringList(
+    const std::vector<base::string16>& value) {
+  WebVector<WebString> web_value(value.size());
+  std::transform(
+      value.begin(), value.end(), web_value.begin(),
+      [](const base::string16& s) { return WebString::FromUTF16(s); });
+  callbacks_->OnSuccess(web_value);
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::Blocked(int64_t existing_version) {
+  callbacks_->OnBlocked(existing_version);
+  // Not resetting |callbacks_|.
+}
+
+void IndexedDBCallbacksImpl::UpgradeNeeded(
+    IDBDatabaseAssociatedPtrInfo database_info,
+    int64_t old_version,
+    blink::WebIDBDataLoss data_loss,
+    const std::string& data_loss_message,
+    const IndexedDBDatabaseMetadata& metadata) {
+  WebIDBDatabase* database = new WebIDBDatabaseImpl(std::move(database_info));
+  WebIDBMetadata web_metadata;
+  ConvertDatabaseMetadata(metadata, &web_metadata);
+  callbacks_->OnUpgradeNeeded(old_version, database, web_metadata, data_loss,
+                              WebString::FromUTF8(data_loss_message));
+  // Not resetting |callbacks_|.
+}
+
+void IndexedDBCallbacksImpl::SuccessDatabase(
+    IDBDatabaseAssociatedPtrInfo database_info,
+    const IndexedDBDatabaseMetadata& metadata) {
+  WebIDBDatabase* database = nullptr;
+  if (database_info.is_valid()) {
+    database = new WebIDBDatabaseImpl(std::move(database_info));
+  }
+
+  WebIDBMetadata web_metadata;
+  ConvertDatabaseMetadata(metadata, &web_metadata);
+  callbacks_->OnSuccess(database, web_metadata);
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessCursor(
+    blink::mojom::IDBCursorAssociatedPtrInfo cursor_info,
+    const IndexedDBKey& key,
+    const IndexedDBKey& primary_key,
+    blink::mojom::IDBValuePtr value) {
+  WebIDBCursorImpl* cursor =
+      new WebIDBCursorImpl(std::move(cursor_info), transaction_id_);
+  callbacks_->OnSuccess(cursor, WebIDBKeyBuilder::Build(key),
+                        WebIDBKeyBuilder::Build(primary_key),
+                        ConvertValue(value));
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessValue(
+    blink::mojom::IDBReturnValuePtr value) {
+  callbacks_->OnSuccess(ConvertReturnValue(value));
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessCursorContinue(
+    const IndexedDBKey& key,
+    const IndexedDBKey& primary_key,
+    blink::mojom::IDBValuePtr value) {
+  callbacks_->OnSuccess(WebIDBKeyBuilder::Build(key),
+                        WebIDBKeyBuilder::Build(primary_key),
+                        ConvertValue(value));
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessCursorPrefetch(
+    const std::vector<IndexedDBKey>& keys,
+    const std::vector<IndexedDBKey>& primary_keys,
+    std::vector<blink::mojom::IDBValuePtr> values) {
+  std::vector<WebIDBValue> web_values;
+  web_values.reserve(values.size());
+  for (const blink::mojom::IDBValuePtr& value : values)
+    web_values.emplace_back(ConvertValue(value));
+
+  if (cursor_) {
+    cursor_->SetPrefetchData(keys, primary_keys, std::move(web_values));
+    cursor_->CachedContinue(callbacks_.get());
+  }
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessArray(
+    std::vector<blink::mojom::IDBReturnValuePtr> values) {
+  WebVector<WebIDBValue> web_values;
+  web_values.reserve(values.size());
+  for (const blink::mojom::IDBReturnValuePtr& value : values)
+    web_values.emplace_back(ConvertReturnValue(value));
+  callbacks_->OnSuccess(std::move(web_values));
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessKey(const IndexedDBKey& key) {
+  callbacks_->OnSuccess(WebIDBKeyBuilder::Build(key));
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::SuccessInteger(int64_t value) {
+  callbacks_->OnSuccess(value);
+  callbacks_.reset();
+}
+
+void IndexedDBCallbacksImpl::Success() {
+  callbacks_->OnSuccess();
+  callbacks_.reset();
+}
+
+}  // namespace content
diff --git a/content/renderer/indexed_db/indexed_db_callbacks_impl.h b/content/renderer/indexed_db/indexed_db_callbacks_impl.h
new file mode 100644
index 0000000..27052f4
--- /dev/null
+++ b/content/renderer/indexed_db/indexed_db_callbacks_impl.h
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_
+#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_
+
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+
+using blink::IndexedDBKey;
+
+namespace blink {
+class WebIDBCallbacks;
+class WebIDBValue;
+}  // namespace blink
+
+namespace content {
+
+class WebIDBCursorImpl;
+
+// Implements the child-process end of the pipe used to deliver callbacks. It
+// is owned by the IO thread. |callback_runner_| is used to post tasks back to
+// the thread which owns the blink::WebIDBCallbacks.
+class IndexedDBCallbacksImpl : public blink::mojom::IDBCallbacks {
+ public:
+  enum : int64_t { kNoTransaction = -1 };
+
+  static blink::WebIDBValue ConvertValue(
+      const blink::mojom::IDBValuePtr& value);
+
+  IndexedDBCallbacksImpl(std::unique_ptr<blink::WebIDBCallbacks> callbacks,
+                         int64_t transaction_id,
+                         const base::WeakPtr<WebIDBCursorImpl>& cursor);
+  ~IndexedDBCallbacksImpl() override;
+
+  // blink::mojom::IDBCallbacks implementation:
+  void Error(int32_t code, const base::string16& message) override;
+  void SuccessNamesAndVersionsList(
+      std::vector<blink::mojom::IDBNameAndVersionPtr> names_and_versions)
+      override;
+  void SuccessStringList(const std::vector<base::string16>& value) override;
+  void Blocked(int64_t existing_version) override;
+  void UpgradeNeeded(blink::mojom::IDBDatabaseAssociatedPtrInfo database_info,
+                     int64_t old_version,
+                     blink::WebIDBDataLoss data_loss,
+                     const std::string& data_loss_message,
+                     const blink::IndexedDBDatabaseMetadata& metadata) override;
+  void SuccessDatabase(
+      blink::mojom::IDBDatabaseAssociatedPtrInfo database_info,
+      const blink::IndexedDBDatabaseMetadata& metadata) override;
+  void SuccessCursor(blink::mojom::IDBCursorAssociatedPtrInfo cursor,
+                     const IndexedDBKey& key,
+                     const IndexedDBKey& primary_key,
+                     blink::mojom::IDBValuePtr value) override;
+  void SuccessValue(blink::mojom::IDBReturnValuePtr value) override;
+  void SuccessCursorContinue(const IndexedDBKey& key,
+                             const IndexedDBKey& primary_key,
+                             blink::mojom::IDBValuePtr value) override;
+  void SuccessCursorPrefetch(
+      const std::vector<IndexedDBKey>& keys,
+      const std::vector<IndexedDBKey>& primary_keys,
+      std::vector<blink::mojom::IDBValuePtr> values) override;
+  void SuccessArray(
+      std::vector<blink::mojom::IDBReturnValuePtr> values) override;
+  void SuccessKey(const IndexedDBKey& key) override;
+  void SuccessInteger(int64_t value) override;
+  void Success() override;
+
+ private:
+  scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
+  std::unique_ptr<blink::WebIDBCallbacks> callbacks_;
+  base::WeakPtr<WebIDBCursorImpl> cursor_;
+  int64_t transaction_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBCallbacksImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc b/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
similarity index 62%
rename from third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
rename to content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
index 1149fab7b..a63c065 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
+++ b/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
@@ -2,23 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_database_callbacks_impl.h"
 
 #include <unordered_map>
 #include <utility>
 
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_observation.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
 
 using blink::WebVector;
 using blink::WebIDBDatabaseCallbacks;
 using blink::WebIDBObservation;
 
-namespace blink {
+namespace content {
 
 IndexedDBDatabaseCallbacksImpl::IndexedDBDatabaseCallbacksImpl(
     std::unique_ptr<WebIDBDatabaseCallbacks> callbacks)
@@ -37,9 +38,10 @@
 
 void IndexedDBDatabaseCallbacksImpl::Abort(int64_t transaction_id,
                                            int32_t code,
-                                           const String& message) {
-  callbacks_->OnAbort(transaction_id,
-                      blink::WebIDBDatabaseError(code, message));
+                                           const base::string16& message) {
+  callbacks_->OnAbort(
+      transaction_id,
+      blink::WebIDBDatabaseError(code, blink::WebString::FromUTF16(message)));
 }
 
 void IndexedDBDatabaseCallbacksImpl::Complete(int64_t transaction_id) {
@@ -47,34 +49,33 @@
 }
 
 void IndexedDBDatabaseCallbacksImpl::Changes(
-    mojom::blink::IDBObserverChangesPtr changes) {
+    blink::mojom::IDBObserverChangesPtr changes) {
   WebVector<WebIDBObservation> web_observations;
   web_observations.reserve(changes->observations.size());
   for (const auto& observation : changes->observations) {
     web_observations.emplace_back(
-        observation->object_store_id, observation->type, observation->key_range,
+        observation->object_store_id, observation->type,
+        WebIDBKeyRangeBuilder::Build(observation->key_range),
         IndexedDBCallbacksImpl::ConvertValue(observation->value));
   }
 
-  std::unordered_map<int32_t, WebVector<int32_t>> observation_index_map;
-  for (const auto& observation_pair : changes->observation_index_map) {
-    observation_index_map[observation_pair.key] =
-        WebVector<int32_t>(observation_pair.value);
-  }
+  WebIDBDatabaseCallbacks::ObservationIndexMap observation_index_map(
+      changes->observation_index_map.begin(),
+      changes->observation_index_map.end());
 
-  std::unordered_map<int32_t, std::pair<int64_t, WebVector<int64_t>>>
+  std::unordered_map<int32_t, std::pair<int64_t, std::vector<int64_t>>>
       observer_transactions;
   for (const auto& transaction_pair : changes->transaction_map) {
     // Moving an int64_t is rather silly. Sadly, std::make_pair's overloads
     // accept either two rvalue arguments, or none.
-    observer_transactions[transaction_pair.key] =
-        std::make_pair<int64_t, Vector<int64_t>>(
-            std::move(transaction_pair.value->id),
-            std::move(transaction_pair.value->scope));
+    observer_transactions[transaction_pair.first] =
+        std::make_pair<int64_t, std::vector<int64_t>>(
+            std::move(transaction_pair.second->id),
+            std::move(transaction_pair.second->scope));
   }
 
   callbacks_->OnChanges(observation_index_map, std::move(web_observations),
                         observer_transactions);
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h b/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
new file mode 100644
index 0000000..304f978
--- /dev/null
+++ b/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
+#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
+
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+
+namespace blink {
+class WebIDBDatabaseCallbacks;
+}
+
+namespace content {
+
+class IndexedDBDatabaseCallbacksImpl
+    : public blink::mojom::IDBDatabaseCallbacks {
+ public:
+  explicit IndexedDBDatabaseCallbacksImpl(
+      std::unique_ptr<blink::WebIDBDatabaseCallbacks> callbacks);
+  ~IndexedDBDatabaseCallbacksImpl() override;
+
+  // blink::mojom::IDBDatabaseCallbacks implementation
+  void ForcedClose() override;
+  void VersionChange(int64_t old_version, int64_t new_version) override;
+  void Abort(int64_t transaction_id,
+             int32_t code,
+             const base::string16& message) override;
+  void Complete(int64_t transaction_id) override;
+  void Changes(blink::mojom::IDBObserverChangesPtr changes) override;
+
+ private:
+  std::unique_ptr<blink::WebIDBDatabaseCallbacks> callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseCallbacksImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
diff --git a/content/renderer/indexed_db/indexed_db_dispatcher.cc b/content/renderer/indexed_db/indexed_db_dispatcher.cc
new file mode 100644
index 0000000..6237adb
--- /dev/null
+++ b/content/renderer/indexed_db/indexed_db_dispatcher.cc
@@ -0,0 +1,80 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_local.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
+#include "content/renderer/indexed_db/webidbcursor_impl.h"
+#include "ipc/ipc_channel.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_observation.h"
+
+using blink::WebIDBKey;
+using blink::WebIDBObservation;
+using base::ThreadLocalPointer;
+
+namespace content {
+static base::LazyInstance<ThreadLocalPointer<IndexedDBDispatcher>>::Leaky
+    g_idb_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
+
+namespace {
+
+IndexedDBDispatcher* const kDeletedIndexedDBDispatcherMarker =
+    reinterpret_cast<IndexedDBDispatcher*>(0x1);
+
+}  // unnamed namespace
+
+IndexedDBDispatcher::IndexedDBDispatcher() {
+  g_idb_dispatcher_tls.Pointer()->Set(this);
+}
+
+IndexedDBDispatcher::~IndexedDBDispatcher() {
+  g_idb_dispatcher_tls.Pointer()->Set(kDeletedIndexedDBDispatcherMarker);
+}
+
+IndexedDBDispatcher* IndexedDBDispatcher::ThreadSpecificInstance() {
+  if (g_idb_dispatcher_tls.Pointer()->Get() ==
+      kDeletedIndexedDBDispatcherMarker) {
+    NOTREACHED() << "Re-instantiating TLS IndexedDBDispatcher.";
+    g_idb_dispatcher_tls.Pointer()->Set(nullptr);
+  }
+  if (g_idb_dispatcher_tls.Pointer()->Get())
+    return g_idb_dispatcher_tls.Pointer()->Get();
+
+  IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher();
+  if (WorkerThread::GetCurrentId())
+    WorkerThread::AddObserver(dispatcher);
+  return dispatcher;
+}
+
+void IndexedDBDispatcher::WillStopCurrentWorkerThread() {
+  delete this;
+}
+
+void IndexedDBDispatcher::RegisterCursor(WebIDBCursorImpl* cursor) {
+  DCHECK(!base::ContainsKey(cursors_, cursor));
+  cursors_.insert(cursor);
+}
+
+void IndexedDBDispatcher::UnregisterCursor(WebIDBCursorImpl* cursor) {
+  DCHECK(base::ContainsKey(cursors_, cursor));
+  cursors_.erase(cursor);
+}
+
+void IndexedDBDispatcher::ResetCursorPrefetchCaches(
+    int64_t transaction_id,
+    WebIDBCursorImpl* exception_cursor) {
+  for (WebIDBCursorImpl* cursor : cursors_) {
+    if (cursor != exception_cursor &&
+        cursor->transaction_id() == transaction_id)
+      cursor->ResetPrefetchCache();
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/indexed_db/indexed_db_dispatcher.h b/content/renderer/indexed_db/indexed_db_dispatcher.h
new file mode 100644
index 0000000..1863778
--- /dev/null
+++ b/content/renderer/indexed_db/indexed_db_dispatcher.h
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DISPATCHER_H_
+#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DISPATCHER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/strings/nullable_string16.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/worker_thread.h"
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_database_callbacks_impl.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
+#include "url/origin.h"
+
+namespace content {
+class WebIDBCursorImpl;
+
+// Handle the indexed db related communication for this context thread - the
+// main thread and each worker thread have their own copies.
+class CONTENT_EXPORT IndexedDBDispatcher : public WorkerThread::Observer {
+ public:
+  // Constructor made public to allow RenderThreadImpl to own a copy without
+  // failing a NOTREACHED in ThreadSpecificInstance in tests that instantiate
+  // two copies of RenderThreadImpl on the same thread.  Everyone else probably
+  // wants to use ThreadSpecificInstance().
+  IndexedDBDispatcher();
+  ~IndexedDBDispatcher() override;
+
+  static IndexedDBDispatcher* ThreadSpecificInstance();
+
+  // WorkerThread::Observer implementation.
+  void WillStopCurrentWorkerThread() override;
+
+  void RegisterCursor(WebIDBCursorImpl* cursor);
+  void UnregisterCursor(WebIDBCursorImpl* cursor);
+  // Reset cursor prefetch caches for all cursors except exception_cursor.
+  void ResetCursorPrefetchCaches(int64_t transaction_id,
+                                 WebIDBCursorImpl* exception_cursor);
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
+  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
+
+  std::unordered_set<WebIDBCursorImpl*> cursors_;
+
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcher);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DISPATCHER_H_
diff --git a/third_party/blink/renderer/modules/exported/indexed_db_key_builder.cc b/content/renderer/indexed_db/indexed_db_key_builders.cc
similarity index 62%
rename from third_party/blink/renderer/modules/exported/indexed_db_key_builder.cc
rename to content/renderer/indexed_db/indexed_db_key_builders.cc
index 4825b10..ad9b6b22 100644
--- a/third_party/blink/renderer/modules/exported/indexed_db_key_builder.cc
+++ b/content/renderer/indexed_db/indexed_db_key_builders.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
 
 #include <stddef.h>
 
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/logging.h"
 #include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
@@ -17,18 +18,32 @@
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
 
-namespace blink {
+using blink::IndexedDBKey;
+using blink::IndexedDBKeyPath;
+using blink::IndexedDBKeyRange;
+using blink::WebIDBKey;
+using blink::WebIDBKeyRange;
+using blink::WebIDBKeyView;
+using blink::kWebIDBKeyTypeArray;
+using blink::kWebIDBKeyTypeBinary;
+using blink::kWebIDBKeyTypeDate;
+using blink::kWebIDBKeyTypeInvalid;
+using blink::kWebIDBKeyTypeMin;
+using blink::kWebIDBKeyTypeNull;
+using blink::kWebIDBKeyTypeNumber;
+using blink::kWebIDBKeyTypeString;
+using blink::WebVector;
+using blink::WebString;
 
 namespace {
 
-IndexedDBKey::KeyArray CopyKeyArray(WebIDBKeyArrayView array) {
+IndexedDBKey::KeyArray CopyKeyArray(blink::WebIDBKeyArrayView array) {
   IndexedDBKey::KeyArray result;
   const size_t array_size = array.size();
   result.reserve(array_size);
   for (size_t i = 0; i < array_size; ++i)
-    result.emplace_back(IndexedDBKeyBuilder::Build(array[i]));
+    result.emplace_back(content::IndexedDBKeyBuilder::Build(array[i]));
   return result;
 }
 
@@ -42,13 +57,15 @@
 
 }  // anonymous namespace
 
+namespace content {
+
 // static
-IndexedDBKey IndexedDBKeyBuilder::Build(WebIDBKeyView key) {
+IndexedDBKey IndexedDBKeyBuilder::Build(blink::WebIDBKeyView key) {
   switch (key.KeyType()) {
     case kWebIDBKeyTypeArray:
       return IndexedDBKey(CopyKeyArray(key.ArrayView()));
     case kWebIDBKeyTypeBinary: {
-      const WebData data = key.Binary();
+      const blink::WebData data = key.Binary();
       std::string key_string;
       key_string.reserve(data.size());
 
@@ -70,44 +87,13 @@
     case kWebIDBKeyTypeInvalid:
       return IndexedDBKey(key.KeyType());
     case kWebIDBKeyTypeMin:
+    default:
       NOTREACHED();
       return IndexedDBKey();
   }
 }
 
 // static
-WebIDBKey WebIDBKeyBuilder::Build(const WebIDBKeyView& key) {
-  switch (key.KeyType()) {
-    case kWebIDBKeyTypeArray: {
-      const WebIDBKeyArrayView& array = key.ArrayView();
-      WebVector<WebIDBKey> web_idb_keys;
-      const size_t array_size = array.size();
-      web_idb_keys.reserve(array_size);
-      for (size_t i = 0; i < array_size; ++i)
-        web_idb_keys.emplace_back(Build(array[i]));
-      return WebIDBKey::CreateArray(std::move(web_idb_keys));
-    }
-    case kWebIDBKeyTypeBinary: {
-      const WebData data = key.Binary();
-      return WebIDBKey::CreateBinary(data);
-    }
-    case kWebIDBKeyTypeString:
-      return WebIDBKey::CreateString(key.String());
-    case kWebIDBKeyTypeDate:
-      return WebIDBKey::CreateDate(key.Date());
-    case kWebIDBKeyTypeNumber:
-      return WebIDBKey::CreateNumber(key.Number());
-    case kWebIDBKeyTypeInvalid:
-      return WebIDBKey::CreateInvalid();
-    case kWebIDBKeyTypeNull:
-      return WebIDBKey::CreateNull();
-    case kWebIDBKeyTypeMin:
-      NOTREACHED();
-      return WebIDBKey::CreateInvalid();
-  }
-}
-
-// static
 WebIDBKey WebIDBKeyBuilder::Build(const IndexedDBKey& key) {
   switch (key.type()) {
     case kWebIDBKeyTypeArray: {
@@ -118,11 +104,8 @@
         web_idb_keys.emplace_back(Build(array_element));
       return WebIDBKey::CreateArray(std::move(web_idb_keys));
     }
-    case kWebIDBKeyTypeBinary: {
-      const std::string& str = key.binary();
-      const WebData& data = WebData(str.c_str(), str.length());
-      return WebIDBKey::CreateBinary(data);
-    }
+    case kWebIDBKeyTypeBinary:
+      return WebIDBKey::CreateBinary(key.binary());
     case kWebIDBKeyTypeString:
       return WebIDBKey::CreateString(WebString::FromUTF16(key.string()));
     case kWebIDBKeyTypeDate:
@@ -134,6 +117,7 @@
     case kWebIDBKeyTypeNull:
       return WebIDBKey::CreateNull();
     case kWebIDBKeyTypeMin:
+    default:
       NOTREACHED();
       return WebIDBKey::CreateInvalid();
   }
@@ -155,13 +139,6 @@
 }
 
 // static
-WebIDBKeyRange WebIDBKeyRangeBuilder::Build(WebIDBKeyView key) {
-  return WebIDBKeyRange(WebIDBKeyBuilder::Build(key),
-                        WebIDBKeyBuilder::Build(key), false /* lower_open */,
-                        false /* upper_open */);
-}
-
-// static
 WebIDBKeyRange WebIDBKeyRangeBuilder::Build(
     const IndexedDBKeyRange& key_range) {
   return WebIDBKeyRange(WebIDBKeyBuilder::Build(key_range.lower()),
@@ -170,31 +147,43 @@
 }
 
 // static
-IndexedDBKeyPath IndexedDBKeyPathBuilder::Build(const WebIDBKeyPath& key_path) {
+IndexedDBKeyPath IndexedDBKeyPathBuilder::Build(
+    const blink::WebIDBKeyPath& key_path) {
   switch (key_path.KeyPathType()) {
-    case kWebIDBKeyPathTypeString:
+    case blink::kWebIDBKeyPathTypeString:
       return IndexedDBKeyPath(key_path.String().Utf16());
-    case kWebIDBKeyPathTypeArray:
+    case blink::kWebIDBKeyPathTypeArray:
       return IndexedDBKeyPath(CopyArray(key_path.Array()));
-    case kWebIDBKeyPathTypeNull:
+    case blink::kWebIDBKeyPathTypeNull:
+      return IndexedDBKeyPath();
+    default:
+      NOTREACHED();
       return IndexedDBKeyPath();
   }
 }
 
 // static
-WebIDBKeyPath WebIDBKeyPathBuilder::Build(const IndexedDBKeyPath& key_path) {
+blink::WebIDBKeyPath WebIDBKeyPathBuilder::Build(
+    const IndexedDBKeyPath& key_path) {
   switch (key_path.type()) {
-    case kWebIDBKeyPathTypeString:
-      return WebIDBKeyPath::Create(WebString::FromUTF16(key_path.string()));
-    case kWebIDBKeyPathTypeArray: {
+    case blink::kWebIDBKeyPathTypeString:
+      return blink::WebIDBKeyPath::Create(
+          WebString::FromUTF16(key_path.string()));
+    case blink::kWebIDBKeyPathTypeArray: {
       WebVector<WebString> key_path_vector(key_path.array().size());
-      for (const auto& item : key_path.array())
-        key_path_vector.emplace_back(WebString::FromUTF16(item));
-      return WebIDBKeyPath::Create(key_path_vector);
+      std::transform(key_path.array().begin(), key_path.array().end(),
+                     key_path_vector.begin(),
+                     [](const typename base::string16& s) {
+                       return WebString::FromUTF16(s);
+                     });
+      return blink::WebIDBKeyPath::Create(key_path_vector);
     }
-    case kWebIDBKeyPathTypeNull:
-      return WebIDBKeyPath::CreateNull();
+    case blink::kWebIDBKeyPathTypeNull:
+      return blink::WebIDBKeyPath::CreateNull();
+    default:
+      NOTREACHED();
+      return blink::WebIDBKeyPath::CreateNull();
   }
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/content/renderer/indexed_db/indexed_db_key_builders.h b/content/renderer/indexed_db/indexed_db_key_builders.h
new file mode 100644
index 0000000..841dbb41
--- /dev/null
+++ b/content/renderer/indexed_db/indexed_db_key_builders.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_KEY_BUILDERS_H_
+#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_KEY_BUILDERS_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
+
+namespace blink {
+
+class IndexedDBKeyRange;
+class WebIDBKeyPath;
+class WebIDBKeyRange;
+
+}  // namespace blink
+
+namespace content {
+
+class CONTENT_EXPORT IndexedDBKeyBuilder {
+ public:
+  static blink::IndexedDBKey Build(blink::WebIDBKeyView key);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyBuilder);
+};
+
+class CONTENT_EXPORT WebIDBKeyBuilder {
+ public:
+  static blink::WebIDBKey Build(const blink::IndexedDBKey& key);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebIDBKeyBuilder);
+};
+
+class CONTENT_EXPORT IndexedDBKeyRangeBuilder {
+ public:
+  static blink::IndexedDBKeyRange Build(const blink::WebIDBKeyRange& key_range);
+
+  // Builds a point range (containing a single key).
+  static blink::IndexedDBKeyRange Build(blink::WebIDBKeyView key);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyRangeBuilder);
+};
+
+class CONTENT_EXPORT WebIDBKeyRangeBuilder {
+ public:
+  static blink::WebIDBKeyRange Build(const blink::IndexedDBKeyRange& key);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebIDBKeyRangeBuilder);
+};
+
+class CONTENT_EXPORT IndexedDBKeyPathBuilder {
+ public:
+  static blink::IndexedDBKeyPath Build(const blink::WebIDBKeyPath& key_path);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyPathBuilder);
+};
+
+class CONTENT_EXPORT WebIDBKeyPathBuilder {
+ public:
+  static blink::WebIDBKeyPath Build(const blink::IndexedDBKeyPath& key_path);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebIDBKeyPathBuilder);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_KEY_BUILDERS_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc b/content/renderer/indexed_db/mock_webidbcallbacks.cc
similarity index 89%
rename from third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc
rename to content/renderer/indexed_db/mock_webidbcallbacks.cc
index 1f783952..ec05f485 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc
+++ b/content/renderer/indexed_db/mock_webidbcallbacks.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h"
+#include "content/renderer/indexed_db/mock_webidbcallbacks.h"
 
-namespace blink {
+namespace content {
 
 MockWebIDBCallbacks::MockWebIDBCallbacks() {}
 
@@ -36,4 +36,4 @@
   DoOnSuccess(values);
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h b/content/renderer/indexed_db/mock_webidbcallbacks.h
similarity index 90%
rename from third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h
rename to content/renderer/indexed_db/mock_webidbcallbacks.h
index 5c9b71d..ec337180 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h
+++ b/content/renderer/indexed_db/mock_webidbcallbacks.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_CALLBACKS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_CALLBACKS_H_
+#ifndef CONTENT_RENDERER_INDEXED_DB_MOCK_WEBIDBCALLBACKS_H_
+#define CONTENT_RENDERER_INDEXED_DB_MOCK_WEBIDBCALLBACKS_H_
 
 #include "base/macros.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -15,7 +15,7 @@
 #include "third_party/blink/public/platform/web_blob_info.h"
 #include "third_party/blink/public/web/web_heap.h"
 
-namespace blink {
+namespace content {
 
 class MockWebIDBCallbacks : public blink::WebIDBCallbacks {
  public:
@@ -71,6 +71,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockWebIDBCallbacks);
 };
 
-}  // namespace blink
+}  // namespace content
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_MOCK_WEB_IDB_CALLBACKS_H_
+#endif  // CONTENT_RENDERER_INDEXED_DB_MOCK_WEBIDBCALLBACKS_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc b/content/renderer/indexed_db/webidbcursor_impl.cc
similarity index 68%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
rename to content/renderer/indexed_db/webidbcursor_impl.cc
index bdf6aeb4..bdf5ce9 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
+++ b/content/renderer/indexed_db/webidbcursor_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h"
+#include "content/renderer/indexed_db/webidbcursor_impl.h"
 
 #include <stddef.h>
 
@@ -10,11 +10,10 @@
 #include <vector>
 
 #include "base/single_thread_task_runner.h"
+#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h"
 
 using blink::WebBlobInfo;
 using blink::WebData;
@@ -22,13 +21,13 @@
 using blink::WebIDBKey;
 using blink::WebIDBKeyView;
 using blink::WebIDBValue;
-using blink::mojom::blink::IDBCallbacksAssociatedPtrInfo;
-using blink::mojom::blink::IDBCursorAssociatedPtrInfo;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBCursorAssociatedPtrInfo;
 
-namespace blink {
+namespace content {
 
 WebIDBCursorImpl::WebIDBCursorImpl(
-    mojom::blink::IDBCursorAssociatedPtrInfo cursor_info,
+    blink::mojom::IDBCursorAssociatedPtrInfo cursor_info,
     int64_t transaction_id)
     : transaction_id_(transaction_id),
       cursor_(std::move(cursor_info)),
@@ -37,7 +36,7 @@
       pending_onsuccess_callbacks_(0),
       prefetch_amount_(kMinPrefetchAmount),
       weak_factory_(this) {
-  IndexedDBDispatcher::RegisterCursor(this);
+  IndexedDBDispatcher::ThreadSpecificInstance()->RegisterCursor(this);
 }
 
 WebIDBCursorImpl::~WebIDBCursorImpl() {
@@ -45,7 +44,7 @@
   // object since inside WebKit, they hold a reference to the object which owns
   // this object. But, if that ever changed, then we'd need to invalidate
   // any such pointers.
-  IndexedDBDispatcher::UnregisterCursor(this);
+  IndexedDBDispatcher::ThreadSpecificInstance()->UnregisterCursor(this);
 }
 
 void WebIDBCursorImpl::Advance(unsigned long count,
@@ -58,7 +57,8 @@
   ResetPrefetchCache();
 
   // Reset all cursor prefetch caches except for this cursor.
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, this);
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id_, this);
 
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr());
@@ -70,12 +70,12 @@
                                       WebIDBCallbacks* callbacks_ptr) {
   std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
 
-  if (key.KeyType() == kWebIDBKeyTypeNull &&
-      primary_key.KeyType() == kWebIDBKeyTypeNull) {
+  if (key.KeyType() == blink::kWebIDBKeyTypeNull &&
+      primary_key.KeyType() == blink::kWebIDBKeyTypeNull) {
     // No key(s), so this would qualify for a prefetch.
     ++continue_count_;
 
-    if (!prefetch_keys_.IsEmpty()) {
+    if (!prefetch_keys_.empty()) {
       // We have a prefetch cache, so serve the result from that.
       CachedContinue(callbacks.get());
       return;
@@ -103,12 +103,13 @@
   }
 
   // Reset all cursor prefetch caches except for this cursor.
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id_, this);
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id_, this);
 
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr());
-  cursor_->CursorContinue(WebIDBKeyBuilder::Build(key),
-                          WebIDBKeyBuilder::Build(primary_key),
+  cursor_->CursorContinue(IndexedDBKeyBuilder::Build(key),
+                          IndexedDBKeyBuilder::Build(primary_key),
                           GetCallbacksProxy(std::move(callbacks_impl)));
 }
 
@@ -125,18 +126,14 @@
     ResetPrefetchCache();
 }
 
-void WebIDBCursorImpl::SetPrefetchData(Vector<WebIDBKey> keys,
-                                       Vector<WebIDBKey> primary_keys,
-                                       Vector<WebIDBValue> values) {
-  // Keys and values are stored in reverse order so that a cache'd continue can
-  // pop a value off of the back and prevent new memory allocations.
-  prefetch_keys_.AppendRange(std::make_move_iterator(keys.rbegin()),
-                             std::make_move_iterator(keys.rend()));
-  prefetch_primary_keys_.AppendRange(
-      std::make_move_iterator(primary_keys.rbegin()),
-      std::make_move_iterator(primary_keys.rend()));
-  prefetch_values_.AppendRange(std::make_move_iterator(values.rbegin()),
-                               std::make_move_iterator(values.rend()));
+void WebIDBCursorImpl::SetPrefetchData(
+    const std::vector<IndexedDBKey>& keys,
+    const std::vector<IndexedDBKey>& primary_keys,
+    std::vector<WebIDBValue> values) {
+  prefetch_keys_.assign(keys.begin(), keys.end());
+  prefetch_primary_keys_.assign(primary_keys.begin(), primary_keys.end());
+  prefetch_values_.assign(std::make_move_iterator(values.begin()),
+                          std::make_move_iterator(values.end()));
 
   used_prefetches_ = 0;
   pending_onsuccess_callbacks_ = 0;
@@ -149,9 +146,9 @@
   DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
 
   while (count > 1) {
-    prefetch_keys_.pop_back();
-    prefetch_primary_keys_.pop_back();
-    prefetch_values_.pop_back();
+    prefetch_keys_.pop_front();
+    prefetch_primary_keys_.pop_front();
+    prefetch_values_.pop_front();
     ++used_prefetches_;
     --count;
   }
@@ -164,15 +161,13 @@
   DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
   DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
 
-  // Keys and values are stored in reverse order so that a cache'd continue can
-  // pop a value off of the back and prevent new memory allocations.
-  WebIDBKey key = std::move(prefetch_keys_.back());
-  WebIDBKey primary_key = std::move(prefetch_primary_keys_.back());
-  WebIDBValue value = std::move(prefetch_values_.back());
+  IndexedDBKey key = prefetch_keys_.front();
+  IndexedDBKey primary_key = prefetch_primary_keys_.front();
+  WebIDBValue value = std::move(prefetch_values_.front());
 
-  prefetch_keys_.pop_back();
-  prefetch_primary_keys_.pop_back();
-  prefetch_values_.pop_back();
+  prefetch_keys_.pop_front();
+  prefetch_primary_keys_.pop_front();
+  prefetch_values_.pop_front();
   ++used_prefetches_;
 
   ++pending_onsuccess_callbacks_;
@@ -185,15 +180,15 @@
     ResetPrefetchCache();
   }
 
-  callbacks->OnSuccess(std::move(key), std::move(primary_key),
-                       std::move(value));
+  callbacks->OnSuccess(WebIDBKeyBuilder::Build(key),
+                       WebIDBKeyBuilder::Build(primary_key), std::move(value));
 }
 
 void WebIDBCursorImpl::ResetPrefetchCache() {
   continue_count_ = 0;
   prefetch_amount_ = kMinPrefetchAmount;
 
-  if (prefetch_keys_.IsEmpty()) {
+  if (prefetch_keys_.empty()) {
     // No prefetch cache, so no need to reset the cursor in the back-end.
     return;
   }
@@ -217,4 +212,4 @@
   return ptr_info;
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/content/renderer/indexed_db/webidbcursor_impl.h b/content/renderer/indexed_db/webidbcursor_impl.h
new file mode 100644
index 0000000..39baa2c
--- /dev/null
+++ b/content/renderer/indexed_db/webidbcursor_impl.h
@@ -0,0 +1,95 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INDEXED_DB_WEBIDBCURSOR_IMPL_H_
+#define CONTENT_RENDERER_INDEXED_DB_WEBIDBCURSOR_IMPL_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/containers/circular_deque.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
+
+namespace content {
+
+class IndexedDBCallbacksImpl;
+
+class CONTENT_EXPORT WebIDBCursorImpl : public blink::WebIDBCursor {
+ public:
+  WebIDBCursorImpl(blink::mojom::IDBCursorAssociatedPtrInfo cursor,
+                   int64_t transaction_id);
+  ~WebIDBCursorImpl() override;
+
+  void Advance(unsigned long count, blink::WebIDBCallbacks* callback) override;
+  void CursorContinue(blink::WebIDBKeyView key,
+                      blink::WebIDBKeyView primary_key,
+                      blink::WebIDBCallbacks* callback) override;
+  void PostSuccessHandlerCallback() override;
+
+  void SetPrefetchData(const std::vector<blink::IndexedDBKey>& keys,
+                       const std::vector<blink::IndexedDBKey>& primary_keys,
+                       std::vector<blink::WebIDBValue> values);
+
+  void CachedAdvance(unsigned long count, blink::WebIDBCallbacks* callbacks);
+  void CachedContinue(blink::WebIDBCallbacks* callbacks);
+
+  // This method is virtual so it can be overridden in unit tests.
+  virtual void ResetPrefetchCache();
+
+  int64_t transaction_id() const { return transaction_id_; }
+
+ private:
+  blink::mojom::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
+      std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
+
+  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
+  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
+  FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, AdvancePrefetchTest);
+  FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchReset);
+  FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
+
+  enum { kInvalidCursorId = -1 };
+  enum { kPrefetchContinueThreshold = 2 };
+  enum { kMinPrefetchAmount = 5 };
+  enum { kMaxPrefetchAmount = 100 };
+
+  int64_t transaction_id_;
+
+  blink::mojom::IDBCursorAssociatedPtr cursor_;
+
+  // Prefetch cache.
+  base::circular_deque<blink::IndexedDBKey> prefetch_keys_;
+  base::circular_deque<blink::IndexedDBKey> prefetch_primary_keys_;
+  base::circular_deque<blink::WebIDBValue> prefetch_values_;
+
+  // Number of continue calls that would qualify for a pre-fetch.
+  int continue_count_;
+
+  // Number of items used from the last prefetch.
+  int used_prefetches_;
+
+  // Number of onsuccess handlers we are waiting for.
+  int pending_onsuccess_callbacks_;
+
+  // Number of items to request in next prefetch.
+  int prefetch_amount_;
+
+  base::WeakPtrFactory<WebIDBCursorImpl> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_INDEXED_DB_WEBIDBCURSOR_IMPL_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/content/renderer/indexed_db/webidbcursor_impl_unittest.cc
similarity index 79%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
rename to content/renderer/indexed_db/webidbcursor_impl_unittest.cc
index 8c66de4..212b216 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
+++ b/content/renderer/indexed_db/webidbcursor_impl_unittest.cc
@@ -2,23 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h"
+#include "content/renderer/indexed_db/webidbcursor_impl.h"
 
 #include <stddef.h>
 #include <stdint.h>
 
 #include <memory>
 
+#include "base/guid.h"
 #include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/values.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
+#include "content/renderer/indexed_db/mock_webidbcallbacks.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_data.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
 using blink::IndexedDBKey;
 using blink::WebBlobInfo;
@@ -29,16 +32,16 @@
 using blink::WebIDBValue;
 using blink::WebString;
 using blink::WebVector;
-using blink::mojom::blink::IDBCursor;
+using blink::mojom::IDBCursor;
 using testing::StrictMock;
 
-namespace blink {
+namespace content {
 
 namespace {
 
 class MockCursorImpl : public IDBCursor {
  public:
-  explicit MockCursorImpl(mojom::blink::IDBCursorAssociatedRequest request)
+  explicit MockCursorImpl(blink::mojom::IDBCursorAssociatedRequest request)
       : binding_(this, std::move(request)) {
     binding_.set_connection_error_handler(base::BindOnce(
         &MockCursorImpl::CursorDestroyed, base::Unretained(this)));
@@ -46,7 +49,7 @@
 
   void Prefetch(
       int32_t count,
-      mojom::blink::IDBCallbacksAssociatedPtrInfo callbacks) override {
+      blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override {
     ++prefetch_calls_;
     last_prefetch_count_ = count;
   }
@@ -58,14 +61,14 @@
   }
 
   void Advance(uint32_t count,
-               mojom::blink::IDBCallbacksAssociatedPtrInfo callbacks) override {
+               blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override {
     ++advance_calls_;
   }
 
   void CursorContinue(
-      WebIDBKey key,
-      WebIDBKey primary_key,
-      mojom::blink::IDBCallbacksAssociatedPtrInfo callbacks) override {
+      const IndexedDBKey& key,
+      const IndexedDBKey& primary_key,
+      blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks) override {
     ++continue_calls_;
   }
 
@@ -116,14 +119,14 @@
 class WebIDBCursorImplTest : public testing::Test {
  public:
   WebIDBCursorImplTest() : null_key_(WebIDBKey::CreateNull()) {
-    mojom::blink::IDBCursorAssociatedPtr ptr;
+    blink::mojom::IDBCursorAssociatedPtr ptr;
     mock_cursor_ = std::make_unique<MockCursorImpl>(
         mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr));
     cursor_ = std::make_unique<WebIDBCursorImpl>(ptr.PassInterface(), 1);
   }
 
  protected:
-  ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   WebIDBKey null_key_;
   std::unique_ptr<WebIDBCursorImpl> cursor_;
   std::unique_ptr<MockCursorImpl> mock_cursor_;
@@ -139,7 +142,7 @@
   for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
     cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                             new MockContinueCallbacks());
-    platform_->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls());
     EXPECT_EQ(0, mock_cursor_->prefetch_calls());
   }
@@ -154,7 +157,7 @@
     // Initiate the prefetch
     cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                             new MockContinueCallbacks());
-    platform_->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
     EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls());
 
@@ -164,22 +167,17 @@
     last_prefetch_count = prefetch_count;
 
     // Fill the prefetch cache as requested.
-    Vector<WebIDBKey> keys;
-    Vector<WebIDBKey> primary_keys;
-    Vector<WebIDBValue> values;
-    size_t expected_size = 0;
+    std::vector<IndexedDBKey> keys;
+    std::vector<IndexedDBKey> primary_keys;
+    std::vector<WebIDBValue> values;
     for (int i = 0; i < prefetch_count; ++i) {
-      WebIDBKey key = WebIDBKey::CreateNumber(expected_key + i);
-      keys.emplace_back(std::move(key));
+      keys.emplace_back(expected_key + i, kWebIDBKeyTypeNumber);
       primary_keys.emplace_back();
-      expected_size++;
-      EXPECT_EQ(expected_size, keys.size());
-      EXPECT_EQ(expected_size, primary_keys.size());
       WebVector<WebBlobInfo> blob_info;
       blob_info.reserve(expected_key + i);
       for (int j = 0; j < expected_key + i; ++j) {
         blob_info.emplace_back(WebBlobInfo::BlobForTesting(
-            WebString("blobuuid"), "text/plain", 123));
+            WebString::FromLatin1(base::GenerateGUID()), "text/plain", 123));
       }
       values.emplace_back(WebData(), std::move(blob_info));
     }
@@ -196,7 +194,7 @@
       WebVector<WebBlobInfo> blobs;
       cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                               new MockContinueCallbacks(&key, &blobs));
-      platform_->RunUntilIdle();
+      base::RunLoop().RunUntilIdle();
       EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
       EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls());
 
@@ -207,7 +205,7 @@
   }
 
   cursor_.reset();
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(mock_cursor_->destroyed());
 }
 
@@ -218,14 +216,14 @@
     cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                             new MockContinueCallbacks());
   }
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, mock_cursor_->prefetch_calls());
 
   // Initiate the prefetch
   cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                           new MockContinueCallbacks());
 
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, mock_cursor_->prefetch_calls());
   EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
             mock_cursor_->continue_calls());
@@ -235,22 +233,17 @@
 
   // Fill the prefetch cache as requested.
   int expected_key = 0;
-  Vector<WebIDBKey> keys;
-  Vector<WebIDBKey> primary_keys;
-  Vector<WebIDBValue> values;
-  size_t expected_size = 0;
+  std::vector<IndexedDBKey> keys;
+  std::vector<IndexedDBKey> primary_keys;
+  std::vector<WebIDBValue> values;
   for (int i = 0; i < prefetch_count; ++i) {
-    WebIDBKey key = WebIDBKey::CreateNumber(expected_key + i);
-    keys.emplace_back(std::move(key));
+    keys.emplace_back(expected_key + i, kWebIDBKeyTypeNumber);
     primary_keys.emplace_back();
-    expected_size++;
-    EXPECT_EQ(expected_size, keys.size());
-    EXPECT_EQ(expected_size, primary_keys.size());
     WebVector<WebBlobInfo> blob_info;
     blob_info.reserve(expected_key + i);
     for (int j = 0; j < expected_key + i; ++j) {
-      blob_info.emplace_back(WebBlobInfo::BlobForTesting(WebString("blobuuid"),
-                                                         "text/plain", 123));
+      blob_info.emplace_back(WebBlobInfo::BlobForTesting(
+          WebString::FromLatin1(base::GenerateGUID()), "text/plain", 123));
     }
     values.emplace_back(WebData(), std::move(blob_info));
   }
@@ -268,23 +261,23 @@
   IndexedDBKey key;
   cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                           new MockContinueCallbacks(&key));
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, key.number());
 
   // IDBCursor.advance(1)
   cursor_->Advance(1, new MockContinueCallbacks(&key));
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, key.number());
 
   // IDBCursor.continue()
   cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                           new MockContinueCallbacks(&key));
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2, key.number());
 
   // IDBCursor.advance(2)
   cursor_->Advance(2, new MockContinueCallbacks(&key));
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(4, key.number());
 
   EXPECT_EQ(0, mock_cursor_->advance_calls());
@@ -292,14 +285,14 @@
   // IDBCursor.advance(lots) - beyond the fetched amount
   cursor_->Advance(WebIDBCursorImpl::kMaxPrefetchAmount,
                    new MockContinueCallbacks(&key));
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, mock_cursor_->advance_calls());
   EXPECT_EQ(1, mock_cursor_->prefetch_calls());
   EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
             mock_cursor_->continue_calls());
 
   cursor_.reset();
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(mock_cursor_->destroyed());
 }
 
@@ -310,7 +303,7 @@
   for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
     cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                             new MockContinueCallbacks());
-    platform_->RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
     EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls());
     EXPECT_EQ(0, mock_cursor_->prefetch_calls());
   }
@@ -318,7 +311,7 @@
   // Initiate the prefetch
   cursor_->CursorContinue(null_key_.View(), null_key_.View(),
                           new MockContinueCallbacks());
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(continue_calls, mock_cursor_->continue_calls());
   EXPECT_EQ(1, mock_cursor_->prefetch_calls());
   EXPECT_EQ(0, mock_cursor_->reset_calls());
@@ -327,21 +320,21 @@
   cursor_->ResetPrefetchCache();
 
   // No reset should have been sent since nothing has been received yet.
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, mock_cursor_->reset_calls());
 
   // Fill the prefetch cache as requested.
   int prefetch_count = mock_cursor_->last_prefetch_count();
-  Vector<WebIDBKey> keys(prefetch_count);
-  Vector<WebIDBKey> primary_keys(prefetch_count);
-  Vector<WebIDBValue> values;
+  std::vector<IndexedDBKey> keys(prefetch_count);
+  std::vector<IndexedDBKey> primary_keys(prefetch_count);
+  std::vector<WebIDBValue> values;
   for (int i = 0; i < prefetch_count; ++i)
     values.emplace_back(WebData(), WebVector<WebBlobInfo>());
   cursor_->SetPrefetchData(std::move(keys), std::move(primary_keys),
                            std::move(values));
 
   // No reset should have been sent since prefetch data hasn't been used.
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, mock_cursor_->reset_calls());
 
   // The real dispatcher would call cursor->CachedContinue(), so do that:
@@ -349,13 +342,13 @@
   cursor_->CachedContinue(&callbacks);
 
   // Now the cursor should have reset the rest of the cache.
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, mock_cursor_->reset_calls());
   EXPECT_EQ(1, mock_cursor_->last_used_count());
 
   cursor_.reset();
-  platform_->RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(mock_cursor_->destroyed());
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/content/renderer/indexed_db/webidbdatabase_impl.cc b/content/renderer/indexed_db/webidbdatabase_impl.cc
new file mode 100644
index 0000000..ae54492
--- /dev/null
+++ b/content/renderer/indexed_db/webidbdatabase_impl.cc
@@ -0,0 +1,360 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/indexed_db/webidbdatabase_impl.h"
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/format_macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/stringprintf.h"
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
+#include "content/renderer/indexed_db/indexed_db_key_builders.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_path.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
+#include "third_party/blink/public/platform/web_blob_info.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_vector.h"
+
+using blink::IndexedDBKey;
+using blink::IndexedDBIndexKeys;
+using blink::WebBlobInfo;
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBDatabaseCallbacks;
+using blink::WebIDBMetadata;
+using blink::WebIDBKey;
+using blink::WebIDBKeyPath;
+using blink::WebIDBKeyRange;
+using blink::WebIDBKeyView;
+using blink::WebString;
+using blink::WebVector;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseAssociatedPtrInfo;
+
+namespace content {
+
+namespace {
+
+std::vector<IndexedDBIndexKeys> ConvertWebIndexKeys(
+    const WebVector<blink::WebIDBIndexKeys>& index_keys) {
+  std::vector<IndexedDBIndexKeys> result;
+  result.reserve(index_keys.size());
+  for (size_t i = 0, len = index_keys.size(); i < len; ++i) {
+    result.emplace_back(index_keys[i].first, std::vector<IndexedDBKey>());
+    std::vector<IndexedDBKey>& result_keys = result.back().second;
+    result_keys.reserve(index_keys[i].second.size());
+    for (const WebIDBKey& index_key : index_keys[i].second)
+      result_keys.emplace_back(IndexedDBKeyBuilder::Build(index_key.View()));
+  }
+  return result;
+}
+
+}  // namespace
+
+WebIDBDatabaseImpl::WebIDBDatabaseImpl(
+    IDBDatabaseAssociatedPtrInfo database_info)
+    : database_(std::move(database_info)) {}
+
+WebIDBDatabaseImpl::~WebIDBDatabaseImpl() = default;
+
+void WebIDBDatabaseImpl::CreateObjectStore(long long transaction_id,
+                                           long long object_store_id,
+                                           const WebString& name,
+                                           const WebIDBKeyPath& key_path,
+                                           bool auto_increment) {
+  database_->CreateObjectStore(transaction_id, object_store_id, name.Utf16(),
+                               IndexedDBKeyPathBuilder::Build(key_path),
+                               auto_increment);
+}
+
+void WebIDBDatabaseImpl::DeleteObjectStore(long long transaction_id,
+                                           long long object_store_id) {
+  database_->DeleteObjectStore(transaction_id, object_store_id);
+}
+
+void WebIDBDatabaseImpl::RenameObjectStore(long long transaction_id,
+                                           long long object_store_id,
+                                           const blink::WebString& new_name) {
+  database_->RenameObjectStore(transaction_id, object_store_id,
+                               new_name.Utf16());
+}
+
+void WebIDBDatabaseImpl::CreateTransaction(
+    long long transaction_id,
+    const WebVector<long long>& object_store_ids,
+    blink::WebIDBTransactionMode mode) {
+  database_->CreateTransaction(
+      transaction_id,
+      std::vector<int64_t>(object_store_ids.begin(), object_store_ids.end()),
+      mode);
+}
+
+void WebIDBDatabaseImpl::Close() {
+  database_->Close();
+}
+
+void WebIDBDatabaseImpl::VersionChangeIgnored() {
+  database_->VersionChangeIgnored();
+}
+
+void WebIDBDatabaseImpl::AddObserver(
+    long long transaction_id,
+    int32_t observer_id,
+    bool include_transaction,
+    bool no_records,
+    bool values,
+    const std::bitset<blink::kWebIDBOperationTypeCount>& operation_types) {
+  static_assert(blink::kWebIDBOperationTypeCount < sizeof(uint16_t) * CHAR_BIT,
+                "WebIDBOperationType Count exceeds size of uint16_t");
+  database_->AddObserver(transaction_id, observer_id, include_transaction,
+                         no_records, values, operation_types.to_ulong());
+}
+
+void WebIDBDatabaseImpl::RemoveObservers(
+    const WebVector<int32_t>& observer_ids_to_remove) {
+  std::vector<int32_t> remove_observer_ids(
+      observer_ids_to_remove.Data(),
+      observer_ids_to_remove.Data() + observer_ids_to_remove.size());
+  database_->RemoveObservers(remove_observer_ids);
+}
+
+void WebIDBDatabaseImpl::Get(long long transaction_id,
+                             long long object_store_id,
+                             long long index_id,
+                             const WebIDBKeyRange& key_range,
+                             bool key_only,
+                             WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->Get(transaction_id, object_store_id, index_id,
+                 IndexedDBKeyRangeBuilder::Build(key_range), key_only,
+                 GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::GetAll(long long transaction_id,
+                                long long object_store_id,
+                                long long index_id,
+                                const WebIDBKeyRange& key_range,
+                                long long max_count,
+                                bool key_only,
+                                WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->GetAll(transaction_id, object_store_id, index_id,
+                    IndexedDBKeyRangeBuilder::Build(key_range), key_only,
+                    max_count, GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::Put(
+    long long transaction_id,
+    long long object_store_id,
+    const blink::WebData& value,
+    const WebVector<WebBlobInfo>& web_blob_info,
+    WebIDBKeyView web_primary_key,
+    blink::WebIDBPutMode put_mode,
+    WebIDBCallbacks* callbacks,
+    const WebVector<blink::WebIDBIndexKeys>& index_keys) {
+  IndexedDBKey key = IndexedDBKeyBuilder::Build(web_primary_key);
+
+  if (value.size() + key.size_estimate() > max_put_value_size_) {
+    callbacks->OnError(blink::WebIDBDatabaseError(
+        blink::kWebIDBDatabaseExceptionUnknownError,
+        WebString::FromUTF8(base::StringPrintf(
+            "The serialized value is too large"
+            " (size=%" PRIuS " bytes, max=%" PRIuS " bytes).",
+            value.size(), max_put_value_size_))));
+    return;
+  }
+
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto mojo_value = blink::mojom::IDBValue::New();
+  DCHECK(mojo_value->bits.empty());
+  mojo_value->bits.reserve(value.size());
+  value.ForEachSegment([&mojo_value](const char* segment, size_t segment_size,
+                                     size_t segment_offset) {
+    mojo_value->bits.append(segment, segment_size);
+    return true;
+  });
+  mojo_value->blob_or_file_info.reserve(web_blob_info.size());
+  for (const WebBlobInfo& info : web_blob_info) {
+    auto blob_info = blink::mojom::IDBBlobInfo::New();
+    if (info.IsFile()) {
+      blob_info->file = blink::mojom::IDBFileInfo::New();
+      blob_info->file->path = blink::WebStringToFilePath(info.FilePath());
+      blob_info->file->name = info.FileName().Utf16();
+      blob_info->file->last_modified =
+          base::Time::FromDoubleT(info.LastModified());
+    }
+    blob_info->size = info.size();
+    blob_info->uuid = info.Uuid().Latin1();
+    DCHECK(blob_info->uuid.size());
+    blob_info->mime_type = info.GetType().Utf16();
+    blob_info->blob = blink::mojom::BlobPtrInfo(info.CloneBlobHandle(),
+                                                blink::mojom::Blob::Version_);
+    mojo_value->blob_or_file_info.push_back(std::move(blob_info));
+  }
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->Put(transaction_id, object_store_id, std::move(mojo_value), key,
+                 put_mode, ConvertWebIndexKeys(index_keys),
+                 GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::SetIndexKeys(
+    long long transaction_id,
+    long long object_store_id,
+    WebIDBKeyView primary_key,
+    const WebVector<blink::WebIDBIndexKeys>& index_keys) {
+  database_->SetIndexKeys(transaction_id, object_store_id,
+                          IndexedDBKeyBuilder::Build(primary_key),
+                          ConvertWebIndexKeys(index_keys));
+}
+
+void WebIDBDatabaseImpl::SetIndexesReady(
+    long long transaction_id,
+    long long object_store_id,
+    const WebVector<long long>& web_index_ids) {
+  std::vector<int64_t> index_ids(web_index_ids.Data(),
+                                 web_index_ids.Data() + web_index_ids.size());
+  database_->SetIndexesReady(transaction_id, object_store_id,
+                             std::move(index_ids));
+}
+
+void WebIDBDatabaseImpl::OpenCursor(long long transaction_id,
+                                    long long object_store_id,
+                                    long long index_id,
+                                    const WebIDBKeyRange& key_range,
+                                    blink::WebIDBCursorDirection direction,
+                                    bool key_only,
+                                    blink::WebIDBTaskType task_type,
+                                    WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->OpenCursor(transaction_id, object_store_id, index_id,
+                        IndexedDBKeyRangeBuilder::Build(key_range), direction,
+                        key_only, task_type,
+                        GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::Count(long long transaction_id,
+                               long long object_store_id,
+                               long long index_id,
+                               const WebIDBKeyRange& key_range,
+                               WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->Count(transaction_id, object_store_id, index_id,
+                   IndexedDBKeyRangeBuilder::Build(key_range),
+                   GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::Delete(long long transaction_id,
+                                long long object_store_id,
+                                WebIDBKeyView primary_key,
+                                WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->DeleteRange(transaction_id, object_store_id,
+                         IndexedDBKeyRangeBuilder::Build(primary_key),
+                         GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::DeleteRange(long long transaction_id,
+                                     long long object_store_id,
+                                     const WebIDBKeyRange& key_range,
+                                     WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->DeleteRange(transaction_id, object_store_id,
+                         IndexedDBKeyRangeBuilder::Build(key_range),
+                         GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::Clear(long long transaction_id,
+                               long long object_store_id,
+                               WebIDBCallbacks* callbacks) {
+  IndexedDBDispatcher::ThreadSpecificInstance()->ResetCursorPrefetchCaches(
+      transaction_id, nullptr);
+
+  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
+      base::WrapUnique(callbacks), transaction_id, nullptr);
+  database_->Clear(transaction_id, object_store_id,
+                   GetCallbacksProxy(std::move(callbacks_impl)));
+}
+
+void WebIDBDatabaseImpl::CreateIndex(long long transaction_id,
+                                     long long object_store_id,
+                                     long long index_id,
+                                     const WebString& name,
+                                     const WebIDBKeyPath& key_path,
+                                     bool unique,
+                                     bool multi_entry) {
+  database_->CreateIndex(transaction_id, object_store_id, index_id,
+                         name.Utf16(), IndexedDBKeyPathBuilder::Build(key_path),
+                         unique, multi_entry);
+}
+
+void WebIDBDatabaseImpl::DeleteIndex(long long transaction_id,
+                                     long long object_store_id,
+                                     long long index_id) {
+  database_->DeleteIndex(transaction_id, object_store_id, index_id);
+}
+
+void WebIDBDatabaseImpl::RenameIndex(long long transaction_id,
+                                     long long object_store_id,
+                                     long long index_id,
+                                     const WebString& new_name) {
+  database_->RenameIndex(transaction_id, object_store_id, index_id,
+                         new_name.Utf16());
+}
+
+void WebIDBDatabaseImpl::Abort(long long transaction_id) {
+  database_->Abort(transaction_id);
+}
+
+void WebIDBDatabaseImpl::Commit(long long transaction_id) {
+  database_->Commit(transaction_id);
+}
+
+IDBCallbacksAssociatedPtrInfo WebIDBDatabaseImpl::GetCallbacksProxy(
+    std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
+  IDBCallbacksAssociatedPtrInfo ptr_info;
+  auto request = mojo::MakeRequest(&ptr_info);
+  mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
+  return ptr_info;
+}
+
+}  // namespace content
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h b/content/renderer/indexed_db/webidbdatabase_impl.h
similarity index 75%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h
rename to content/renderer/indexed_db/webidbdatabase_impl.h
index 8ef41986..d26e1de 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h
+++ b/content/renderer/indexed_db/webidbdatabase_impl.h
@@ -2,43 +2,49 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_IMPL_H_
+#ifndef CONTENT_RENDERER_INDEXED_DB_WEBIDBDATABASE_IMPL_H_
+#define CONTENT_RENDERER_INDEXED_DB_WEBIDBDATABASE_IMPL_H_
 
 #include <stdint.h>
 
 #include <set>
 
+#include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
+#include "content/common/content_export.h"
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 
 namespace blink {
-class IndexedDBCallbacksImpl;
 class WebBlobInfo;
 class WebIDBCallbacks;
+class WebString;
+}  // namespace blink
 
-class MODULES_EXPORT WebIDBDatabaseImpl : public blink::WebIDBDatabase {
+namespace content {
+
+class IndexedDBCallbacksImpl;
+
+class CONTENT_EXPORT WebIDBDatabaseImpl : public blink::WebIDBDatabase {
  public:
-  WebIDBDatabaseImpl(mojom::blink::IDBDatabaseAssociatedPtrInfo database);
+  WebIDBDatabaseImpl(blink::mojom::IDBDatabaseAssociatedPtrInfo database);
   ~WebIDBDatabaseImpl() override;
 
   // blink::WebIDBDatabase
   void CreateObjectStore(long long transaction_id,
                          long long objectstore_id,
-                         const String& name,
+                         const blink::WebString& name,
                          const blink::WebIDBKeyPath&,
                          bool auto_increment) override;
   void DeleteObjectStore(long long transaction_id,
                          long long object_store_id) override;
   void RenameObjectStore(long long transaction_id,
                          long long object_store_id,
-                         const String& new_name) override;
+                         const blink::WebString& new_name) override;
   void CreateTransaction(long long transaction_id,
-                         const Vector<int64_t>& scope,
+                         const blink::WebVector<long long>& scope,
                          blink::WebIDBTransactionMode mode) override;
 
   void Close() override;
@@ -51,7 +57,8 @@
                    bool values,
                    const std::bitset<blink::kWebIDBOperationTypeCount>&
                        operation_types) override;
-  void RemoveObservers(const Vector<int32_t>& observer_ids) override;
+  void RemoveObservers(
+      const blink::WebVector<int32_t>& observer_ids_to_remove) override;
 
   void Get(long long transaction_id,
            long long object_store_id,
@@ -69,18 +76,18 @@
   void Put(long long transaction_id,
            long long object_store_id,
            const blink::WebData& value,
-           const Vector<blink::WebBlobInfo>&,
+           const blink::WebVector<blink::WebBlobInfo>&,
            blink::WebIDBKeyView primary_key,
            blink::WebIDBPutMode,
            blink::WebIDBCallbacks*,
-           const Vector<blink::WebIDBIndexKeys>&) override;
+           const blink::WebVector<blink::WebIDBIndexKeys>&) override;
   void SetIndexKeys(long long transaction_id,
                     long long object_store_id,
                     blink::WebIDBKeyView primary_key,
-                    const Vector<blink::WebIDBIndexKeys>&) override;
+                    const blink::WebVector<blink::WebIDBIndexKeys>&) override;
   void SetIndexesReady(long long transaction_id,
                        long long object_store_id,
-                       const Vector<int64_t>& index_ids) override;
+                       const blink::WebVector<long long>& index_ids) override;
   void OpenCursor(long long transaction_id,
                   long long object_store_id,
                   long long index_id,
@@ -108,7 +115,7 @@
   void CreateIndex(long long transaction_id,
                    long long object_store_id,
                    long long index_id,
-                   const String& name,
+                   const blink::WebString& name,
                    const blink::WebIDBKeyPath&,
                    bool unique,
                    bool multi_entry) override;
@@ -118,12 +125,12 @@
   void RenameIndex(long long transaction_id,
                    long long object_store_id,
                    long long index_id,
-                   const String& new_name) override;
+                   const blink::WebString& new_name) override;
   void Abort(long long transaction_id) override;
   void Commit(long long transaction_id) override;
 
  private:
-  mojom::blink::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
+  blink::mojom::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
       std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
 
   FRIEND_TEST_ALL_PREFIXES(WebIDBDatabaseImplTest, ValueSizeTest);
@@ -134,12 +141,12 @@
   // Used by unit tests to exercise behavior without allocating huge chunks
   // of memory.
   size_t max_put_value_size_ =
-      mojom::blink::kIDBMaxMessageSize - mojom::blink::kIDBMaxMessageOverhead;
+      blink::mojom::kIDBMaxMessageSize - blink::mojom::kIDBMaxMessageOverhead;
 
   std::set<int32_t> observer_ids_;
-  mojom::blink::IDBDatabaseAssociatedPtr database_;
+  blink::mojom::IDBDatabaseAssociatedPtr database_;
 };
 
-}  // namespace blink
+}  // namespace content
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_IMPL_H_
+#endif  // CONTENT_RENDERER_INDEXED_DB_WEBIDBDATABASE_IMPL_H_
diff --git a/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc b/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc
new file mode 100644
index 0000000..39bc0f26e
--- /dev/null
+++ b/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/renderer/indexed_db/mock_webidbcallbacks.h"
+#include "content/renderer/indexed_db/webidbdatabase_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_blob_info.h"
+#include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/public/web/web_heap.h"
+
+using blink::IndexedDBKey;
+using blink::WebBlobInfo;
+using blink::WebData;
+using blink::WebIDBCursor;
+using blink::WebIDBKey;
+using blink::WebVector;
+using testing::_;
+using testing::Invoke;
+using testing::StrictMock;
+using testing::WithArgs;
+
+namespace content {
+
+class WebIDBDatabaseImplTest : public testing::Test {
+ public:
+  WebIDBDatabaseImplTest() {}
+
+  void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); }
+
+ private:
+  TestBrowserThreadBundle thread_bundle_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebIDBDatabaseImplTest);
+};
+
+TEST_F(WebIDBDatabaseImplTest, ValueSizeTest) {
+  // For testing use a much smaller maximum size to prevent allocating >100 MB
+  // of memory, which crashes on memory-constrained systems.
+  const size_t kMaxValueSizeForTesting = 10 * 1024 * 1024;  // 10 MB
+
+  const std::vector<char> data(kMaxValueSizeForTesting + 1);
+  const WebData value(&data.front(), data.size());
+  const WebVector<WebBlobInfo> web_blob_info;
+
+  const int64_t transaction_id = 1;
+  const int64_t object_store_id = 2;
+
+  StrictMock<MockWebIDBCallbacks> callbacks;
+  EXPECT_CALL(callbacks, OnError(_)).Times(1);
+
+  WebIDBDatabaseImpl database_impl(nullptr);
+  database_impl.max_put_value_size_ = kMaxValueSizeForTesting;
+  const WebIDBKey idb_key = WebIDBKey::CreateNumber(0);
+  database_impl.Put(transaction_id, object_store_id, value, web_blob_info,
+                    idb_key.View(), blink::kWebIDBPutModeAddOrUpdate,
+                    &callbacks, WebVector<blink::WebIDBIndexKeys>());
+}
+
+TEST_F(WebIDBDatabaseImplTest, KeyAndValueSizeTest) {
+  // For testing use a much smaller maximum size to prevent allocating >100 MB
+  // of memory, which crashes on memory-constrained systems.
+  const size_t kMaxValueSizeForTesting = 10 * 1024 * 1024;  // 10 MB
+  const size_t kKeySize = 1024 * 1024;
+
+  const std::vector<char> data(kMaxValueSizeForTesting - kKeySize);
+  const WebData value(&data.front(), data.size());
+  const WebVector<WebBlobInfo> web_blob_info;
+  const WebIDBKey key = WebIDBKey::CreateString(blink::WebString::FromUTF16(
+      base::string16(kKeySize / sizeof(base::string16::value_type), 'x')));
+
+  const int64_t transaction_id = 1;
+  const int64_t object_store_id = 2;
+
+  StrictMock<MockWebIDBCallbacks> callbacks;
+  EXPECT_CALL(callbacks, OnError(_)).Times(1);
+
+  WebIDBDatabaseImpl database_impl(nullptr);
+  database_impl.max_put_value_size_ = kMaxValueSizeForTesting;
+  database_impl.Put(transaction_id, object_store_id, value, web_blob_info,
+                    key.View(), blink::kWebIDBPutModeAddOrUpdate, &callbacks,
+                    WebVector<blink::WebIDBIndexKeys>());
+}
+
+}  // namespace content
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc b/content/renderer/indexed_db/webidbfactory_impl.cc
similarity index 71%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
rename to content/renderer/indexed_db/webidbfactory_impl.cc
index f158e08..62682a0 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
+++ b/content/renderer/indexed_db/webidbfactory_impl.cc
@@ -2,19 +2,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h"
+#include "content/renderer/indexed_db/webidbfactory_impl.h"
 
 #include "base/memory/ptr_util.h"
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_database_callbacks_impl.h"
+#include "content/renderer/storage_util.h"
+#include "ipc/ipc_sync_channel.h"
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
 
-namespace blink {
+using blink::WebIDBCallbacks;
+using blink::WebIDBDatabase;
+using blink::WebIDBDatabaseCallbacks;
+using blink::WebSecurityOrigin;
+using blink::WebString;
+using blink::mojom::IDBCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo;
+using blink::mojom::IDBFactoryPtrInfo;
 
-WebIDBFactoryImpl::WebIDBFactoryImpl(
-    mojom::blink::IDBFactoryPtrInfo factory_info)
+namespace content {
+
+WebIDBFactoryImpl::WebIDBFactoryImpl(IDBFactoryPtrInfo factory_info)
     : factory_(std::move(factory_info)) {}
 
 WebIDBFactoryImpl::~WebIDBFactoryImpl() = default;
@@ -27,7 +37,7 @@
       base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
       nullptr);
   factory_->GetDatabaseInfo(GetCallbacksProxy(std::move(callbacks_impl)),
-                            origin);
+                            url::Origin(origin));
 }
 
 void WebIDBFactoryImpl::GetDatabaseNames(
@@ -38,7 +48,7 @@
       base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
       nullptr);
   factory_->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks_impl)),
-                             origin);
+                             url::Origin(origin));
 }
 
 void WebIDBFactoryImpl::Open(
@@ -54,10 +64,9 @@
   auto database_callbacks_impl =
       std::make_unique<IndexedDBDatabaseCallbacksImpl>(
           base::WrapUnique(database_callbacks));
-  DCHECK(!name.IsNull());
   factory_->Open(GetCallbacksProxy(std::move(callbacks_impl)),
                  GetDatabaseCallbacksProxy(std::move(database_callbacks_impl)),
-                 origin, name, version, transaction_id);
+                 url::Origin(origin), name.Utf16(), version, transaction_id);
 }
 
 void WebIDBFactoryImpl::DeleteDatabase(
@@ -69,27 +78,25 @@
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
       nullptr);
-  DCHECK(!name.IsNull());
-  factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks_impl)), origin,
-                           name, force_close);
+  factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks_impl)),
+                           url::Origin(origin), name.Utf16(), force_close);
 }
 
-mojom::blink::IDBCallbacksAssociatedPtrInfo
-WebIDBFactoryImpl::GetCallbacksProxy(
+IDBCallbacksAssociatedPtrInfo WebIDBFactoryImpl::GetCallbacksProxy(
     std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
-  mojom::blink::IDBCallbacksAssociatedPtrInfo ptr_info;
+  IDBCallbacksAssociatedPtrInfo ptr_info;
   auto request = mojo::MakeRequest(&ptr_info);
   mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
   return ptr_info;
 }
 
-mojom::blink::IDBDatabaseCallbacksAssociatedPtrInfo
+IDBDatabaseCallbacksAssociatedPtrInfo
 WebIDBFactoryImpl::GetDatabaseCallbacksProxy(
     std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks) {
-  mojom::blink::IDBDatabaseCallbacksAssociatedPtrInfo ptr_info;
+  IDBDatabaseCallbacksAssociatedPtrInfo ptr_info;
   auto request = mojo::MakeRequest(&ptr_info);
   mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
   return ptr_info;
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h b/content/renderer/indexed_db/webidbfactory_impl.h
similarity index 63%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
rename to content/renderer/indexed_db/webidbfactory_impl.h
index dbc69d8..619ea19 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
+++ b/content/renderer/indexed_db/webidbfactory_impl.h
@@ -2,24 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_FACTORY_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_FACTORY_IMPL_H_
+#ifndef CONTENT_RENDERER_INDEXED_DB_WEBIDBFACTORY_IMPL_H_
+#define CONTENT_RENDERER_INDEXED_DB_WEBIDBFACTORY_IMPL_H_
 
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "content/renderer/indexed_db/indexed_db_callbacks_impl.h"
+#include "content/renderer/indexed_db/indexed_db_database_callbacks_impl.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
 
 namespace blink {
 class WebSecurityOrigin;
 class WebString;
+}  // namespace blink
+
+namespace content {
 
 class WebIDBFactoryImpl : public blink::WebIDBFactory {
  public:
-  explicit WebIDBFactoryImpl(mojom::blink::IDBFactoryPtrInfo factory_info);
+  explicit WebIDBFactoryImpl(blink::mojom::IDBFactoryPtrInfo factory_info);
   ~WebIDBFactoryImpl() override;
 
   // See WebIDBFactory.h for documentation on these functions.
@@ -46,14 +50,14 @@
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
 
  private:
-  mojom::blink::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
-      std::unique_ptr<blink::IndexedDBCallbacksImpl> callbacks);
-  mojom::blink::IDBDatabaseCallbacksAssociatedPtrInfo GetDatabaseCallbacksProxy(
-      std::unique_ptr<blink::IndexedDBDatabaseCallbacksImpl> callbacks);
+  blink::mojom::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
+      std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
+  blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo GetDatabaseCallbacksProxy(
+      std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks);
 
-  mojom::blink::IDBFactoryPtr factory_;
+  blink::mojom::IDBFactoryPtr factory_;
 };
 
-}  // namespace blink
+}  // namespace content
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_FACTORY_IMPL_H_
+#endif  // CONTENT_RENDERER_INDEXED_DB_WEBIDBFACTORY_IMPL_H_
diff --git a/content/renderer/loader/navigation_response_override_parameters.h b/content/renderer/loader/navigation_response_override_parameters.h
index e9a9b7b..0692c5f9 100644
--- a/content/renderer/loader/navigation_response_override_parameters.h
+++ b/content/renderer/loader/navigation_response_override_parameters.h
@@ -11,7 +11,6 @@
 #include "net/url_request/redirect_info.h"
 #include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
-#include "url/gurl.h"
 
 namespace content {
 
@@ -23,7 +22,6 @@
 
   network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
   network::ResourceResponseHead response;
-  std::vector<GURL> redirects;
   std::vector<network::ResourceResponseHead> redirect_responses;
   std::vector<net::RedirectInfo> redirect_infos;
 };
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2763704..226250d 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6519,7 +6519,6 @@
   response_override->url_loader_client_endpoints =
       std::move(url_loader_client_endpoints);
   response_override->response = head;
-  response_override->redirects = request_params.redirects;
   response_override->redirect_responses = request_params.redirect_response;
   response_override->redirect_infos = request_params.redirect_infos;
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index ef96381..9cd0d75 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -88,6 +88,7 @@
 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
 #include "content/renderer/effective_connection_type_helper.h"
 #include "content/renderer/gpu/frame_swap_message_queue.h"
+#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
 #include "content/renderer/input/widget_input_handler_manager.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/low_memory_mode_controller.h"
@@ -763,6 +764,7 @@
                           base::Unretained(appcache_dispatcher())),
       GetWebMainThreadScheduler()->IPCTaskRunner());
   dom_storage_dispatcher_.reset(new DomStorageDispatcher());
+  main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher());
 
   vc_manager_.reset(new VideoCaptureImplManager());
 
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index dbd473b..e366aec 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -125,6 +125,7 @@
 class DomStorageDispatcher;
 class FrameSwapMessageQueue;
 class GpuVideoAcceleratorFactoriesImpl;
+class IndexedDBDispatcher;
 class LowMemoryModeController;
 class MidiMessageFilter;
 class P2PSocketDispatcher;
@@ -588,6 +589,7 @@
   // These objects live solely on the render thread.
   std::unique_ptr<AppCacheDispatcher> appcache_dispatcher_;
   std::unique_ptr<DomStorageDispatcher> dom_storage_dispatcher_;
+  std::unique_ptr<IndexedDBDispatcher> main_thread_indexed_db_dispatcher_;
   std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler_;
   std::unique_ptr<RendererBlinkPlatformImpl> blink_platform_impl_;
   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 310b55f..d8728b9f 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -46,6 +46,7 @@
 #include "content/renderer/dom_storage/session_web_storage_namespace_impl.h"
 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
 #include "content/renderer/image_capture/image_capture_frame_grabber.h"
+#include "content/renderer/indexed_db/webidbfactory_impl.h"
 #include "content/renderer/loader/child_url_loader_factory_bundle.h"
 #include "content/renderer/loader/code_cache_loader_impl.h"
 #include "content/renderer/loader/resource_dispatcher.h"
@@ -140,6 +141,7 @@
 using blink::WebBlobRegistry;
 using blink::WebCanvasCaptureHandler;
 using blink::WebDatabaseObserver;
+using blink::WebIDBFactory;
 using blink::WebImageCaptureFrameGrabber;
 using blink::WebMediaPlayer;
 using blink::WebMediaRecorderHandler;
@@ -562,6 +564,17 @@
 
 //------------------------------------------------------------------------------
 
+std::unique_ptr<blink::WebIDBFactory>
+RendererBlinkPlatformImpl::CreateIdbFactory() {
+  blink::mojom::IDBFactoryPtrInfo web_idb_factory_host_info;
+  GetInterfaceProvider()->GetInterface(
+      mojo::MakeRequest(&web_idb_factory_host_info));
+  return std::make_unique<WebIDBFactoryImpl>(
+      std::move(web_idb_factory_host_info));
+}
+
+//------------------------------------------------------------------------------
+
 WebString RendererBlinkPlatformImpl::FileSystemCreateOriginIdentifier(
     const blink::WebSecurityOrigin& origin) {
   return WebString::FromUTF8(
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index d12e1fc..4ec814f 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -27,6 +27,7 @@
 #include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
 #include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h"
 
 #if defined(OS_LINUX)
@@ -124,6 +125,7 @@
   viz::FrameSinkId GenerateFrameSinkId() override;
   bool IsLockedToSite() const override;
 
+  std::unique_ptr<blink::WebIDBFactory> CreateIdbFactory() override;
   blink::WebString FileSystemCreateOriginIdentifier(
       const blink::WebSecurityOrigin& origin) override;
 
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index ff2339a..97f047c 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -242,8 +242,6 @@
     response_override_->url_loader_client_endpoints =
         std::move(main_script_load_params->url_loader_client_endpoints);
     response_override_->response = main_script_load_params->response_head;
-    // TODO(nhiroki): Set |response_override_->redirects|.
-    // (https://crbug.com/715632)
     response_override_->redirect_responses =
         main_script_load_params->redirect_response_heads;
     response_override_->redirect_infos =
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 8250527..fb31996 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1703,6 +1703,10 @@
     "../renderer/gpu/layer_tree_view_unittest.cc",
     "../renderer/gpu/queue_message_swap_promise_unittest.cc",
     "../renderer/ico_image_decoder_unittest.cc",
+    "../renderer/indexed_db/mock_webidbcallbacks.cc",
+    "../renderer/indexed_db/mock_webidbcallbacks.h",
+    "../renderer/indexed_db/webidbcursor_impl_unittest.cc",
+    "../renderer/indexed_db/webidbdatabase_impl_unittest.cc",
     "../renderer/input/input_event_prediction_unittest.cc",
     "../renderer/input/main_thread_event_queue_unittest.cc",
     "../renderer/loader/resource_dispatcher_unittest.cc",
diff --git a/content/test/data/indexeddb/cursor_prefetch.js b/content/test/data/indexeddb/cursor_prefetch.js
index 772f5c0..076e6a9 100644
--- a/content/test/data/indexeddb/cursor_prefetch.js
+++ b/content/test/data/indexeddb/cursor_prefetch.js
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 // These constants should match the ones in
-// third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h to
-// make sure the test hits the right code paths.
+// content/child/indexed_db/webidbcursor_impl.h to make sure the test hits the
+// right code paths.
 var kPrefetchThreshold = 2;
 var kMinPrefetchAmount = 5;
 
diff --git a/content/test/renderer_audio_output_stream_factory_context_impl_unittest.cc b/content/test/renderer_audio_output_stream_factory_context_impl_unittest.cc
index 33e51ff..cca3c08 100644
--- a/content/test/renderer_audio_output_stream_factory_context_impl_unittest.cc
+++ b/content/test/renderer_audio_output_stream_factory_context_impl_unittest.cc
@@ -205,7 +205,9 @@
       factory_context_;
 };
 
-TEST_F(RendererAudioOutputStreamFactoryIntegrationTest, StreamIntegrationTest) {
+// It's flaky on the buildbot, http://crbug.com/761214.
+TEST_F(RendererAudioOutputStreamFactoryIntegrationTest,
+       DISABLED_StreamIntegrationTest) {
   // Sets up the factory on the IO thread and runs client code on the UI thread.
   // Send a sine wave from the client and makes sure it's received by the output
   // stream.
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc
index 4d75061..98a8fc1 100644
--- a/content/test/test_blink_web_unit_test_support.cc
+++ b/content/test/test_blink_web_unit_test_support.cc
@@ -214,6 +214,12 @@
   return &blob_registry_;
 }
 
+std::unique_ptr<blink::WebIDBFactory>
+TestBlinkWebUnitTestSupport::CreateIdbFactory() {
+  NOTREACHED() << "IndexedDB cannot be tested with in-process harnesses.";
+  return nullptr;
+}
+
 std::unique_ptr<blink::WebURLLoaderFactory>
 TestBlinkWebUnitTestSupport::CreateDefaultURLLoaderFactory() {
   return std::make_unique<WebURLLoaderFactoryWithMock>(
diff --git a/content/test/test_blink_web_unit_test_support.h b/content/test/test_blink_web_unit_test_support.h
index 44e7e95..75010ad 100644
--- a/content/test/test_blink_web_unit_test_support.h
+++ b/content/test/test_blink_web_unit_test_support.h
@@ -34,6 +34,7 @@
   ~TestBlinkWebUnitTestSupport() override;
 
   blink::WebBlobRegistry* GetBlobRegistry() override;
+  std::unique_ptr<blink::WebIDBFactory> CreateIdbFactory() override;
 
   std::unique_ptr<blink::WebURLLoaderFactory> CreateDefaultURLLoaderFactory()
       override;
diff --git a/extensions/browser/api/networking_private/networking_cast_private_delegate.h b/extensions/browser/api/networking_private/networking_cast_private_delegate.h
index d3de7d1..01dbd034 100644
--- a/extensions/browser/api/networking_private/networking_cast_private_delegate.h
+++ b/extensions/browser/api/networking_private/networking_cast_private_delegate.h
@@ -71,16 +71,6 @@
                                  const FailureCallback& failure_callback) = 0;
 
   // Verifies that data provided in |credentials| authenticates a cast device.
-  // If the device is verified as a cast device, it fetches credentials of the
-  // network identified with |network_guid| and returns the network credentials
-  // encrypted with a public key derived from |credentials|.
-  virtual void VerifyAndEncryptCredentials(
-      const std::string& network_guid,
-      std::unique_ptr<Credentials> credentials,
-      const DataCallback& encrypted_credetials_callback,
-      const FailureCallback& failure_callback) = 0;
-
-  // Verifies that data provided in |credentials| authenticates a cast device.
   // If the device is verified as a cast device, it returns |data| encrypted
   // with a public key derived from |credentials|.
   virtual void VerifyAndEncryptData(
diff --git a/extensions/browser/api/networking_private/networking_private_api.cc b/extensions/browser/api/networking_private/networking_private_api.cc
index b335eb5..2895006a 100644
--- a/extensions/browser/api/networking_private/networking_private_api.cc
+++ b/extensions/browser/api/networking_private/networking_private_api.cc
@@ -726,55 +726,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// NetworkingPrivateVerifyAndEncryptCredentialsFunction
-
-NetworkingPrivateVerifyAndEncryptCredentialsFunction::
-    ~NetworkingPrivateVerifyAndEncryptCredentialsFunction() {
-}
-
-ExtensionFunction::ResponseAction
-NetworkingPrivateVerifyAndEncryptCredentialsFunction::Run() {
-  // This method is private - as such, it should not be exposed through public
-  // networking.onc API.
-  // TODO(tbarzic): Consider exposing this via separate API.
-  // http://crbug.com/678737
-  if (!HasPrivateNetworkingAccess(extension(), source_context_type(),
-                                  source_url())) {
-    return RespondNow(Error(kPrivateOnlyError));
-  }
-  std::unique_ptr<private_api::VerifyAndEncryptCredentials::Params> params =
-      private_api::VerifyAndEncryptCredentials::Params::Create(*args_);
-  EXTENSION_FUNCTION_VALIDATE(params);
-
-  NetworkingCastPrivateDelegate* delegate =
-      ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
-  if (!delegate)
-    return RespondNow(Error("Not supported."));
-
-  delegate->VerifyAndEncryptCredentials(
-      params->network_guid, AsCastCredentials(params->properties),
-      base::Bind(&NetworkingPrivateVerifyAndEncryptCredentialsFunction::Success,
-                 this),
-      base::Bind(&NetworkingPrivateVerifyAndEncryptCredentialsFunction::Failure,
-                 this));
-  // Success() or Failure() might have been called synchronously at this point.
-  // In that case this function has already called Respond(). Return
-  // AlreadyResponded() in that case.
-  return did_respond() ? AlreadyResponded() : RespondLater();
-}
-
-void NetworkingPrivateVerifyAndEncryptCredentialsFunction::Success(
-    const std::string& result) {
-  Respond(ArgumentList(
-      private_api::VerifyAndEncryptCredentials::Results::Create(result)));
-}
-
-void NetworkingPrivateVerifyAndEncryptCredentialsFunction::Failure(
-    const std::string& error) {
-  Respond(Error(error));
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // NetworkingPrivateVerifyAndEncryptDataFunction
 
 NetworkingPrivateVerifyAndEncryptDataFunction::
diff --git a/extensions/browser/api/networking_private/networking_private_api.h b/extensions/browser/api/networking_private/networking_private_api.h
index f4c8e69..9c52180 100644
--- a/extensions/browser/api/networking_private/networking_private_api.h
+++ b/extensions/browser/api/networking_private/networking_private_api.h
@@ -368,28 +368,6 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateVerifyDestinationFunction);
 };
 
-// Implements the chrome.networkingPrivate.verifyAndEncryptCredentials method.
-class NetworkingPrivateVerifyAndEncryptCredentialsFunction
-    : public UIThreadExtensionFunction {
- public:
-  NetworkingPrivateVerifyAndEncryptCredentialsFunction() {}
-  DECLARE_EXTENSION_FUNCTION("networkingPrivate.verifyAndEncryptCredentials",
-                             NETWORKINGPRIVATE_VERIFYANDENCRYPTCREDENTIALS);
-
- protected:
-  ~NetworkingPrivateVerifyAndEncryptCredentialsFunction() override;
-
-  // ExtensionFunction:
-  ResponseAction Run() override;
-
-  void Success(const std::string& result);
-  void Failure(const std::string& error);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      NetworkingPrivateVerifyAndEncryptCredentialsFunction);
-};
-
 // Implements the chrome.networkingPrivate.verifyAndEncryptData method.
 class NetworkingPrivateVerifyAndEncryptDataFunction
     : public UIThreadExtensionFunction {
diff --git a/extensions/browser/api/networking_private/networking_private_stubs.cc b/extensions/browser/api/networking_private/networking_private_stubs.cc
index 067d503b..2e8aa08 100644
--- a/extensions/browser/api/networking_private/networking_private_stubs.cc
+++ b/extensions/browser/api/networking_private/networking_private_stubs.cc
@@ -199,17 +199,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// NetworkingPrivateVerifyAndEncryptCredentialsFunction
-
-NetworkingPrivateVerifyAndEncryptCredentialsFunction::
-    ~NetworkingPrivateVerifyAndEncryptCredentialsFunction() {}
-
-ExtensionFunction::ResponseAction
-NetworkingPrivateVerifyAndEncryptCredentialsFunction::Run() {
-  return RespondNow(Error(kStubError));
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // NetworkingPrivateVerifyAndEncryptDataFunction
 
 NetworkingPrivateVerifyAndEncryptDataFunction::
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl
index c7ca1595..77e7d59 100644
--- a/extensions/common/api/networking_private.idl
+++ b/extensions/common/api/networking_private.idl
@@ -1072,18 +1072,6 @@
     static void verifyDestination(VerificationProperties properties,
                                   BooleanCallback callback);
 
-    // Verifies that the device is a trusted device and retrieves encrypted
-    // network credentials.
-    // |properties|: Properties of the destination to use in verifying that it
-    //     is a trusted device.
-    // |networkGuid|: The GUID of the Cellular network to activate.
-    // |callback|: A callback function that receives base64-encoded encrypted
-    //     credential data to send to a trusted device.
-    [nodoc, deprecated = "Use networking.castPrivate API."]
-    static void verifyAndEncryptCredentials(VerificationProperties properties,
-                                            DOMString networkGuid,
-                                            StringCallback callback);
-
     // Verifies that the device is a trusted device and encrypts supplied
     // data with device public key.
     // |properties|: Properties of the destination to use in verifying that it
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 5fd0089..92221647 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -2492,6 +2492,11 @@
       mixins: "goma-ci"
     }
     builders {
+      name: "Chromium Android ARM 32-bit Goma RBE Staging"
+      dimensions: "os:Ubuntu-14.04"
+      mixins: "goma-ci"
+    }
+    builders {
       name: "CrWinClangGomaGCEStaging"
       dimensions: "os:Windows-10"
       mixins: "goma-ci"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index 823fb1c..fba35e4 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -3201,30 +3201,35 @@
   builders {
     name: "buildbot/chromium.goma/Chromium Linux Goma RBE Staging (clobber)"
     name: "buildbucket/luci.chromium.ci/Chromium Linux Goma RBE Staging (clobber)"
-    category: "rbe|rel|linux"
+    category: "rbe|linux|rel"
     short_name: "clb"
   }
   builders {
     name: "buildbot/chromium.goma/Chromium Linux Goma RBE Staging"
     name: "buildbucket/luci.chromium.ci/Chromium Linux Goma RBE Staging"
-    category: "rbe|rel|linux"
+    category: "rbe|linux|rel"
   }
   builders {
     name: "buildbot/chromium.goma/Chromium Linux Goma RBE Staging (dbg) (clobber)"
     name: "buildbucket/luci.chromium.ci/Chromium Linux Goma RBE Staging (dbg) (clobber)"
-    category: "rbe|debug|linux"
+    category: "rbe|linux|debug"
     short_name: "clb"
   }
   builders {
     name: "buildbot/chromium.goma/Chromium Linux Goma RBE Staging (dbg)"
     name: "buildbucket/luci.chromium.ci/Chromium Linux Goma RBE Staging (dbg)"
-    category: "rbe|debug|linux"
+    category: "rbe|linux|debug"
   }
   builders {
     name: "buildbucket/luci.chromium.ci/Chromium Mac Goma RBE Staging (clobber)"
-    category: "rbe|rel|mac"
+    category: "rbe|mac|rel"
     short_name: "clb"
   }
+  builders {
+    name: "buildbucket/luci.chromium.ci/Chromium Android ARM 32-bit Goma RBE Staging"
+    category: "rbe|rel|android"
+    short_name: "arm"
+  }
 }
 
 consoles {
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index c5d35b78..4775a8d1 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -102,6 +102,7 @@
   triggers: "Cast Android (dbg)"
   triggers: "Cast Audio Linux"
   triggers: "Cast Linux"
+  triggers: "Chromium Android ARM 32-bit Goma RBE Staging"
   triggers: "Chromium Linux Goma GCE Staging"
   triggers: "Chromium Linux Goma RBE Staging (clobber)"
   triggers: "Chromium Linux Goma RBE Staging (dbg) (clobber)"
@@ -4092,6 +4093,16 @@
 }
 
 job {
+  id: "Chromium Android ARM 32-bit Goma RBE Staging"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Chromium Android ARM 32-bit Goma RBE Staging"
+  }
+}
+
+job {
   id: "Chromium Linux Goma RBE Staging"
   acl_sets: "default"
   buildbucket: {
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py
index 0d7b280..6a9cec35 100644
--- a/ios/build/bots/scripts/test_runner.py
+++ b/ios/build/bots/scripts/test_runner.py
@@ -1033,9 +1033,6 @@
     '''Performs setup actions which must occur prior to every test launch.'''
     super(WprProxySimulatorTestRunner, self).set_up()
 
-    cert_path = "{}/TrustStore_trust.sqlite3".format(self.wpr_tools_path)
-
-    self.copy_trusted_certificate(cert_path)
     self.proxy_start()
 
   def tear_down(self):
@@ -1068,6 +1065,12 @@
       # TODO(crbug.com/812705): Implement test sharding for unit tests.
       # TODO(crbug.com/812712): Use thread pool for DeviceTestRunner as well.
 
+      # Create a simulator for these tests, and prepare it with the
+      # certificate needed for HTTPS proxying.
+      udid = self.getSimulator()
+      cert_path = "{}/TrustStore_trust.sqlite3".format(self.wpr_tools_path)
+      self.copy_trusted_certificate(cert_path)
+
       # General algorithm explanation (will clean up later)
       # For each recipe in the test folder, if there is a matching replay,
       # Run the test suite on it (similar to how SimulatorTestRunner does)
@@ -1097,7 +1100,8 @@
           recipe_cmd = [
             self.iossim_path, '-d', self.platform, '-s',
             self.version, '-t', 'AutofillAutomationTestCase', '-c',
-            '-autofillautomation={}'.format(recipePath)
+            '-autofillautomation={}'.format(recipePath),
+            '-u', udid,
           ]
           for env_var in self.env_vars:
             recipe_cmd.extend(['-e', env_var])
@@ -1171,6 +1175,8 @@
           print 'No matching replay file for recipe {}'.format(
               recipePath)
 
+      self.deleteSimulator(udid)
+
     # iossim can return 5 if it exits noncleanly even if all tests passed.
     # Therefore we cannot rely on process exit code to determine success.
 
diff --git a/ios/build/bots/scripts/test_runner_test.py b/ios/build/bots/scripts/test_runner_test.py
index 9619e20e..7cb988a 100755
--- a/ios/build/bots/scripts/test_runner_test.py
+++ b/ios/build/bots/scripts/test_runner_test.py
@@ -363,6 +363,9 @@
               lambda _: 'fake-bundle-id')
     self.mock(os.path, 'abspath', lambda path: '/abs/path/to/%s' % path)
     self.mock(os.path, 'exists', lambda _: True)
+    self.mock(test_runner.SimulatorTestRunner, 'getSimulator', lambda _: 'fake-id')
+    self.mock(test_runner.SimulatorTestRunner, 'deleteSimulator', lambda a, b: True)
+    self.mock(test_runner.WprProxySimulatorTestRunner, 'copy_trusted_certificate', lambda a, b: True)
 
   def test_replay_path_not_found(self):
     """Ensures ReplayPathNotFoundError is raised."""
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index f2f57a3..f273e60 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -1963,6 +1963,12 @@
     if (node->is_folder()) {
       [self handleSelectFolderForNavigation:node];
     } else {
+      if (self.sharedState.currentlyShowingSearchResults) {
+        // Set the searchController active property to NO or the SearchBar will
+        // cause the navigation controller to linger for a second  when
+        // dismissing.
+        self.searchController.active = NO;
+      }
       // Open URL. Pass this to the delegate.
       [self handleSelectUrlForNavigation:node->url()];
     }
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn
index 6102956..bf6aebd 100644
--- a/services/tracing/BUILD.gn
+++ b/services/tracing/BUILD.gn
@@ -81,7 +81,10 @@
   ]
 
   if (is_mac || is_linux || is_android) {
-    sources += [ "public/cpp/perfetto/trace_event_data_source_unittest.cc" ]
+    sources += [
+      "public/cpp/perfetto/trace_event_data_source_unittest.cc",
+      "public/cpp/perfetto/traced_value_proto_writer_unittest.cc",
+    ]
   }
 
   if (!is_android) {
diff --git a/services/tracing/DEPS b/services/tracing/DEPS
index ebe3550..265033b 100644
--- a/services/tracing/DEPS
+++ b/services/tracing/DEPS
@@ -2,4 +2,5 @@
   "+services/service_manager/public",
   "+third_party/perfetto/include",
   "+third_party/perfetto/protos/perfetto",
+  "+third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h",
 ]
diff --git a/services/tracing/perfetto/json_trace_exporter.cc b/services/tracing/perfetto/json_trace_exporter.cc
index df3f0103..94296ea4 100644
--- a/services/tracing/perfetto/json_trace_exporter.cc
+++ b/services/tracing/perfetto/json_trace_exporter.cc
@@ -7,12 +7,11 @@
 #include <unordered_map>
 #include <utility>
 
+#include "base/format_macros.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/json/string_escape.h"
 #include "base/logging.h"
-
-#include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
 #include "services/tracing/public/mojom/perfetto_service.mojom.h"
@@ -23,7 +22,61 @@
 
 using TraceEvent = base::trace_event::TraceEvent;
 
+namespace tracing {
+
 namespace {
+
+void AppendProtoArrayAsJSON(std::string* out,
+                            const perfetto::protos::ChromeTracedValue& array);
+
+void AppendProtoValueAsJSON(std::string* out,
+                            const perfetto::protos::ChromeTracedValue& value) {
+  base::trace_event::TraceEvent::TraceValue json_value;
+  if (value.has_int_value()) {
+    json_value.as_int = value.int_value();
+    TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out);
+  } else if (value.has_double_value()) {
+    json_value.as_double = value.double_value();
+    TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out);
+  } else if (value.has_bool_value()) {
+    json_value.as_bool = value.bool_value();
+    TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out);
+  } else if (value.has_string_value()) {
+    json_value.as_string = value.string_value().c_str();
+    TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out);
+  } else if (value.has_nested_type()) {
+    if (value.nested_type() == perfetto::protos::ChromeTracedValue::ARRAY) {
+      AppendProtoArrayAsJSON(out, value);
+      return;
+    } else if (value.nested_type() ==
+               perfetto::protos::ChromeTracedValue::DICT) {
+      AppendProtoDictAsJSON(out, value);
+    } else {
+      NOTREACHED();
+    }
+  } else {
+    NOTREACHED();
+  }
+}
+
+void AppendProtoArrayAsJSON(std::string* out,
+                            const perfetto::protos::ChromeTracedValue& array) {
+  out->append("[");
+
+  bool is_first_entry = true;
+  for (auto& value : array.array_values()) {
+    if (!is_first_entry) {
+      out->append(",");
+    } else {
+      is_first_entry = false;
+    }
+
+    AppendProtoValueAsJSON(out, value);
+  }
+
+  out->append("]");
+}
+
 const char* GetStringFromStringTable(
     const std::unordered_map<int, std::string>& string_table,
     int index) {
@@ -193,6 +246,13 @@
       *out += arg.json_value();
       continue;
     }
+
+    if (arg.has_traced_value()) {
+      AppendProtoDictAsJSON(out, arg.traced_value());
+      continue;
+    }
+
+    NOTREACHED();
   }
 
   *out += "}}";
@@ -200,7 +260,24 @@
 
 }  // namespace
 
-namespace tracing {
+void AppendProtoDictAsJSON(std::string* out,
+                           const perfetto::protos::ChromeTracedValue& dict) {
+  out->append("{");
+
+  DCHECK_EQ(dict.dict_keys_size(), dict.dict_values_size());
+  for (int i = 0; i < dict.dict_keys_size(); ++i) {
+    if (i != 0) {
+      out->append(",");
+    }
+
+    base::EscapeJSONString(dict.dict_keys(i), true, out);
+    out->append(":");
+
+    AppendProtoValueAsJSON(out, dict.dict_values(i));
+  }
+
+  out->append("}");
+}
 
 JSONTraceExporter::JSONTraceExporter(const std::string& config,
                                      perfetto::TracingService* service)
diff --git a/services/tracing/perfetto/json_trace_exporter.h b/services/tracing/perfetto/json_trace_exporter.h
index be55410..2657ed8 100644
--- a/services/tracing/perfetto/json_trace_exporter.h
+++ b/services/tracing/perfetto/json_trace_exporter.h
@@ -12,12 +12,22 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/values.h"
-
 #include "third_party/perfetto/include/perfetto/tracing/core/consumer.h"
 #include "third_party/perfetto/include/perfetto/tracing/core/tracing_service.h"
 
+namespace perfetto {
+namespace protos {
+class ChromeTracedValue;
+}  // namespace protos
+}  // namespace perfetto
+
 namespace tracing {
 
+// Serializes the supplied proto into JSON, using the same
+// format as TracedValue::AppendAsTraceFormat.
+void AppendProtoDictAsJSON(std::string* out,
+                           const perfetto::protos::ChromeTracedValue& dict);
+
 // This is a Perfetto consumer which will enable Perfetto tracing
 // and subscribe to ChromeTraceEvent data sources. Any received
 // protos will be converted to the legacy JSON Chrome Tracing
diff --git a/services/tracing/perfetto/json_trace_exporter_unittest.cc b/services/tracing/perfetto/json_trace_exporter_unittest.cc
index f46987d..9499c6e 100644
--- a/services/tracing/perfetto/json_trace_exporter_unittest.cc
+++ b/services/tracing/perfetto/json_trace_exporter_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/test/trace_event_analyzer.h"
 #include "base/trace_event/trace_event.h"
+#include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #include "services/tracing/public/mojom/perfetto_service.mojom.h"
@@ -579,4 +580,125 @@
   EXPECT_EQ("conv_value2", trace_event->GetKnownArgAsString("foo2"));
 }
 
+TEST_F(JSONTraceExporterTest, TestEventWithTracedValueArg) {
+  CreateJSONTraceExporter("foo");
+  service()->WaitForTracingEnabled();
+  StopAndFlush();
+
+  perfetto::protos::TracePacket trace_packet_proto;
+  auto* new_trace_event =
+      trace_packet_proto.mutable_chrome_events()->add_trace_events();
+  SetTestPacketBasicData(new_trace_event);
+
+  auto* new_arg = new_trace_event->add_args();
+  new_arg->set_name("foo1");
+  auto* traced_value = new_arg->mutable_traced_value();
+  traced_value->add_dict_keys("bool");
+  traced_value->add_dict_values()->set_bool_value(true);
+
+  FinalizePacket(trace_packet_proto);
+
+  service()->WaitForTracingDisabled();
+  auto* trace_event = ValidateAndGetBasicTestPacket();
+
+  auto arg_value = trace_event->GetKnownArgAsValue("foo1");
+  EXPECT_EQ(true, arg_value->FindKey("bool")->GetBool());
+}
+
+TEST_F(JSONTraceExporterTest, TracedValueFlatDictionary) {
+  perfetto::protos::ChromeTracedValue traced_value;
+
+  {
+    traced_value.add_dict_keys("bool");
+    traced_value.add_dict_values()->set_bool_value(true);
+  }
+
+  {
+    traced_value.add_dict_keys("double");
+    traced_value.add_dict_values()->set_double_value(8.0);
+  }
+
+  {
+    traced_value.add_dict_keys("int");
+    traced_value.add_dict_values()->set_int_value(2014);
+  }
+
+  {
+    traced_value.add_dict_keys("string");
+    traced_value.add_dict_values()->set_string_value("bar");
+  }
+
+  std::string json;
+  AppendProtoDictAsJSON(&json, traced_value);
+
+  EXPECT_EQ("{\"bool\":true,\"double\":8.0,\"int\":2014,\"string\":\"bar\"}",
+            json);
+}
+
+TEST_F(JSONTraceExporterTest, TracedValueHierarchy) {
+  perfetto::protos::ChromeTracedValue traced_value;
+
+  {
+    traced_value.add_dict_keys("a1");
+    auto* a1_array = traced_value.add_dict_values();
+    a1_array->set_nested_type(perfetto::protos::ChromeTracedValue::ARRAY);
+
+    a1_array->add_array_values()->set_int_value(1);
+    a1_array->add_array_values()->set_bool_value(true);
+
+    auto* sub_dict = a1_array->add_array_values();
+    sub_dict->set_nested_type(perfetto::protos::ChromeTracedValue::DICT);
+    sub_dict->add_dict_keys("i2");
+    sub_dict->add_dict_values()->set_int_value(3);
+  }
+
+  {
+    traced_value.add_dict_keys("b0");
+    traced_value.add_dict_values()->set_bool_value(true);
+  }
+
+  {
+    traced_value.add_dict_keys("d0");
+    traced_value.add_dict_values()->set_double_value(6.0);
+  }
+
+  {
+    traced_value.add_dict_keys("a1");
+    auto* dict1_subdict = traced_value.add_dict_values();
+    dict1_subdict->set_nested_type(perfetto::protos::ChromeTracedValue::DICT);
+
+    dict1_subdict->add_dict_keys("dict2");
+    auto* dict2_sub_sub_dict = dict1_subdict->add_dict_values();
+    dict2_sub_sub_dict->set_nested_type(
+        perfetto::protos::ChromeTracedValue::DICT);
+
+    dict2_sub_sub_dict->add_dict_keys("b2");
+    dict2_sub_sub_dict->add_dict_values()->set_bool_value(true);
+
+    dict1_subdict->add_dict_keys("i1");
+    dict1_subdict->add_dict_values()->set_int_value(2014);
+
+    dict1_subdict->add_dict_keys("s1");
+    dict1_subdict->add_dict_values()->set_string_value("foo");
+  }
+
+  {
+    traced_value.add_dict_keys("i0");
+    traced_value.add_dict_values()->set_int_value(2014);
+  }
+
+  {
+    traced_value.add_dict_keys("s0");
+    traced_value.add_dict_values()->set_string_value("foo");
+  }
+
+  std::string json;
+  AppendProtoDictAsJSON(&json, traced_value);
+
+  EXPECT_EQ(
+      "{\"a1\":[1,true,{\"i2\":3}],\"b0\":true,\"d0\":6.0,\"a1\":{\"dict2\":{"
+      "\"b2\":true},\"i1\":2014,\"s1\":\"foo\"},\"i0\":2014,\"s0\":\"foo\"}",
+      json);
+}
+
 }  // namespace tracing
diff --git a/services/tracing/public/cpp/BUILD.gn b/services/tracing/public/cpp/BUILD.gn
index 950482a..92352825 100644
--- a/services/tracing/public/cpp/BUILD.gn
+++ b/services/tracing/public/cpp/BUILD.gn
@@ -26,6 +26,8 @@
 
   if (is_mac || is_linux || is_android || is_win) {
     sources += [
+      "perfetto/heap_scattered_stream_delegate.cc",
+      "perfetto/heap_scattered_stream_delegate.h",
       "perfetto/producer_client.cc",
       "perfetto/producer_client.h",
       "perfetto/shared_memory.cc",
@@ -34,9 +36,12 @@
       "perfetto/task_runner.h",
       "perfetto/trace_event_data_source.cc",
       "perfetto/trace_event_data_source.h",
+      "perfetto/traced_value_proto_writer.cc",
+      "perfetto/traced_value_proto_writer.h",
     ]
 
     deps = [
+      "//third_party/perfetto/include/perfetto/protozero:protozero",
       "//third_party/perfetto/protos/perfetto/trace/chrome:minimal_complete_lite",
     ]
 
diff --git a/services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.cc b/services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.cc
new file mode 100644
index 0000000..92e2cc0
--- /dev/null
+++ b/services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.cc
@@ -0,0 +1,83 @@
+// 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 "services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/logging.h"
+
+namespace tracing {
+
+namespace {
+
+// TODO(oysteine): Tune these values.
+static const size_t kDefaultChunkSizeBytes = 128;
+static const size_t kMaximumChunkSizeBytes = 128 * 1024;
+
+}  // namespace
+
+HeapScatteredStreamWriterDelegate::Chunk::Chunk(size_t size)
+    : buffer_(std::unique_ptr<uint8_t[]>(new uint8_t[size])),
+      size_(size),
+      unused_bytes_(size) {
+  DCHECK(size);
+}
+
+HeapScatteredStreamWriterDelegate::Chunk::Chunk(Chunk&& chunk)
+    : buffer_(std::move(chunk.buffer_)),
+      size_(std::move(chunk.size_)),
+      unused_bytes_(std::move(chunk.unused_bytes_)) {}
+
+HeapScatteredStreamWriterDelegate::Chunk::~Chunk() = default;
+
+protozero::ContiguousMemoryRange
+HeapScatteredStreamWriterDelegate::Chunk::GetTotalRange() const {
+  protozero::ContiguousMemoryRange range = {buffer_.get(),
+                                            buffer_.get() + size_};
+  return range;
+}
+
+protozero::ContiguousMemoryRange
+HeapScatteredStreamWriterDelegate::Chunk::GetUsedRange() const {
+  protozero::ContiguousMemoryRange range = {
+      buffer_.get(), buffer_.get() + size_ - unused_bytes_};
+  return range;
+}
+
+HeapScatteredStreamWriterDelegate::HeapScatteredStreamWriterDelegate(
+    size_t initial_size_hint) {
+  next_chunk_size_ =
+      initial_size_hint ? initial_size_hint : kDefaultChunkSizeBytes;
+}
+
+HeapScatteredStreamWriterDelegate::~HeapScatteredStreamWriterDelegate() =
+    default;
+
+size_t HeapScatteredStreamWriterDelegate::GetTotalSize() {
+  size_t total_size = 0;
+  for (auto& chunk : chunks_) {
+    total_size += chunk.size();
+  }
+  return total_size;
+}
+
+void HeapScatteredStreamWriterDelegate::AdjustUsedSizeOfCurrentChunk() {
+  if (!chunks_.empty()) {
+    DCHECK(writer_);
+    chunks_.back().set_unused_bytes(writer_->bytes_available());
+  }
+}
+
+protozero::ContiguousMemoryRange
+HeapScatteredStreamWriterDelegate::GetNewBuffer() {
+  AdjustUsedSizeOfCurrentChunk();
+
+  chunks_.emplace_back(next_chunk_size_);
+  next_chunk_size_ = std::min(kMaximumChunkSizeBytes, next_chunk_size_ * 2);
+  return chunks_.back().GetTotalRange();
+}
+
+}  // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h b/services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h
new file mode 100644
index 0000000..0d1866e
--- /dev/null
+++ b/services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h
@@ -0,0 +1,68 @@
+// 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 SERVICES_TRACING_PUBLIC_CPP_PERFETTO_HEAP_SCATTERED_STREAM_DELEGATE_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_HEAP_SCATTERED_STREAM_DELEGATE_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h"
+
+namespace tracing {
+
+// This is used to supply Perfetto's protozero library with
+// a temporary heap-backed storage, which can then later be memcpy'd
+// into the shared memory buffer.
+class COMPONENT_EXPORT(TRACING_CPP) HeapScatteredStreamWriterDelegate
+    : public protozero::ScatteredStreamWriter::Delegate {
+ public:
+  class Chunk {
+   public:
+    explicit Chunk(size_t size);
+    Chunk(Chunk&& chunk);
+    ~Chunk();
+
+    protozero::ContiguousMemoryRange GetTotalRange() const;
+    protozero::ContiguousMemoryRange GetUsedRange() const;
+
+    uint8_t* start() const { return buffer_.get(); }
+    size_t size() const { return size_; }
+    size_t unused_bytes() const { return unused_bytes_; }
+    void set_unused_bytes(size_t unused_bytes) { unused_bytes_ = unused_bytes; }
+
+   private:
+    std::unique_ptr<uint8_t[]> buffer_;
+    const size_t size_;
+    size_t unused_bytes_;
+  };
+
+  explicit HeapScatteredStreamWriterDelegate(size_t initial_size_hint);
+  ~HeapScatteredStreamWriterDelegate() override;
+
+  const std::vector<Chunk>& chunks() const { return chunks_; }
+
+  void set_writer(protozero::ScatteredStreamWriter* writer) {
+    writer_ = writer;
+  }
+
+  size_t GetTotalSize();
+  void AdjustUsedSizeOfCurrentChunk();
+
+  // protozero::ScatteredStreamWriter::Delegate implementation.
+  protozero::ContiguousMemoryRange GetNewBuffer() override;
+
+ private:
+  std::vector<Chunk> chunks_;
+  size_t next_chunk_size_;
+  protozero::ScatteredStreamWriter* writer_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(HeapScatteredStreamWriterDelegate);
+};
+
+}  // namespace tracing
+
+#endif  // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_HEAP_SCATTERED_STREAM_DELEGATE_H_
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index f7bec193..88d0a78a 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -12,6 +12,7 @@
 #include "base/no_destructor.h"
 #include "base/process/process_handle.h"
 #include "base/trace_event/trace_event.h"
+#include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
 #include "services/tracing/public/mojom/constants.mojom.h"
 #include "third_party/perfetto/include/perfetto/tracing/core/shared_memory_arbiter.h"
 #include "third_party/perfetto/include/perfetto/tracing/core/trace_writer.h"
@@ -153,13 +154,18 @@
   }
 
   void AddConvertableToTraceFormat(
-      const base::trace_event::ConvertableToTraceFormat* value,
+      base::trace_event::ConvertableToTraceFormat* value,
       perfetto::protos::pbzero::ChromeTraceEvent_Arg* arg) {
+    PerfettoProtoAppender proto_appender(arg);
+    if (value->AppendToProto(&proto_appender)) {
+      return;
+    }
+
     std::string json = value->ToString();
     arg->set_json_value(json.c_str());
   }
 
-  void AddTraceEvent(const TraceEvent& trace_event) {
+  void AddTraceEvent(TraceEvent* trace_event) {
     // TODO(oysteine): Adding trace events to Perfetto will
     // stall in some situations, specifically when we overflow
     // the buffer and need to make a sync call to flush it, and we're
@@ -170,7 +176,7 @@
     // TODO(oysteine): Temporary workaround for a specific trace event
     // which is added while a scheduler lock is held, and will deadlock
     // if Perfetto does a PostTask to commit a finished chunk.
-    if (strcmp(trace_event.name(), "RealTimeDomain::DelayTillNextTask") == 0) {
+    if (strcmp(trace_event->name(), "RealTimeDomain::DelayTillNextTask") == 0) {
       return;
     }
 
@@ -186,17 +192,18 @@
     // If the TRACE_EVENT_FLAG_COPY flag is set, the char* pointers aren't
     // necessarily valid after the TRACE_EVENT* call, and so we need to store
     // the string every time.
-    bool string_table_enabled = !(trace_event.flags() & TRACE_EVENT_FLAG_COPY);
+    bool string_table_enabled = !(trace_event->flags() & TRACE_EVENT_FLAG_COPY);
     if (string_table_enabled) {
-      name_index = GetStringTableIndexForString(trace_event.name());
-      category_name_index = GetStringTableIndexForString(
-          TraceLog::GetCategoryGroupName(trace_event.category_group_enabled()));
+      name_index = GetStringTableIndexForString(trace_event->name());
+      category_name_index =
+          GetStringTableIndexForString(TraceLog::GetCategoryGroupName(
+              trace_event->category_group_enabled()));
 
       for (int i = 0;
-           i < base::trace_event::kTraceMaxNumArgs && trace_event.arg_name(i);
+           i < base::trace_event::kTraceMaxNumArgs && trace_event->arg_name(i);
            ++i) {
         arg_name_indices[i] =
-            GetStringTableIndexForString(trace_event.arg_name(i));
+            GetStringTableIndexForString(trace_event->arg_name(i));
       }
     }
 
@@ -205,58 +212,58 @@
     if (name_index) {
       new_trace_event->set_name_index(name_index);
     } else {
-      new_trace_event->set_name(trace_event.name());
+      new_trace_event->set_name(trace_event->name());
     }
 
     if (category_name_index) {
       new_trace_event->set_category_group_name_index(category_name_index);
     } else {
-      new_trace_event->set_category_group_name(
-          TraceLog::GetCategoryGroupName(trace_event.category_group_enabled()));
+      new_trace_event->set_category_group_name(TraceLog::GetCategoryGroupName(
+          trace_event->category_group_enabled()));
     }
 
     new_trace_event->set_timestamp(
-        trace_event.timestamp().since_origin().InMicroseconds());
+        trace_event->timestamp().since_origin().InMicroseconds());
 
-    uint32_t flags = trace_event.flags();
+    uint32_t flags = trace_event->flags();
     new_trace_event->set_flags(flags);
 
     int process_id;
     int thread_id;
     if ((flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) &&
-        trace_event.thread_id() != base::kNullProcessId) {
-      process_id = trace_event.thread_id();
+        trace_event->thread_id() != base::kNullProcessId) {
+      process_id = trace_event->thread_id();
       thread_id = -1;
     } else {
       process_id = TraceLog::GetInstance()->process_id();
-      thread_id = trace_event.thread_id();
+      thread_id = trace_event->thread_id();
     }
 
     new_trace_event->set_process_id(process_id);
     new_trace_event->set_thread_id(thread_id);
 
-    char phase = trace_event.phase();
+    char phase = trace_event->phase();
     new_trace_event->set_phase(phase);
 
     for (int i = 0;
-         i < base::trace_event::kTraceMaxNumArgs && trace_event.arg_name(i);
+         i < base::trace_event::kTraceMaxNumArgs && trace_event->arg_name(i);
          ++i) {
-      auto type = trace_event.arg_type(i);
+      auto type = trace_event->arg_type(i);
       auto* new_arg = new_trace_event->add_args();
 
       if (arg_name_indices[i]) {
         new_arg->set_name_index(arg_name_indices[i]);
       } else {
-        new_arg->set_name(trace_event.arg_name(i));
+        new_arg->set_name(trace_event->arg_name(i));
       }
 
       if (type == TRACE_VALUE_TYPE_CONVERTABLE) {
-        AddConvertableToTraceFormat(trace_event.arg_convertible_value(i),
+        AddConvertableToTraceFormat(trace_event->arg_convertible_value(i),
                                     new_arg);
         continue;
       }
 
-      auto& value = trace_event.arg_value(i);
+      auto& value = trace_event->arg_value(i);
       switch (type) {
         case TRACE_VALUE_TYPE_BOOL:
           new_arg->set_bool_value(value.as_bool);
@@ -285,7 +292,7 @@
     }
 
     if (phase == TRACE_EVENT_PHASE_COMPLETE) {
-      int64_t duration = trace_event.duration().InMicroseconds();
+      int64_t duration = trace_event->duration().InMicroseconds();
       if (duration != -1) {
         new_trace_event->set_duration(duration);
       } else {
@@ -295,33 +302,33 @@
         new_trace_event->set_duration(0);
       }
 
-      if (!trace_event.thread_timestamp().is_null()) {
+      if (!trace_event->thread_timestamp().is_null()) {
         int64_t thread_duration =
-            trace_event.thread_duration().InMicroseconds();
+            trace_event->thread_duration().InMicroseconds();
         if (thread_duration != -1) {
           new_trace_event->set_thread_duration(thread_duration);
         }
       }
     }
 
-    if (!trace_event.thread_timestamp().is_null()) {
+    if (!trace_event->thread_timestamp().is_null()) {
       int64_t thread_time_int64 =
-          trace_event.thread_timestamp().since_origin().InMicroseconds();
+          trace_event->thread_timestamp().since_origin().InMicroseconds();
       new_trace_event->set_thread_timestamp(thread_time_int64);
     }
 
-    if (trace_event.scope() != trace_event_internal::kGlobalScope) {
-      new_trace_event->set_scope(trace_event.scope());
+    if (trace_event->scope() != trace_event_internal::kGlobalScope) {
+      new_trace_event->set_scope(trace_event->scope());
     }
 
     if (flags & (TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_HAS_LOCAL_ID |
                  TRACE_EVENT_FLAG_HAS_GLOBAL_ID)) {
-      new_trace_event->set_id(trace_event.id());
+      new_trace_event->set_id(trace_event->id());
     }
 
     if ((flags & TRACE_EVENT_FLAG_FLOW_OUT) ||
         (flags & TRACE_EVENT_FLAG_FLOW_IN)) {
-      new_trace_event->set_bind_id(trace_event.bind_id());
+      new_trace_event->set_bind_id(trace_event->bind_id());
     }
   }
 
@@ -362,7 +369,9 @@
 }
 
 TraceEventDataSource::TraceEventDataSource()
-    : DataSourceBase(mojom::kTraceEventDataSourceName) {}
+    : DataSourceBase(mojom::kTraceEventDataSourceName) {
+  RegisterTracedValueProtoWriter();
+}
 
 TraceEventDataSource::~TraceEventDataSource() = default;
 
@@ -456,7 +465,7 @@
 }
 
 // static
-void TraceEventDataSource::OnAddTraceEvent(const TraceEvent& trace_event) {
+void TraceEventDataSource::OnAddTraceEvent(TraceEvent* trace_event) {
   auto* thread_local_event_sink =
       static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get());
 
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
index efefbd8..2ea58964 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.h
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -84,7 +84,7 @@
   ThreadLocalEventSink* CreateThreadLocalEventSink();
 
   // Callback from TraceLog, can be called from any thread.
-  static void OnAddTraceEvent(const base::trace_event::TraceEvent& trace_event);
+  static void OnAddTraceEvent(base::trace_event::TraceEvent* trace_event);
 
   base::Lock lock_;
   uint32_t target_buffer_ = 0;
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
index 77b678f9..fb034b9 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -19,6 +19,7 @@
 #include "services/tracing/public/mojom/perfetto_service.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h"
+#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h"
 #include "third_party/perfetto/include/perfetto/tracing/core/trace_writer.h"
 #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
 #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
new file mode 100644
index 0000000..a279a641
--- /dev/null
+++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
@@ -0,0 +1,265 @@
+// 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 "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
+
+#include <stack>
+
+#include "base/hash.h"
+#include "base/json/string_escape.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "base/values.h"
+#include "services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h"
+#include "third_party/perfetto/include/perfetto/protozero/message_handle.h"
+#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h"
+
+using TracedValue = base::trace_event::TracedValue;
+using ChromeTracedValue = perfetto::protos::pbzero::ChromeTracedValue;
+using TracedValueHandle =
+    protozero::MessageHandle<perfetto::protos::pbzero::ChromeTracedValue>;
+using TraceEvent = base::trace_event::TraceEvent;
+
+namespace tracing {
+
+PerfettoProtoAppender::PerfettoProtoAppender(
+    perfetto::protos::pbzero::ChromeTraceEvent_Arg* proto)
+    : proto_(proto) {}
+
+PerfettoProtoAppender::~PerfettoProtoAppender() = default;
+
+void PerfettoProtoAppender::AddBuffer(uint8_t* begin, uint8_t* end) {
+  ranges_.emplace_back();
+  ranges_.back().begin = begin;
+  ranges_.back().end = end;
+}
+
+size_t PerfettoProtoAppender::Finalize(uint32_t field_id) {
+  return proto_->AppendScatteredBytes(field_id, ranges_.data(), ranges_.size());
+}
+
+namespace {
+
+class ProtoWriter final : public TracedValue::Writer {
+ public:
+  explicit ProtoWriter(size_t capacity)
+      : delegate_(capacity), stream_(&delegate_) {
+    proto_.Reset(&stream_);
+    delegate_.set_writer(&stream_);
+    node_stack_.emplace(TracedValueHandle(&proto_));
+    proto_.set_nested_type(perfetto::protos::pbzero::ChromeTracedValue::DICT);
+  }
+
+  ~ProtoWriter() override {
+    // At this point there should just be the root dict still open if any,
+    // which can happen if the TracedValue is created but never
+    // used (i.e. proto never gets finalized).
+    if (!node_stack_.empty()) {
+      node_stack_.pop();
+    }
+
+    DCHECK(node_stack_.empty());
+  }
+
+  bool IsPickleWriter() const override { return false; }
+  bool IsProtoWriter() const override { return true; }
+
+  void SetInteger(const char* name, int value) override {
+    AddDictEntry(name)->set_int_value(value);
+  }
+
+  void SetIntegerWithCopiedName(base::StringPiece name, int value) override {
+    AddDictEntry(name)->set_int_value(value);
+  }
+
+  void SetDouble(const char* name, double value) override {
+    AddDictEntry(name)->set_double_value(value);
+  }
+
+  void SetDoubleWithCopiedName(base::StringPiece name, double value) override {
+    AddDictEntry(name)->set_double_value(value);
+  }
+
+  void SetBoolean(const char* name, bool value) override {
+    AddDictEntry(name)->set_bool_value(value);
+  }
+
+  void SetBooleanWithCopiedName(base::StringPiece name, bool value) override {
+    AddDictEntry(name)->set_bool_value(value);
+  }
+
+  void SetString(const char* name, base::StringPiece value) override {
+    AddDictEntry(name)->set_string_value(value.data(), value.size());
+  }
+
+  void SetStringWithCopiedName(base::StringPiece name,
+                               base::StringPiece value) override {
+    AddDictEntry(name)->set_string_value(value.data(), value.size());
+  }
+
+  void SetValue(const char* name, Writer* value) override {
+    DCHECK(value->IsProtoWriter());
+    ProtoWriter* child_proto_writer = static_cast<ProtoWriter*>(value);
+
+    uint32_t full_child_size = child_proto_writer->Finalize();
+
+    DCHECK(!node_stack_.empty());
+    node_stack_.top()->add_dict_keys(name);
+
+    std::vector<protozero::ContiguousMemoryRange> ranges;
+    for (auto& chunk : child_proto_writer->delegate_.chunks()) {
+      ranges.emplace_back(chunk.GetUsedRange());
+    }
+
+    size_t appended_size = node_stack_.top()->AppendScatteredBytes(
+        perfetto::protos::pbzero::ChromeTracedValue::kDictValuesFieldNumber,
+        ranges.data(), ranges.size());
+    DCHECK_EQ(full_child_size, appended_size);
+  }
+
+  void SetValueWithCopiedName(base::StringPiece name, Writer* value) override {
+    SetValue(name.as_string().c_str(), value);
+  }
+
+  void BeginArray() override {
+    node_stack_.emplace(TracedValueHandle(AddArrayEntry()));
+    node_stack_.top()->set_nested_type(
+        perfetto::protos::pbzero::ChromeTracedValue::ARRAY);
+  }
+
+  void BeginDictionary() override {
+    node_stack_.emplace(TracedValueHandle(AddArrayEntry()));
+    node_stack_.top()->set_nested_type(
+        perfetto::protos::pbzero::ChromeTracedValue::DICT);
+  }
+
+  void BeginDictionary(const char* name) override {
+    node_stack_.emplace(TracedValueHandle(AddDictEntry(name)));
+    node_stack_.top()->set_nested_type(
+        perfetto::protos::pbzero::ChromeTracedValue::DICT);
+  }
+
+  void BeginDictionaryWithCopiedName(base::StringPiece name) override {
+    node_stack_.emplace(TracedValueHandle(AddDictEntry(name)));
+    node_stack_.top()->set_nested_type(
+        perfetto::protos::pbzero::ChromeTracedValue::DICT);
+  }
+
+  void BeginArray(const char* name) override {
+    node_stack_.emplace(TracedValueHandle(AddDictEntry(name)));
+    node_stack_.top()->set_nested_type(
+        perfetto::protos::pbzero::ChromeTracedValue::ARRAY);
+  }
+
+  void BeginArrayWithCopiedName(base::StringPiece name) override {
+    node_stack_.emplace(TracedValueHandle(AddDictEntry(name)));
+    node_stack_.top()->set_nested_type(
+        perfetto::protos::pbzero::ChromeTracedValue::ARRAY);
+  }
+
+  void EndDictionary() override {
+    DCHECK_GE(node_stack_.size(), 2u);
+    node_stack_.pop();
+  }
+
+  void EndArray() override {
+    DCHECK_GE(node_stack_.size(), 2u);
+    node_stack_.pop();
+  }
+
+  void AppendInteger(int value) override {
+    AddArrayEntry()->set_int_value(value);
+  }
+
+  void AppendDouble(double value) override {
+    AddArrayEntry()->set_double_value(value);
+  }
+
+  void AppendBoolean(bool value) override {
+    AddArrayEntry()->set_bool_value(value);
+  }
+
+  void AppendString(base::StringPiece value) override {
+    AddArrayEntry()->set_string_value(value.data(), value.size());
+  }
+
+  uint32_t Finalize() {
+    if (!node_stack_.empty()) {
+      node_stack_.pop();
+    }
+
+    DCHECK(node_stack_.empty());
+    uint32_t full_size = proto_.Finalize();
+    delegate_.AdjustUsedSizeOfCurrentChunk();
+
+    return full_size;
+  }
+
+  void AppendAsTraceFormat(std::string* out) const override { NOTREACHED(); }
+
+  bool AppendToProto(
+      base::trace_event::TracedValue::ProtoAppender* appender) override {
+    uint32_t full_size = Finalize();
+
+    for (auto& chunk : delegate_.chunks()) {
+      appender->AddBuffer(chunk.start(),
+                          chunk.start() + chunk.size() - chunk.unused_bytes());
+    }
+
+    size_t appended_size =
+        appender->Finalize(perfetto::protos::pbzero::ChromeTraceEvent_Arg::
+                               kTracedValueFieldNumber);
+    DCHECK_EQ(full_size, appended_size);
+    return true;
+  }
+
+  void EstimateTraceMemoryOverhead(
+      base::trace_event::TraceEventMemoryOverhead* overhead) override {
+    overhead->Add(base::trace_event::TraceEventMemoryOverhead::kTracedValue,
+                  /* allocated size */
+                  delegate_.GetTotalSize(),
+                  /* resident size */
+                  delegate_.GetTotalSize());
+  }
+
+  std::unique_ptr<base::Value> ToBaseValue() const override {
+    base::Value root(base::Value::Type::DICTIONARY);
+    return base::Value::ToUniquePtrValue(std::move(root));
+  }
+
+ private:
+  ChromeTracedValue* AddDictEntry(const char* name) {
+    DCHECK(!node_stack_.empty() && !node_stack_.top()->is_finalized());
+    node_stack_.top()->add_dict_keys(name);
+    return node_stack_.top()->add_dict_values();
+  }
+
+  ChromeTracedValue* AddDictEntry(base::StringPiece name) {
+    DCHECK(!node_stack_.empty() && !node_stack_.top()->is_finalized());
+    node_stack_.top()->add_dict_keys(name.data(), name.length());
+    return node_stack_.top()->add_dict_values();
+  }
+
+  ChromeTracedValue* AddArrayEntry() {
+    DCHECK(!node_stack_.empty() && !node_stack_.top()->is_finalized());
+    return node_stack_.top()->add_array_values();
+  }
+
+  std::stack<TracedValueHandle> node_stack_;
+
+  perfetto::protos::pbzero::ChromeTracedValue proto_;
+  HeapScatteredStreamWriterDelegate delegate_;
+  protozero::ScatteredStreamWriter stream_;
+};
+
+std::unique_ptr<TracedValue::Writer> CreateProtoWriter(size_t capacity) {
+  return std::make_unique<ProtoWriter>(capacity);
+}
+
+}  // namespace
+
+void RegisterTracedValueProtoWriter() {
+  TracedValue::SetWriterFactoryCallback(&CreateProtoWriter);
+}
+
+}  // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
new file mode 100644
index 0000000..3bb39ad
--- /dev/null
+++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.h
@@ -0,0 +1,41 @@
+// 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 SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACED_VALUE_PROTO_WRITER_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACED_VALUE_PROTO_WRITER_H_
+
+#include "base/component_export.h"
+#include "base/trace_event/trace_event_impl.h"
+#include "third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h"
+
+namespace perfetto {
+namespace protos {
+namespace pbzero {
+class ChromeTraceEvent_Arg;
+}  // namespace pbzero
+}  // namespace protos
+}  // namespace perfetto
+
+namespace tracing {
+
+class COMPONENT_EXPORT(TRACING_CPP) PerfettoProtoAppender
+    : public base::trace_event::ConvertableToTraceFormat::ProtoAppender {
+ public:
+  explicit PerfettoProtoAppender(
+      perfetto::protos::pbzero::ChromeTraceEvent_Arg* proto);
+  ~PerfettoProtoAppender() override;
+
+  // ProtoAppender implementation
+  void AddBuffer(uint8_t* begin, uint8_t* end) override;
+  size_t Finalize(uint32_t field_id) override;
+
+ private:
+  std::vector<protozero::ContiguousMemoryRange> ranges_;
+  perfetto::protos::pbzero::ChromeTraceEvent_Arg* proto_;
+};
+
+void COMPONENT_EXPORT(TRACING_CPP) RegisterTracedValueProtoWriter();
+}  // namespace tracing
+
+#endif  // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACED_VALUE_PROTO_WRITER_H_
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc b/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
new file mode 100644
index 0000000..f8bdeb4
--- /dev/null
+++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
@@ -0,0 +1,317 @@
+// 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 "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
+
+#include <memory>
+#include <string>
+
+#include "base/trace_event/trace_event_argument.h"
+#include "services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.h"
+#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h"
+#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h"
+
+using TracedValue = base::trace_event::TracedValue;
+
+namespace tracing {
+
+namespace {
+
+class ProtoInputStream : public google::protobuf::io::ZeroCopyInputStream {
+ public:
+  explicit ProtoInputStream(HeapScatteredStreamWriterDelegate* delegate)
+      : delegate_(delegate) {
+    delegate->AdjustUsedSizeOfCurrentChunk();
+  }
+
+  // google::protobuf::io::ZeroCopyInputStream implementation.
+  bool Next(const void** data, int* size) override {
+    DCHECK(!has_backed_up_);
+
+    auto& chunks = delegate_->chunks();
+    if (chunks.size() <= chunks_read_) {
+      return false;
+    }
+
+    *data = chunks[chunks_read_].start();
+    *size = chunks[chunks_read_].size() - chunks[chunks_read_].unused_bytes();
+
+    chunks_read_++;
+    return true;
+  }
+
+  void BackUp(int count) override {
+    // This should only be called once, on the last buffer (and
+    // that means we can ignore it).
+    DCHECK(!has_backed_up_);
+    has_backed_up_ = true;
+  }
+
+  bool Skip(int count) override {
+    NOTREACHED();
+    return false;
+  }
+
+  int64_t ByteCount() const override {
+    NOTREACHED();
+    return 0;
+  }
+
+ private:
+  const HeapScatteredStreamWriterDelegate* delegate_;
+  size_t chunks_read_ = 0;
+  bool has_backed_up_ = false;
+};
+
+class TracedValueProtoWriterTest : public testing::Test {
+ public:
+  void SetUp() override { RegisterTracedValueProtoWriter(); }
+
+  void TearDown() override {}
+};
+
+const perfetto::protos::ChromeTracedValue* FindDictEntry(
+    const perfetto::protos::ChromeTracedValue* dict,
+    const char* name) {
+  EXPECT_EQ(dict->dict_values_size(), dict->dict_keys_size());
+
+  for (int i = 0; i < dict->dict_keys_size(); ++i) {
+    if (dict->dict_keys(i) == name) {
+      return &dict->dict_values(i);
+    }
+  }
+
+  NOTREACHED();
+  return nullptr;
+}
+
+bool IsValue(const perfetto::protos::ChromeTracedValue* proto_value,
+             bool value) {
+  return proto_value->has_bool_value() && (proto_value->bool_value() == value);
+}
+
+bool IsValue(const perfetto::protos::ChromeTracedValue* proto_value,
+             double value) {
+  return proto_value->has_double_value() &&
+         (proto_value->double_value() == value);
+}
+
+bool IsValue(const perfetto::protos::ChromeTracedValue* proto_value,
+             int value) {
+  return proto_value->has_int_value() && (proto_value->int_value() == value);
+}
+
+bool IsValue(const perfetto::protos::ChromeTracedValue* proto_value,
+             const char* value) {
+  return proto_value->has_string_value() &&
+         (proto_value->string_value() == value);
+}
+
+perfetto::protos::ChromeTracedValue GetProtoFromTracedValue(
+    TracedValue* traced_value) {
+  HeapScatteredStreamWriterDelegate delegate_(100);
+  protozero::ScatteredStreamWriter stream_(&delegate_);
+  perfetto::protos::pbzero::ChromeTraceEvent_Arg proto;
+  proto.Reset(&stream_);
+  delegate_.set_writer(&stream_);
+
+  PerfettoProtoAppender proto_appender(&proto);
+  EXPECT_TRUE(traced_value->AppendToProto(&proto_appender));
+  uint32_t size = proto.Finalize();
+  ProtoInputStream stream(&delegate_);
+
+  perfetto::protos::ChromeTraceEvent_Arg full_proto;
+  EXPECT_TRUE(full_proto.ParseFromBoundedZeroCopyStream(&stream, size));
+  EXPECT_TRUE(full_proto.has_traced_value());
+
+  return full_proto.traced_value();
+}
+
+TEST_F(TracedValueProtoWriterTest, FlatDictionary) {
+  std::unique_ptr<TracedValue> value(new TracedValue());
+  value->SetBoolean("bool", true);
+  value->SetDouble("double", 0.0);
+  value->SetInteger("int", 2014);
+  value->SetString("string", "string");
+
+  auto full_proto = GetProtoFromTracedValue(value.get());
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "bool"), true));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "double"), 0.0));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "int"), 2014));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "string"), "string"));
+}
+
+TEST_F(TracedValueProtoWriterTest, NoDotPathExpansion) {
+  std::unique_ptr<TracedValue> value(new TracedValue());
+  value->SetBoolean("bo.ol", true);
+  value->SetDouble("doub.le", 0.0);
+  value->SetInteger("in.t", 2014);
+  value->SetString("str.ing", "str.ing");
+
+  auto full_proto = GetProtoFromTracedValue(value.get());
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "bo.ol"), true));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "doub.le"), 0.0));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "in.t"), 2014));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "str.ing"), "str.ing"));
+}
+
+TEST_F(TracedValueProtoWriterTest, Hierarchy) {
+  std::unique_ptr<TracedValue> value(new TracedValue());
+  value->BeginArray("a1");
+  value->AppendInteger(1);
+  value->AppendBoolean(true);
+  value->BeginDictionary();
+  value->SetInteger("i2", 3);
+  value->EndDictionary();
+  value->EndArray();
+  value->SetBoolean("b0", true);
+  value->SetDouble("d0", 0.0);
+  value->BeginDictionary("dict1");
+  value->BeginDictionary("dict2");
+  value->SetBoolean("b2", false);
+  value->EndDictionary();
+  value->SetInteger("i1", 2014);
+  value->SetString("s1", "foo");
+  value->EndDictionary();
+  value->SetInteger("i0", 2014);
+  value->SetString("s0", "foo");
+
+  auto full_proto = GetProtoFromTracedValue(value.get());
+
+  auto* a1_array = FindDictEntry(&full_proto, "a1");
+  EXPECT_TRUE(a1_array);
+  EXPECT_EQ(a1_array->nested_type(),
+            perfetto::protos::ChromeTracedValue::ARRAY);
+  EXPECT_EQ(a1_array->array_values_size(), 3);
+  EXPECT_TRUE(IsValue(&a1_array->array_values(0), 1));
+  EXPECT_TRUE(IsValue(&a1_array->array_values(1), true));
+  auto* a1_subdict = &a1_array->array_values(2);
+  EXPECT_TRUE(a1_subdict);
+  EXPECT_EQ(a1_subdict->nested_type(),
+            perfetto::protos::ChromeTracedValue::DICT);
+  EXPECT_EQ(a1_subdict->dict_values_size(), 1);
+  EXPECT_TRUE(IsValue(FindDictEntry(a1_subdict, "i2"), 3));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "b0"), true));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "d0"), 0.0));
+  auto* dict1 = FindDictEntry(&full_proto, "dict1");
+  EXPECT_TRUE(dict1);
+  EXPECT_EQ(dict1->dict_values_size(), 3);
+  EXPECT_EQ(dict1->nested_type(), perfetto::protos::ChromeTracedValue::DICT);
+  auto* dict2 = FindDictEntry(dict1, "dict2");
+  EXPECT_TRUE(dict2);
+  EXPECT_EQ(dict2->dict_values_size(), 1);
+  EXPECT_EQ(dict2->nested_type(), perfetto::protos::ChromeTracedValue::DICT);
+  EXPECT_TRUE(IsValue(FindDictEntry(dict2, "b2"), false));
+  EXPECT_TRUE(IsValue(FindDictEntry(dict1, "i1"), 2014));
+  EXPECT_TRUE(IsValue(FindDictEntry(dict1, "s1"), "foo"));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "i0"), 2014));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "s0"), "foo"));
+}
+
+TEST_F(TracedValueProtoWriterTest, LongStrings) {
+  std::string kLongString = "supercalifragilisticexpialidocious";
+  std::string kLongString2 = "0123456789012345678901234567890123456789";
+  char kLongString3[4096];
+  for (size_t i = 0; i < sizeof(kLongString3); ++i)
+    kLongString3[i] = 'a' + (i % 25);
+  kLongString3[sizeof(kLongString3) - 1] = '\0';
+
+  std::unique_ptr<TracedValue> value(new TracedValue());
+  value->SetString("a", "short");
+  value->SetString("b", kLongString);
+  value->BeginArray("c");
+  value->AppendString(kLongString2);
+  value->AppendString("");
+  value->BeginDictionary();
+  value->SetString("a", kLongString3);
+  value->EndDictionary();
+  value->EndArray();
+
+  auto full_proto = GetProtoFromTracedValue(value.get());
+
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "a"), "short"));
+  EXPECT_TRUE(IsValue(FindDictEntry(&full_proto, "b"), kLongString.c_str()));
+  auto* c_array = FindDictEntry(&full_proto, "c");
+  EXPECT_TRUE(c_array);
+  EXPECT_EQ(c_array->array_values_size(), 3);
+  EXPECT_EQ(c_array->nested_type(), perfetto::protos::ChromeTracedValue::ARRAY);
+  EXPECT_TRUE(IsValue(&c_array->array_values(0), kLongString2.c_str()));
+  EXPECT_TRUE(IsValue(&c_array->array_values(1), ""));
+  auto* c_subdict = &c_array->array_values(2);
+  EXPECT_TRUE(c_subdict);
+  EXPECT_EQ(c_subdict->dict_values_size(), 1);
+  EXPECT_EQ(c_subdict->nested_type(),
+            perfetto::protos::ChromeTracedValue::DICT);
+  EXPECT_TRUE(IsValue(FindDictEntry(c_subdict, "a"), kLongString3));
+}
+
+// Test that the proto which results from the TracedValue is still
+// valid regardless of the size of the buffer chunks we provide to
+// the allocator, as some buffer sizes will leave unused bytes
+// at the end where there isn't enough space for, say, a size field.
+// 10-140 bytes tests both buffers being smaller and larger than
+// the actual size of the proto.
+TEST_F(TracedValueProtoWriterTest, ProtoMessageBoundaries) {
+  for (int i = 10; i < 140; ++i) {
+    std::unique_ptr<TracedValue> value(new TracedValue(i));
+
+    value->SetString("source", "RendererCompositor");
+    value->SetString("thread", "RendererCompositor");
+    value->SetString("compile_target", "Chromium");
+
+    auto full_proto = GetProtoFromTracedValue(value.get());
+
+    EXPECT_TRUE(
+        IsValue(FindDictEntry(&full_proto, "source"), "RendererCompositor"));
+    EXPECT_TRUE(
+        IsValue(FindDictEntry(&full_proto, "thread"), "RendererCompositor"));
+    EXPECT_TRUE(
+        IsValue(FindDictEntry(&full_proto, "compile_target"), "Chromium"));
+  }
+}
+
+TEST_F(TracedValueProtoWriterTest, PassTracedValue) {
+  auto dict_value = std::make_unique<TracedValue>();
+  dict_value->SetInteger("a", 1);
+
+  auto nested_dict_value = std::make_unique<TracedValue>();
+  nested_dict_value->SetInteger("b", 2);
+  nested_dict_value->BeginArray("c");
+  nested_dict_value->AppendString("foo");
+  nested_dict_value->EndArray();
+
+  dict_value->SetValue("e", nested_dict_value.get());
+
+  {
+    // Check the merged result.
+    auto parent_proto = GetProtoFromTracedValue(dict_value.get());
+
+    EXPECT_TRUE(IsValue(FindDictEntry(&parent_proto, "a"), 1));
+
+    auto* nested_dict = FindDictEntry(&parent_proto, "e");
+    EXPECT_TRUE(nested_dict);
+    EXPECT_EQ(nested_dict->dict_values_size(), 2);
+    EXPECT_TRUE(IsValue(FindDictEntry(nested_dict, "b"), 2));
+    auto* c_array = FindDictEntry(nested_dict, "c");
+    EXPECT_TRUE(c_array);
+    EXPECT_EQ(c_array->array_values_size(), 1);
+    EXPECT_TRUE(IsValue(&c_array->array_values(0), "foo"));
+  }
+
+  {
+    // Check that the passed nested dict was left untouched.
+    auto child_proto = GetProtoFromTracedValue(nested_dict_value.get());
+    EXPECT_TRUE(IsValue(FindDictEntry(&child_proto, "b"), 2));
+    auto* c_array = FindDictEntry(&child_proto, "c");
+    EXPECT_TRUE(c_array);
+    EXPECT_EQ(c_array->array_values_size(), 1);
+    EXPECT_TRUE(IsValue(&c_array->array_values(0), "foo"));
+  }
+}
+
+}  // namespace
+
+}  // namespace tracing
diff --git a/services/viz/public/cpp/compositing/quads_struct_traits.cc b/services/viz/public/cpp/compositing/quads_struct_traits.cc
index af3742e9..47121a2 100644
--- a/services/viz/public/cpp/compositing/quads_struct_traits.cc
+++ b/services/viz/public/cpp/compositing/quads_struct_traits.cc
@@ -79,7 +79,6 @@
     return false;
   }
   quad->force_anti_aliasing_off = data.force_anti_aliasing_off();
-  quad->backdrop_filter_quality = data.backdrop_filter_quality();
   return true;
 }
 
diff --git a/services/viz/public/cpp/compositing/quads_struct_traits.h b/services/viz/public/cpp/compositing/quads_struct_traits.h
index 129fcd1c..ac28fea3 100644
--- a/services/viz/public/cpp/compositing/quads_struct_traits.h
+++ b/services/viz/public/cpp/compositing/quads_struct_traits.h
@@ -189,12 +189,6 @@
     return quad->force_anti_aliasing_off;
   }
 
-  static float backdrop_filter_quality(const viz::DrawQuad& input) {
-    const viz::RenderPassDrawQuad* quad =
-        viz::RenderPassDrawQuad::MaterialCast(&input);
-    return quad->backdrop_filter_quality;
-  }
-
   static bool Read(viz::mojom::RenderPassQuadStateDataView data,
                    viz::DrawQuad* out);
 };
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
index 0cb36c0..fdc693e 100644
--- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -903,7 +903,6 @@
   const gfx::Rect rect2(2468, 8642, 4321, 1234);
   const uint32_t color2 = 0xffffffff;
   const bool force_anti_aliasing_off = true;
-  const float backdrop_filter_quality = 1.0f;
   SolidColorDrawQuad* solid_quad =
       render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   solid_quad->SetNew(sqs, rect2, rect2, color2, force_anti_aliasing_off);
@@ -935,7 +934,7 @@
   render_pass_quad->SetNew(sqs, rect4, rect4, render_pass_id, resource_id4,
                            mask_uv_rect, mask_texture_size, filters_scale,
                            filters_origin, tex_coord_rect,
-                           force_anti_aliasing_off, backdrop_filter_quality);
+                           force_anti_aliasing_off);
 
   const gfx::Rect rect5(123, 567, 91011, 131415);
   const ResourceId resource_id5(1337);
diff --git a/services/viz/public/interfaces/compositing/quads.mojom b/services/viz/public/interfaces/compositing/quads.mojom
index 3f12a14..b1eaad0 100644
--- a/services/viz/public/interfaces/compositing/quads.mojom
+++ b/services/viz/public/interfaces/compositing/quads.mojom
@@ -41,7 +41,6 @@
   gfx.mojom.RectF tex_coord_rect;
 
   bool force_anti_aliasing_off;
-  float backdrop_filter_quality;
 };
 
 struct SolidColorQuadState {
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index bd96e6ac..25b9de9 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -21361,6 +21361,51 @@
       {
         "args": [
           "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "experiment_percentage": 50,
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "chrome_public_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "shards": 20
+        },
+        "test": "chrome_public_test_apk"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
           "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk"
diff --git a/testing/buildbot/filters/webui_polymer2_browser_tests.filter b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
index f9e3013..f4fa3d3fd 100644
--- a/testing/buildbot/filters/webui_polymer2_browser_tests.filter
+++ b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
@@ -241,6 +241,7 @@
 NetInternalsTest.*
 NoBackgroundTasksTest.*
 NTP4WebUITest.*
+OnboardingWelcomeEmailChooserTest.*
 OpenAudioFiles/*
 PasswordsAndFormsBrowserTest.*
 PrintPreviewAdvancedDialogTest.*
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index fe9065c..78d7f97 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -221,10 +221,6 @@
     ],
   },
   'chrome_public_test_apk': {
-    'remove_from': [
-      # TODO(crbug.com/877280): Add it back when we have the capacity.
-      'android-marshmallow-arm64-rel',
-    ],
     'modifications': {
       # chromium.android
       'android-kitkat-arm-rel': {
@@ -232,6 +228,11 @@
           'shards': 12,
         },
       },
+      'android-marshmallow-arm64-rel': {
+        # TODO(crbug.com/731759): Enable this once we're confident that it
+        # passes.
+        'experiment_percentage': 50,
+      },
       'KitKat Phone Tester (dbg)': {
         'swarming': {
           'shards': 20,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 053d02c..d2d12e8b 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3170,7 +3170,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Intervention_R8",
+                    "name": "Intervention_R9",
                     "params": {
                         "navigate_ads": "true",
                         "pause_renderer": "true",
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 1660813..2ce7c71 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -380,7 +380,6 @@
 crbug.com/591099 media/picture-in-picture/picture-in-picture-interstitial.html [ Pass ]
 crbug.com/591099 paint/float/float-under-inline-self-painting-change.html [ Failure ]
 crbug.com/835484 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ]
-crbug.com/591099 paint/invalidation/clip/control-clip.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/align-content-change-keeping-geometry.html [ Failure ]
 crbug.com/591099 paint/invalidation/flexbox/align-self-change-keeping-geometry-grid.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index c176e79..9056ea14 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -29,6 +29,7 @@
 crbug.com/891427 virtual/threaded/animations/responsive/viewport-unit-translate-responsive.html [ Timeout ]
 crbug.com/891427 virtual/threaded/http/tests/devtools/tracing/frame-model-instrumentation.js [ Failure ]
 crbug.com/891427 fast/scrolling/editor-command-scroll-page-scale.html [ Failure ]
+crbug.com/891427 virtual/fractional_scrolling/fast/scrolling/editor-command-scroll-page-scale.html [ Pass Failure ]
 crbug.com/891427 virtual/scroll_customization/fast/scrolling/editor-command-scroll-page-scale.html [ Failure ]
 crbug.com/891427 virtual/threaded/fast/scrolling/editor-command-scroll-page-scale.html [ Failure ]
 crbug.com/891427 fast/replaced/replaced-breaking.html [ Failure ]
@@ -3151,6 +3152,7 @@
 crbug.com/893480 external/wpt/infrastructure/testdriver/actions/multiDevice.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height.html [ Failure ]
 crbug.com/626703 external/wpt/wasm/webapi/instantiateStreaming-bad-imports.any.serviceworker.html [ Crash ]
 crbug.com/626703 external/wpt/wasm/webapi/rejected-arg.any.html [ Timeout ]
 crbug.com/626703 external/wpt/wasm/webapi/instantiateStreaming.any.serviceworker.html [ Crash ]
@@ -3285,13 +3287,8 @@
 crbug.com/626703 virtual/layout_ng_experimental/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-block-margins-2.html [ Failure ]
 crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-block-margins-2.html [ Failure ]
 crbug.com/626703 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-not-allowed.https.html [ Timeout ]
-crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/postmessage-to-client.https.html [ Timeout ]
-crbug.com/626703 external/wpt/service-workers/service-worker/postmessage-to-client.https.html [ Timeout ]
-crbug.com/626703 virtual/outofblink-cors/external/wpt/service-workers/service-worker/postmessage-to-client.https.html [ Timeout ]
-crbug.com/626703 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/postmessage-to-client.https.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Failure ]
-crbug.com/626703 [ Win10 ] external/wpt/speech-api/idlharness.window.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center_position_50.html [ Failure ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center_wrapped.html [ Failure ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center_position_lt_50.html [ Failure ]
@@ -4339,6 +4336,13 @@
 crbug.com/595993 virtual/outofblink-cors/external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ]
 crbug.com/595993 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ]
 
+# These tests fail because ServiceWorkerContainer.startMessages() is not
+# implemented yet.
+crbug.com/894682 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ]
+crbug.com/894682 external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ]
+crbug.com/894682 virtual/outofblink-cors/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ]
+crbug.com/894682 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ]
+
 crbug.com/619427 [ Mac Linux ] fast/overflow/overflow-height-float-not-removed-crash3.html [ Pass Failure ]
 
 # [css-ui] Imported tests from W3C suite.
@@ -5710,7 +5714,6 @@
 
 #Sheriff 2018-10-23
 crbug.com/898156 [ Linux Mac Win ] inspector-protocol/runtime/runtime-console-log-handle-navigate.js [ Crash ]
-crbug.com/898214 [ Mac10.10 Mac10.11 ] external/wpt/html/dom/interfaces.https.html?exclude=(Document|Window|HTML.*) [ Failure ]
 crbug.com/898214 [ Mac10.11 ] virtual/outofblink-cors-ns/external/wpt/fetch/api/credentials/authentication-basic.any.html [ Failure ]
 crbug.com/898050 [ Mac Win ] fast/workers/taskqueue/basic.html [ Pass Timeout ]
 crbug.com/898378 [ Mac10.13 ] fast/scroll-behavior/smooth-scroll/keyboard-scroll.html [ Timeout ]
@@ -5755,3 +5758,4 @@
 
 # Sheriff 2018-10-30
 crbug.com/867668 [ Linux ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-click-hyperlink.html [ Failure Pass ]
+crbug.com/867668 [ Linux ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
index 8752473a..7f5deb5 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -101159,6 +101159,18 @@
      {}
     ]
    ],
+   "html/rendering/replaced-elements/the-select-element/select-1-line-height.html": [
+    [
+     "/html/rendering/replaced-elements/the-select-element/select-1-line-height.html",
+     [
+      [
+       "/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "html/rendering/the-css-user-agent-style-sheet-and-presentational-hints/body-bgcolor-attribute-change.html": [
     [
      "/html/rendering/the-css-user-agent-style-sheet-and-presentational-hints/body-bgcolor-attribute-change.html",
@@ -102819,6 +102831,18 @@
      {}
     ]
    ],
+   "svg/linking/reftests/use-hidden-attr-change.html": [
+    [
+     "/svg/linking/reftests/use-hidden-attr-change.html",
+     [
+      [
+       "/svg/linking/reftests/use-descendant-combinator-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/painting/currentColor-override-pserver-fallback.svg": [
     [
      "/svg/painting/currentColor-override-pserver-fallback.svg",
@@ -103167,6 +103191,18 @@
      {}
     ]
    ],
+   "svg/render/reftests/filter-effects-on-pattern.html": [
+    [
+     "/svg/render/reftests/filter-effects-on-pattern.html",
+     [
+      [
+       "/svg/render/reftests/filter-effects-on-pattern-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/rendering/order/z-index.svg": [
     [
      "/svg/rendering/order/z-index.svg",
@@ -103179,6 +103215,18 @@
      {}
     ]
    ],
+   "svg/shapes/circle-01.svg": [
+    [
+     "/svg/shapes/circle-01.svg",
+     [
+      [
+       "/svg/shapes/circle-01-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/shapes/ellipse-01.svg": [
     [
      "/svg/shapes/ellipse-01.svg",
@@ -103275,6 +103323,18 @@
      {}
     ]
    ],
+   "svg/shapes/ellipse-09.svg": [
+    [
+     "/svg/shapes/ellipse-09.svg",
+     [
+      [
+       "/svg/shapes/ellipse-04-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/shapes/line-dasharray.svg": [
     [
      "/svg/shapes/line-dasharray.svg",
@@ -103335,6 +103395,18 @@
      {}
     ]
    ],
+   "svg/shapes/rect-05.svg": [
+    [
+     "/svg/shapes/rect-05.svg",
+     [
+      [
+       "/svg/shapes/rect-05-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/shapes/reftests/pathlength-001.svg": [
     [
      "/svg/shapes/reftests/pathlength-001.svg",
@@ -120227,11 +120299,6 @@
      {}
     ]
    ],
-   "css/css-animations/idlharness-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "css/css-animations/parsing/animation-name-invalid-expected.txt": [
     [
      {}
@@ -137327,6 +137394,11 @@
      {}
     ]
    ],
+   "css/css-text/inheritance-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-text/letter-spacing/reference/letter-spacing-control-chars-001.ref.html": [
     [
      {}
@@ -138712,6 +138784,11 @@
      {}
     ]
    ],
+   "css/css-transforms/inheritance-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-transforms/inline-styles/reference/svg-inline-styles-ref.html": [
     [
      {}
@@ -140102,11 +140179,6 @@
      {}
     ]
    ],
-   "css/css-transitions/idlharness-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "css/css-transitions/properties-value-001-expected.txt": [
     [
      {}
@@ -140832,6 +140904,11 @@
      {}
     ]
    ],
+   "css/css-ui/inheritance-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-ui/outline-018-expected.txt": [
     [
      {}
@@ -146482,6 +146559,11 @@
      {}
     ]
    ],
+   "css/support/computed-testcommon.js": [
+    [
+     {}
+    ]
+   ],
    "css/support/green.ico": [
     [
      {}
@@ -154372,21 +154454,6 @@
      {}
     ]
    ],
-   "hr-time/idlharness.any.serviceworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "hr-time/idlharness.any.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "hr-time/idlharness.any.worker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "hr-time/resources/now_frame.html": [
     [
      {}
@@ -161012,11 +161079,6 @@
      {}
     ]
    ],
-   "html/interaction/focus/processing-model/legend-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "html/interaction/focus/processing-model/support/preventScroll-helper.html": [
     [
      {}
@@ -161552,6 +161614,11 @@
      {}
     ]
    ],
+   "html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html": [
+    [
+     {}
+    ]
+   ],
    "html/rendering/replaced-elements/tools/gen-svgsizing-tests.py": [
     [
      {}
@@ -163227,6 +163294,11 @@
      {}
     ]
    ],
+   "html/semantics/forms/form-submission-target/form-target-iframe-helper.py": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/forms/introduction-1/contains.json": [
     [
      {}
@@ -177822,6 +177894,11 @@
      {}
     ]
    ],
+   "svg/render/reftests/filter-effects-on-pattern-ref.html": [
+    [
+     {}
+    ]
+   ],
    "svg/rendering/order/z-index-ref.svg": [
     [
      {}
@@ -177832,6 +177909,11 @@
      {}
     ]
    ],
+   "svg/shapes/circle-01-ref.svg": [
+    [
+     {}
+    ]
+   ],
    "svg/shapes/ellipse-01-ref.svg": [
     [
      {}
@@ -177882,6 +177964,11 @@
      {}
     ]
    ],
+   "svg/shapes/rect-05-ref.svg": [
+    [
+     {}
+    ]
+   ],
    "svg/shapes/reftests/pathlength-001-ref.svg": [
     [
      {}
@@ -198419,6 +198506,12 @@
      {}
     ]
    ],
+   "css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html": [
+    [
+     "/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html",
+     {}
+    ]
+   ],
    "css/CSS2/floats/zero-space-between-floats-001.html": [
     [
      "/css/CSS2/floats/zero-space-between-floats-001.html",
@@ -205325,6 +205418,12 @@
      {}
     ]
    ],
+   "css/css-transforms/inheritance.html": [
+    [
+     "/css/css-transforms/inheritance.html",
+     {}
+    ]
+   ],
    "css/css-transforms/parsing/perspective-origin-parsing-invalid.html": [
     [
      "/css/css-transforms/parsing/perspective-origin-parsing-invalid.html",
@@ -210017,6 +210116,12 @@
      {}
     ]
    ],
+   "css/motion/inheritance.html": [
+    [
+     "/css/motion/inheritance.html",
+     {}
+    ]
+   ],
    "css/motion/offset-path-serialization.html": [
     [
      "/css/motion/offset-path-serialization.html",
@@ -210465,6 +210570,12 @@
      {}
     ]
    ],
+   "css/selectors/invalidation/where.html": [
+    [
+     "/css/selectors/invalidation/where.html",
+     {}
+    ]
+   ],
    "css/selectors/matches-nested.html": [
     [
      "/css/selectors/matches-nested.html",
@@ -231531,6 +231642,12 @@
      {}
     ]
    ],
+   "html/semantics/forms/form-submission-target/form-target-iframe.html": [
+    [
+     "/html/semantics/forms/form-submission-target/form-target-iframe.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/historical.html": [
     [
      "/html/semantics/forms/historical.html",
@@ -286973,7 +287090,7 @@
    "testharness"
   ],
   "2dcontext/imagebitmap/createImageBitmap-invalid-args-expected.txt": [
-   "149fbe0d8c1bea6efb95351e83167314f2743bac",
+   "9824e58ea0bfa61c788ddee35892c6116f0bd032",
    "support"
   ],
   "2dcontext/imagebitmap/createImageBitmap-invalid-args.html": [
@@ -289277,7 +289394,7 @@
    "testharness"
   ],
   "IndexedDB/get-databases.any.js": [
-   "99b7ae7d4681f002779699d8737047aff9198012",
+   "f054e0fec2f0543eae7978303ae2a24858bdf245",
    "testharness"
   ],
   "IndexedDB/globalscope-indexedDB-SameObject.html": [
@@ -290569,11 +290686,11 @@
    "testharness"
   ],
   "IndexedDB/support-promises.js": [
-   "21e2163ec60eb3eee05269b83f583f77fad780eb",
+   "d320ba04ce951d905a754aa63a89619e0c941c20",
    "support"
   ],
   "IndexedDB/support.js": [
-   "9b3b92218b16bcabc430af8eb2160180f51bd5d8",
+   "5edbdacbcc7d0cf27d0e3330198b55d50540345e",
    "support"
   ],
   "IndexedDB/transaction-abort-generator-revert.html": [
@@ -292337,7 +292454,7 @@
    "testharness"
   ],
   "audio-output/setSinkId-expected.txt": [
-   "cdf1a9fc3225b118058907cb6e72cb153fb898f0",
+   "81cdb58c5f45395a51395571ea2cd7979faf8d7c",
    "support"
   ],
   "audio-output/setSinkId-manual.https.html": [
@@ -292349,7 +292466,7 @@
    "testharness"
   ],
   "audio-output/setSinkId.https-expected.txt": [
-   "cdf1a9fc3225b118058907cb6e72cb153fb898f0",
+   "81cdb58c5f45395a51395571ea2cd7979faf8d7c",
    "support"
   ],
   "audio-output/setSinkId.https.html": [
@@ -292829,7 +292946,7 @@
    "testharness"
   ],
   "bluetooth/idl/idlharness.tentative.https.window-expected.txt": [
-   "4a16e4f396b4419bb1d7b77bcb10f584dc1bb5b9",
+   "e5d18e75caf74f49ee2f1ad67ca2dc18f627be24",
    "support"
   ],
   "bluetooth/idl/idlharness.tentative.https.window.js": [
@@ -293877,7 +293994,7 @@
    "testharness"
   ],
   "compat/idlharness.window-expected.txt": [
-   "0104eb394c86d999c034644eedddba2609bc191e",
+   "6deefcc139986cd0068208e6baa4f1accc6ac70f",
    "support"
   ],
   "compat/idlharness.window.js": [
@@ -299412,6 +299529,10 @@
    "129263ecb7d972fa85974e0423ba59645b2b0424",
    "reftest"
   ],
+  "css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html": [
+   "4b1baff8b956d706b2f90e67277ccf3a7c4d3458",
+   "testharness"
+  ],
   "css/CSS2/abspos/between-float-and-text.html": [
    "b4c933e8d8021ed357d9942d2f44b7cd44abbf76",
    "reftest"
@@ -314128,10 +314249,6 @@
    "5b96a422f55f45cddabdf011acb83e5081ec1ef3",
    "testharness"
   ],
-  "css/css-animations/idlharness-expected.txt": [
-   "50b4cddbf768e2e5b8d8a786b6db59a432fb8a0b",
-   "support"
-  ],
   "css/css-animations/idlharness.html": [
    "1d3ed2b9b806792c7efaeeee9ab264101dd222bc",
    "testharness"
@@ -335509,7 +335626,7 @@
    "support"
   ],
   "css/css-masking/idlharness-expected.txt": [
-   "002bd396362453e0ae6a208635e6f529dd1b7a6b",
+   "f188afc0043b727bb09f4342f294a737793f51e3",
    "support"
   ],
   "css/css-masking/idlharness.html": [
@@ -337901,15 +338018,15 @@
    "testharness"
   ],
   "css/css-properties-values-api/registered-property-computation.html": [
-   "1651295cba45af823a4c5c2b7074dc361308847b",
+   "180cdf601edd4a82398d29239141bf38e55bd0c1",
    "testharness"
   ],
   "css/css-properties-values-api/registered-property-cssom.html": [
-   "019778e95e03689aaab5e47a0fd6be2382f3fb99",
+   "59443b3323a89f64e2ae5b07508819b2872ead12",
    "testharness"
   ],
   "css/css-properties-values-api/registered-property-initial.html": [
-   "d655af661f7fd95ed0289cddb9c5546467d28592",
+   "24543d5c5fdc84706a28502d8cf8c2c7f925978e",
    "testharness"
   ],
   "css/css-properties-values-api/resources/utils.js": [
@@ -338029,7 +338146,7 @@
    "reftest"
   ],
   "css/css-pseudo/idlharness-expected.txt": [
-   "8b356c8339d2c644a365e2473da60bc5278d26d7",
+   "4ccc625263f54e24750d9a852a714c4f3b1405b5",
    "support"
   ],
   "css/css-pseudo/idlharness.html": [
@@ -343296,6 +343413,10 @@
    "ec44c093a32decdc7bd39b77d7409fff36b62f4b",
    "testharness"
   ],
+  "css/css-text/inheritance-expected.txt": [
+   "42a075a61ac85fbb1c487b8224a92028593f62e5",
+   "support"
+  ],
   "css/css-text/inheritance.html": [
    "ef3270651c3df4ae6112fdfeec0e7fea4b9d6ccf",
    "testharness"
@@ -346532,6 +346653,14 @@
    "0350137bedefbf1491faf54a75115be08a858703",
    "reftest"
   ],
+  "css/css-transforms/inheritance-expected.txt": [
+   "7862d8b1fe1301290c8cb059a303dce7aa674813",
+   "support"
+  ],
+  "css/css-transforms/inheritance.html": [
+   "2bc0cf5c803947a076728919fdec0380e2c541b1",
+   "testharness"
+  ],
   "css/css-transforms/inline-styles/reference/svg-inline-styles-ref.html": [
    "3a953420308986668b4114fc496d81a072f7c68a",
    "support"
@@ -351352,10 +351481,6 @@
    "8d0360a8ecf7a37b81acb10917b63abc7c9543cc",
    "testharness"
   ],
-  "css/css-transitions/idlharness-expected.txt": [
-   "74256a1bb72f5d4fba014477682264522fedd0cf",
-   "support"
-  ],
   "css/css-transitions/idlharness.html": [
    "4cc7ee50eb4915fcf95843f7eeee266abfa7b81a",
    "testharness"
@@ -352005,7 +352130,7 @@
    "testharness"
   ],
   "css/css-typed-om/interfaces-expected.txt": [
-   "7c32597684e932b0aa43e0af9ffa37ce7cdf2654",
+   "20b1327353b09f826aa79eec3be678e9383665f9",
    "support"
   ],
   "css/css-typed-om/interfaces.html": [
@@ -354252,6 +354377,10 @@
    "cb3b7ae9df1998eb125182d21e6d27d79f408e81",
    "manual"
   ],
+  "css/css-ui/inheritance-expected.txt": [
+   "848321d9a14266b6de4bb2eb5360797f978b1324",
+   "support"
+  ],
   "css/css-ui/inheritance.html": [
    "912e9f3228f5be96542f8052a13fca9acb718f83",
    "testharness"
@@ -363209,7 +363338,7 @@
    "testharness"
   ],
   "css/cssom-view/interfaces-expected.txt": [
-   "eb20004db272bb7df9ddb30773b6a859bb4839b7",
+   "62a5805456e6bb6d7b6e1990b80a66e77c65dd32",
    "support"
   ],
   "css/cssom-view/interfaces.html": [
@@ -363897,7 +364026,7 @@
    "testharness"
   ],
   "css/cssom/interfaces-expected.txt": [
-   "706e87a3a58aba9b66678871282668e92f61acb3",
+   "a83ae3f6f059d12f3eabd5b9aee6d5153b71db55",
    "support"
   ],
   "css/cssom/interfaces.html": [
@@ -364564,6 +364693,10 @@
    "6933733e1970d06fd5473b74f7ba63a9a821624a",
    "support"
   ],
+  "css/motion/inheritance.html": [
+   "8af4f9b91a83506d6f20c320e229cf890e0fdf4f",
+   "testharness"
+  ],
   "css/motion/offset-anchor-transform-box-fill-box-ref.html": [
    "f718ea6abfbab54333ba674ff0dcd320d8672bcd",
    "support"
@@ -365164,6 +365297,10 @@
    "41778239518d4d9b602f7fc18ee3ea5c910da85b",
    "reftest"
   ],
+  "css/selectors/invalidation/where.html": [
+   "1c6432f46eb4f2b424fdd3ca9c453925a23710ed",
+   "testharness"
+  ],
   "css/selectors/matches-nested.html": [
    "b82d43d09017955af2904f6362e858929a6d4399",
    "testharness"
@@ -366656,6 +366793,10 @@
    "85dd7324815b8f8ef1a1d0496224c1a0661db9d8",
    "support"
   ],
+  "css/support/computed-testcommon.js": [
+   "0999418e748162bcee4d062b010bca45bd7cfdfe",
+   "support"
+  ],
   "css/support/green.ico": [
    "691f61166f0d8f3c51d8e6441c9584c858223686",
    "support"
@@ -372053,7 +372194,7 @@
    "testharness"
   ],
   "dom/interfaces_exclude=Node-expected.txt": [
-   "33ba6302ac10570d37fa9b0f229142761ab21151",
+   "41fe5fad5348f067d6775f565a2233662c6093a0",
    "support"
   ],
   "dom/lists/DOMTokenList-Iterable.html": [
@@ -373545,7 +373686,7 @@
    "testharness"
   ],
   "domparsing/interfaces.any.worker-expected.txt": [
-   "a7bebc632f47797738405ff3f7fa844a4da84485",
+   "ac6137df9df30045488ad21d7cee76c7e270539c",
    "support"
   ],
   "domparsing/outerhtml-01.html": [
@@ -377209,7 +377350,7 @@
    "support"
   ],
   "feature-policy/idlharness.window-expected.txt": [
-   "c4a5606274e6baaec4fe2f0b8fe0e62c56bde332",
+   "71a041e90710f0287c8b864a511e49caf1305ba3",
    "support"
   ],
   "feature-policy/idlharness.window.js": [
@@ -377805,7 +377946,7 @@
    "testharness"
   ],
   "fetch/api/idl.any-expected.txt": [
-   "b013c5c01cf6101d4a24aed21b7933fbae0ea904",
+   "c0f63b02ed266a31f8b42a8a395de157201feaf9",
    "support"
   ],
   "fetch/api/idl.any.js": [
@@ -377813,15 +377954,15 @@
    "testharness"
   ],
   "fetch/api/idl.any.serviceworker-expected.txt": [
-   "cf90de4569b1aad191d590b2d2aeebcbd19b209c",
+   "47b603335d336fe1011f5ad2bd5e48a8f45d478d",
    "support"
   ],
   "fetch/api/idl.any.sharedworker-expected.txt": [
-   "20b02f1c54a7b0383a719fa01306d620949c9938",
+   "c0f63b02ed266a31f8b42a8a395de157201feaf9",
    "support"
   ],
   "fetch/api/idl.any.worker-expected.txt": [
-   "20b02f1c54a7b0383a719fa01306d620949c9938",
+   "c0f63b02ed266a31f8b42a8a395de157201feaf9",
    "support"
   ],
   "fetch/api/policies/csp-blocked-worker-expected.txt": [
@@ -378697,15 +378838,15 @@
    "testharness"
   ],
   "fetch/cors-rfc1918/idlharness.tentative.any.serviceworker-expected.txt": [
-   "2d89b4412e3e2b8623ee2e3f1fea430ad85bbe80",
+   "8558fae4a9e5dd1078f39f63c19c2d34931b8bb4",
    "support"
   ],
   "fetch/cors-rfc1918/idlharness.tentative.any.sharedworker-expected.txt": [
-   "2d89b4412e3e2b8623ee2e3f1fea430ad85bbe80",
+   "8558fae4a9e5dd1078f39f63c19c2d34931b8bb4",
    "support"
   ],
   "fetch/cors-rfc1918/idlharness.tentative.any.worker-expected.txt": [
-   "2d89b4412e3e2b8623ee2e3f1fea430ad85bbe80",
+   "8558fae4a9e5dd1078f39f63c19c2d34931b8bb4",
    "support"
   ],
   "fetch/cross-origin-resource-policy/fetch-expected.txt": [
@@ -379877,7 +380018,7 @@
    "support"
   ],
   "gamepad/idlharness.window-expected.txt": [
-   "dc95c50da05b27c95fee09b9d044819c6a867833",
+   "915af06444db6fc8d6b7b3254057b2eacea971b8",
    "support"
   ],
   "gamepad/idlharness.window.js": [
@@ -380224,18 +380365,6 @@
    "4e266c09e3358034e6fac6fb282bbeb138e4278a",
    "testharness"
   ],
-  "hr-time/idlharness.any.serviceworker-expected.txt": [
-   "02975ba0f63852a89c92413ddf0077d92e56a6a7",
-   "support"
-  ],
-  "hr-time/idlharness.any.sharedworker-expected.txt": [
-   "02975ba0f63852a89c92413ddf0077d92e56a6a7",
-   "support"
-  ],
-  "hr-time/idlharness.any.worker-expected.txt": [
-   "02975ba0f63852a89c92413ddf0077d92e56a6a7",
-   "support"
-  ],
   "hr-time/monotonic-clock.any.js": [
    "f7f254557f4296f8e69757eb9ed3ac11a05d3a33",
    "testharness"
@@ -380357,7 +380486,7 @@
    "support"
   ],
   "html-media-capture/idlharness.window-expected.txt": [
-   "b887ef5b2298ecfa2197c00b81783941fb827c8c",
+   "c8248ba917fd886a519cc6cf2bfa29912dfc1675",
    "support"
   ],
   "html-media-capture/idlharness.window.js": [
@@ -382661,7 +382790,7 @@
    "support"
   ],
   "html/browsers/the-window-object/window-properties.https-expected.txt": [
-   "706f4d55ae64ab6ee025955499fc13194bfc0600",
+   "bc228dee1a5cd3a2a940098470ced39e8c016915",
    "support"
   ],
   "html/browsers/the-window-object/window-properties.https.html": [
@@ -384125,7 +384254,7 @@
    "testharness"
   ],
   "html/dom/interfaces.https_exclude=(Document_Window_HTML._)-expected.txt": [
-   "32ee1e59eb978b361d2011fb518c3ff7c3271c3b",
+   "fa4972aa45cd156bc80ec41fa77dd732c5d50212",
    "support"
   ],
   "html/dom/interfaces.https_include=(Document_Window)-expected.txt": [
@@ -388220,10 +388349,6 @@
    "d8171abc715990a9e752c2d974acdfd7ecd34fc2",
    "testharness"
   ],
-  "html/interaction/focus/processing-model/legend-expected.txt": [
-   "e8e576ac85c8f1fa3101b0396b4058fd3e6fc49c",
-   "support"
-  ],
   "html/interaction/focus/processing-model/legend-focusable.html": [
    "c9209d3cf62d467ad1eb7a13c51fa45d55c19fb3",
    "testharness"
@@ -389392,6 +389517,14 @@
    "3b8d992cc2a07dfd902dbb1011e2c348e862baaa",
    "reftest"
   ],
+  "html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html": [
+   "26e5f33282192b10f56cd66fefeda2c1b9d9b389",
+   "support"
+  ],
+  "html/rendering/replaced-elements/the-select-element/select-1-line-height.html": [
+   "e6383f089ffa5550005f99257ecac7984dd09110",
+   "reftest"
+  ],
   "html/rendering/replaced-elements/tools/gen-svgsizing-tests.py": [
    "5ba69f8ab5ba0a74810c570d9a4f3d7ddd90a3ba",
    "support"
@@ -393208,6 +393341,14 @@
    "d05364387e62dfedc857628af833c3558ee3d1db",
    "testharness"
   ],
+  "html/semantics/forms/form-submission-target/form-target-iframe-helper.py": [
+   "291221a9f6ba8876a022021c53c38ff28a3fd893",
+   "support"
+  ],
+  "html/semantics/forms/form-submission-target/form-target-iframe.html": [
+   "f37bc33f6f93ca94940ffeb0066945eb9aa020ee",
+   "testharness"
+  ],
   "html/semantics/forms/historical.html": [
    "6873ecd251741fb8436a377081d5a6d3de53b7ab",
    "testharness"
@@ -401505,7 +401646,7 @@
    "support"
   ],
   "mediacapture-fromelement/idlharness.window-expected.txt": [
-   "124357262486faeca6da07bde09d0fd09765195c",
+   "e2149ce949cb54bf34daf519d0ece6f17d8d2565",
    "support"
   ],
   "mediacapture-fromelement/idlharness.window.js": [
@@ -401809,7 +401950,7 @@
    "testharness"
   ],
   "mediacapture-streams/idlharness.https.window-expected.txt": [
-   "aa959031a0539255b84d7e964add7b4e7c7c1d21",
+   "da7a86a02110e86d0302242a95e9b11d354bd8f8",
    "support"
   ],
   "mediacapture-streams/idlharness.https.window.js": [
@@ -411973,7 +412114,7 @@
    "testharness"
   ],
   "payment-request/META.yml": [
-   "0a075e19c6bd89b662c088689c87124c1627d024",
+   "e608c0ee279fcb7987f9167f8223f3fedce66c33",
    "support"
   ],
   "payment-request/MerchantValidationEvent/complete-method-manual.https-expected.txt": [
@@ -412441,7 +412582,7 @@
    "support"
   ],
   "performance-timeline/webtiming-resolution.any.js": [
-   "4031388a3bce39692e68292596d30864f5dfbaff",
+   "46e0489352f09767dc847615bd64464946f9088e",
    "testharness"
   ],
   "performance-timeline/worker-with-performance-observer.html": [
@@ -412493,7 +412634,7 @@
    "testharness"
   ],
   "picture-in-picture/picture-in-picture-window.html": [
-   "6d14cf54c71bd3ec30e0818e0af0713562c4cfcf",
+   "47b8133274276b407e854bfffc7362fb37777e21",
    "testharness"
   ],
   "picture-in-picture/request-picture-in-picture-twice.html": [
@@ -412593,7 +412734,7 @@
    "support"
   ],
   "pointerevents/idlharness.window-expected.txt": [
-   "fb85fa069a511a66975e9507ca9072b8de118652",
+   "fd20b3c8f221720c598c8117fb4ebac37212d429",
    "support"
   ],
   "pointerevents/idlharness.window.js": [
@@ -413437,7 +413578,7 @@
    "testharness"
   ],
   "push-api/idlharness.https.any.serviceworker-expected.txt": [
-   "2a17bcb16d14ab27fedf9b39526592e2dc556e1f",
+   "d0869e0c2479d67cc748449dbca84525e06e60de",
    "support"
   ],
   "quirks/META.yml": [
@@ -422201,7 +422342,7 @@
    "support"
   ],
   "resources/idlharness.js": [
-   "9e6ed236b0a43f32ffaecbbbb2b8fbe7540b83c5",
+   "40a5fa59cd209d12e6d42dcdff92c4974ae49cf2",
    "support"
   ],
   "resources/idlharness.js.headers": [
@@ -426877,7 +427018,7 @@
    "testharness"
   ],
   "speech-api/idlharness.window-expected.txt": [
-   "e913d754fb7115c56329bbefe1f0d22d09e5c4b4",
+   "ee63d6ddb08884ca48c46c9428fbf14dbddfeab0",
    "support"
   ],
   "speech-api/idlharness.window.js": [
@@ -428525,7 +428666,7 @@
    "testharness"
   ],
   "svg/idlharness.window-expected.txt": [
-   "b4aa8b69006486f5f3ca3877c9b4ff9f775479c0",
+   "36ed012772ed16804638a6ba9f1ebdeca0158acc",
    "support"
   ],
   "svg/idlharness.window.js": [
@@ -428612,6 +428753,10 @@
    "dae3fc1173b9280de8959edff3d5991a8b4c7593",
    "support"
   ],
+  "svg/linking/reftests/use-hidden-attr-change.html": [
+   "4fe535bbac11a457cdd4d9187498e4a9f3bf6f8d",
+   "reftest"
+  ],
   "svg/painting/currentColor-override-pserver-fallback-ref.svg": [
    "c4d946beb6e00cca918d05148fb16e818bb93723",
    "support"
@@ -428872,6 +429017,14 @@
    "7cbf68d39a05d9b3e27f2613b65eaf64f63ed54b",
    "reftest"
   ],
+  "svg/render/reftests/filter-effects-on-pattern-ref.html": [
+   "a61f17bf199374af3b6d106d3f5a72bc532449b8",
+   "support"
+  ],
+  "svg/render/reftests/filter-effects-on-pattern.html": [
+   "1894bf8cc3b1c51f7bebd334ca422e9c75d5c3dd",
+   "reftest"
+  ],
   "svg/rendering/order/z-index-ref.svg": [
    "ff7f9156682b6436ea8d0e4ab805b7c0f0d0fd5a",
    "support"
@@ -428912,6 +429065,14 @@
    "5c1758908605d71baf9fe87c9b54ccfab5c5e5cd",
    "testharness"
   ],
+  "svg/shapes/circle-01-ref.svg": [
+   "1d62e8e2af82f8da03937be22d4c3f695111edb8",
+   "support"
+  ],
+  "svg/shapes/circle-01.svg": [
+   "8eecd6621fb47d0aafc79eed5db00780220b6496",
+   "reftest"
+  ],
   "svg/shapes/ellipse-01-ref.svg": [
    "c4ab1bd03913d56166a0a54a91d3a3c03703eceb",
    "support"
@@ -428964,6 +429125,10 @@
    "1ff393beb0e558eeba328f2e0697c9bcc73c10d0",
    "reftest"
   ],
+  "svg/shapes/ellipse-09.svg": [
+   "77e3f3fe70bbc1655942353bdc719e7ffac46ba0",
+   "reftest"
+  ],
   "svg/shapes/line-dasharray-ref.svg": [
    "5b1caaa8bc732191433f478da5162c07b266d757",
    "support"
@@ -429012,6 +429177,14 @@
    "37c4c9b2ab59238f9ff1339ac31e1eb1c1f4685b",
    "reftest"
   ],
+  "svg/shapes/rect-05-ref.svg": [
+   "1d62e8e2af82f8da03937be22d4c3f695111edb8",
+   "support"
+  ],
+  "svg/shapes/rect-05.svg": [
+   "27d01efc64b9345f7deaeb6960c3d4b7ce8386b1",
+   "reftest"
+  ],
   "svg/shapes/reftests/pathlength-001-ref.svg": [
    "0ec9e0353ae4bcdf12acbdfe0e3aa85c22565054",
    "support"
@@ -429449,7 +429622,7 @@
    "testharness"
   ],
   "touch-events/idlharness.window-expected.txt": [
-   "610536241ea584ec951f8f93798739f0dce704a3",
+   "8ac9fbeb9c574d441a29bb53d936e135c29fbb7f",
    "support"
   ],
   "touch-events/idlharness.window.js": [
@@ -432013,7 +432186,7 @@
    "support"
   ],
   "webaudio/idlharness.https.window-expected.txt": [
-   "64ec9f4302453321fba932e2a2e8fd5f6fc48d7a",
+   "1e99acda1386d360603d7fc5ed3f506a04b9bc2c",
    "support"
   ],
   "webaudio/idlharness.https.window.js": [
@@ -433609,7 +433782,7 @@
    "support"
   ],
   "webmidi/idlharness.https.window-expected.txt": [
-   "c2d675a6233a1ba9ffb23bea0408018149d53f17",
+   "85db0f6a3d1aca55117e386a8305728747103d32",
    "support"
   ],
   "webmidi/idlharness.https.window.js": [
@@ -434217,7 +434390,7 @@
    "testharness"
   ],
   "webrtc/RTCRtpTransceiver.https-expected.txt": [
-   "429c3ca75e4571edcddad7247878cacd846a1a9c",
+   "09b20d29848db8b5d2ed8d0de5e5431f194e07b8",
    "support"
   ],
   "webrtc/RTCRtpTransceiver.https.html": [
@@ -438865,7 +439038,7 @@
    "support"
   ],
   "webxr/idlharness.https.window-expected.txt": [
-   "794ad858937207b7b438a3d9764e0018a2c7ca72",
+   "2528268adbdf0d79fa4f072caff9f76bea547abf",
    "support"
   ],
   "webxr/idlharness.https.window.js": [
@@ -441121,11 +441294,11 @@
    "testharness"
   ],
   "xhr/idlharness.any.sharedworker-expected.txt": [
-   "a388bd716506badb035b9eb9bd4fd99542e88561",
+   "50788e8c4785fc44f06fad8e5541710990a0f94f",
    "support"
   ],
   "xhr/idlharness.any.worker-expected.txt": [
-   "a388bd716506badb035b9eb9bd4fd99542e88561",
+   "50788e8c4785fc44f06fad8e5541710990a0f94f",
    "support"
   ],
   "xhr/loadstart-and-state.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex-rename-abort.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex-rename-abort.html
index b14d301..b61988e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex-rename-abort.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbindex-rename-abort.html
@@ -39,9 +39,8 @@
             'versionchange transaction is aborted');
 
         const request = indexedDB.open(dbName, 1);
-        return requestWatcher(testCase, request).wait_for('success');
-    }).then(event => {
-        const database = event.target.result;
+        return promiseForRequest(testCase, request);
+    }).then(database => {
         const transaction = database.transaction('books', 'readonly');
         const store = transaction.objectStore('books');
         assert_array_equals(
@@ -95,9 +94,8 @@
             'versionchange transaction is aborted');
 
         const request = indexedDB.open(dbName, 1);
-        return requestWatcher(testCase, request).wait_for('success');
-    }).then(event => {
-        const database = event.target.result;
+        return promiseForRequest(testCase, request);
+    }).then(database => {
         const transaction = database.transaction('not_books', 'readonly');
         const store = transaction.objectStore('not_books');
         assert_array_equals(
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore-rename-abort.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore-rename-abort.html
index 6e16c31e..75893cd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore-rename-abort.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbobjectstore-rename-abort.html
@@ -40,9 +40,8 @@
                 'IDBObjectStore.name should not reflect the rename any more ' +
                 'after the versionchange transaction is aborted');
         const request = indexedDB.open(dbName, 1);
-        return requestWatcher(testCase, request).wait_for('success');
-    }).then(event => {
-        const database = event.target.result;
+        return promiseForRequest(testCase, request);
+    }).then(database => {
         assert_array_equals(
             database.objectStoreNames, ['books'],
             'IDBDatabase.objectStoreNames should not reflect the rename ' +
@@ -107,9 +106,8 @@
             'should be empty after the versionchange transaction is aborted ' +
             'returns');
         const request = indexedDB.open(dbName, 1);
-        return requestWatcher(testCase, request).wait_for('success');
-    }).then(event => {
-        const database = event.target.result;
+        return promiseForRequest(testCase, request);
+    }).then(database => {
         assert_array_equals(
             database.objectStoreNames, [],
             'IDBDatabase.objectStoreNames should not reflect the creation or ' +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-common.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-common.js
new file mode 100644
index 0000000..45c8ffe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-common.js
@@ -0,0 +1,93 @@
+// Returns the "name" property written to the object with the given ID.
+function nameForId(id) {
+  return `Object ${id}`;
+}
+
+// Initial database setup used by all the reading-autoincrement tests.
+async function setupAutoincrementDatabase(testCase) {
+  const database = await createDatabase(testCase, database => {
+    const store = database.createObjectStore(
+        'store', { autoIncrement: true, keyPath: 'id' });
+    store.createIndex('by_name', 'name', { unique: true });
+    store.createIndex('by_id', 'id', { unique: true });
+
+    // Cover writing from the initial upgrade transaction.
+    for (let i = 1; i <= 16; ++i) {
+      if (i % 2 == 0) {
+        store.put({name: nameForId(i), id: i});
+      } else {
+        store.put({name: nameForId(i)});
+      }
+    }
+  });
+
+  // Cover writing from a subsequent transaction.
+  const transaction = database.transaction(['store'], 'readwrite');
+  const store = transaction.objectStore('store');
+  for (let i = 17; i <= 32; ++i) {
+    if (i % 2 == 0) {
+      store.put({name: nameForId(i), id: i});
+    } else {
+      store.put({name: nameForId(i)});
+    }
+  }
+  await promiseForTransaction(testCase, transaction);
+
+  return database;
+}
+
+// Returns the IDs used by the object store, sorted as strings.
+//
+// This is used to determine the correct order of records when retrieved from an
+// index that uses stringified IDs.
+function idsSortedByStringCompare() {
+  const stringIds = [];
+  for (let i = 1; i <= 32; ++i)
+    stringIds.push(i);
+  stringIds.sort((a, b) => indexedDB.cmp(`${a}`, `${b}`));
+  return stringIds;
+}
+
+async function iterateCursor(testCase, cursorRequest, callback) {
+  // This uses requestWatcher() directly instead of using promiseForRequest()
+  // inside the loop to avoid creating multiple EventWatcher instances. In turn,
+  // this avoids ending up with O(N) listeners for the request and O(N^2)
+  // dispatched events.
+  const eventWatcher = requestWatcher(testCase, cursorRequest);
+  while (true) {
+    const event = await eventWatcher.wait_for('success');
+    const cursor = event.target.result;
+    if (cursor === null)
+      return;
+    callback(cursor);
+    cursor.continue();
+  }
+}
+
+// Returns equivalent information to getAllKeys() by iterating a cursor.
+//
+// Returns an array with one dictionary per entry in the source. The dictionary
+// has the properties "key" and "primaryKey".
+async function getAllKeysViaCursor(testCase, cursorSource) {
+  const results = [];
+  await iterateCursor(testCase, cursorSource.openKeyCursor(), cursor => {
+    results.push({ key: cursor.key, primaryKey: cursor.primaryKey });
+  });
+  return results;
+}
+
+// Returns equivalent information to getAll() by iterating a cursor.
+//
+// Returns an array with one dictionary per entry in the source. The dictionary
+// has the properties "key", "primaryKey" and "value".
+async function getAllViaCursor(testCase, cursorSource) {
+  const results = [];
+  await iterateCursor(testCase, cursorSource.openCursor(), cursor => {
+    results.push({
+      key: cursor.key,
+      primaryKey: cursor.primaryKey,
+      value: cursor.value,
+    });
+  });
+  return results;
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-indexes-cursors.any.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-indexes-cursors.any.js
new file mode 100644
index 0000000..d793876
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-indexes-cursors.any.js
@@ -0,0 +1,88 @@
+// META: global=window,dedicatedworker,sharedworker,serviceworker
+// META: script=../support-promises.js
+// META: script=./reading-autoincrement-common.js
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_id');
+
+  const result = await getAllViaCursor(testCase, index);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].key, i, 'Autoincrement index key');
+    assert_equals(result[i - 1].primaryKey, i, 'Autoincrement primary key');
+    assert_equals(result[i - 1].value.id, i, 'Autoincrement key in value');
+    assert_equals(result[i - 1].value.name, nameForId(i),
+                  'String property in value');
+  }
+
+  database.close();
+}, 'IDBIndex.openCursor() iterates over an index on the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_id');
+
+  const result = await getAllKeysViaCursor(testCase, index);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].key, i, 'Autoincrement index key');
+    assert_equals(result[i - 1].primaryKey, i, 'Autoincrement primary key');
+  }
+
+  database.close();
+}, 'IDBIndex.openKeyCursor() iterates over an index on the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_name');
+
+  const stringSortedIds = idsSortedByStringCompare();
+
+  const result = await getAllViaCursor(testCase, index);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].key, nameForId(stringSortedIds[i - 1]),
+                  'Index key');
+    assert_equals(result[i - 1].primaryKey, stringSortedIds[i - 1],
+                  'Autoincrement primary key');
+    assert_equals(result[i - 1].value.id, stringSortedIds[i - 1],
+                  'Autoincrement key in value');
+    assert_equals(result[i - 1].value.name, nameForId(stringSortedIds[i - 1]),
+                  'String property in value');
+  }
+
+  database.close();
+}, 'IDBIndex.openCursor() iterates over an index not covering the ' +
+   'autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_name');
+
+  const stringSortedIds = idsSortedByStringCompare();
+
+  const result = await getAllKeysViaCursor(testCase, index);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].key, nameForId(stringSortedIds[i - 1]),
+                  'Index key');
+    assert_equals(result[i - 1].primaryKey, stringSortedIds[i - 1],
+                  'Autoincrement primary key');
+  }
+
+  database.close();
+}, 'IDBIndex.openKeyCursor() iterates over an index not covering the ' +
+   'autoincrement key');
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-indexes.any.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-indexes.any.js
new file mode 100644
index 0000000..d945b78
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-indexes.any.js
@@ -0,0 +1,108 @@
+// META: global=window,dedicatedworker,sharedworker,serviceworker
+// META: script=../support-promises.js
+// META: script=./reading-autoincrement-common.js
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_id');
+  const request = index.getAll();
+  const result = await promiseForRequest(testCase, request);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].id, i, 'Autoincrement key');
+    assert_equals(result[i - 1].name, nameForId(i), 'String property');
+  }
+
+  database.close();
+}, 'IDBIndex.getAll() for an index on the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_id');
+  const request = index.getAllKeys();
+  const result = await promiseForRequest(testCase, request);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i)
+    assert_equals(result[i - 1], i, 'Autoincrement key');
+
+  database.close();
+}, 'IDBIndex.getAllKeys() for an index on the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_id');
+
+  for (let i = 1; i <= 32; ++i) {
+    const request = index.get(i);
+    const result = await promiseForRequest(testCase, request);
+    assert_equals(result.id, i, 'autoincrement key');
+    assert_equals(result.name, nameForId(i), 'string property');
+  }
+
+  database.close();
+}, 'IDBIndex.get() for an index on the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const stringSortedIds = idsSortedByStringCompare();
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_name');
+  const request = index.getAll();
+  const result = await promiseForRequest(testCase, request);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].id, stringSortedIds[i - 1],
+                  'autoincrement key');
+    assert_equals(result[i - 1].name, nameForId(stringSortedIds[i - 1]),
+                  'string property');
+  }
+
+  database.close();
+}, 'IDBIndex.getAll() for an index not covering the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const stringSortedIds = idsSortedByStringCompare();
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_name');
+  const request = index.getAllKeys();
+  const result = await promiseForRequest(testCase, request);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i)
+    assert_equals(result[i - 1], stringSortedIds[i - 1], 'String property');
+
+  database.close();
+}, 'IDBIndex.getAllKeys() returns correct result for an index not covering ' +
+   'the autoincrement key');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const index = store.index('by_name');
+
+  for (let i = 1; i <= 32; ++i) {
+    const request = index.get(nameForId(i));
+    const result = await promiseForRequest(testCase, request);
+    assert_equals(result.id, i, 'Autoincrement key');
+    assert_equals(result.name, nameForId(i), 'String property');
+  }
+
+  database.close();
+}, 'IDBIndex.get() for an index not covering the autoincrement key');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-store-cursors.any.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-store-cursors.any.js
new file mode 100644
index 0000000..05971098
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-store-cursors.any.js
@@ -0,0 +1,38 @@
+// META: global=window,dedicatedworker,sharedworker,serviceworker
+// META: script=../support-promises.js
+// META: script=./reading-autoincrement-common.js
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+
+  const result = await getAllViaCursor(testCase, store);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].key, i, 'Autoincrement key');
+    assert_equals(result[i - 1].primaryKey, i, 'Autoincrement primary key');
+    assert_equals(result[i - 1].value.id, i, 'Autoincrement key in value');
+    assert_equals(result[i - 1].value.name, nameForId(i),
+                  'string property in value');
+  }
+
+  database.close();
+}, 'IDBObjectStore.openCursor() iterates over an autoincrement store');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+
+  const result = await getAllKeysViaCursor(testCase, store);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].key, i, 'Incorrect autoincrement key');
+    assert_equals(result[i - 1].primaryKey, i, 'Incorrect primary key');
+  }
+
+  database.close();
+}, 'IDBObjectStore.openKeyCursor() iterates over an autoincrement store');
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-store.any.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-store.any.js
new file mode 100644
index 0000000..bbba6a33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/key-generators/reading-autoincrement-store.any.js
@@ -0,0 +1,49 @@
+// META: global=window,dedicatedworker,sharedworker,serviceworker
+// META: script=../support-promises.js
+// META: script=./reading-autoincrement-common.js
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const request = store.getAll();
+  const result = await promiseForRequest(testCase, request);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i) {
+    assert_equals(result[i - 1].id, i, 'Autoincrement key');
+    assert_equals(result[i - 1].name, nameForId(i), 'String property');
+  }
+
+  database.close();
+}, 'IDBObjectStore.getAll() for an autoincrement store');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+  const request = store.getAllKeys();
+  const result = await promiseForRequest(testCase, request);
+  assert_equals(result.length, 32);
+  for (let i = 1; i <= 32; ++i)
+    assert_equals(result[i - 1], i, 'Autoincrement key');
+
+  database.close();
+}, 'IDBObjectStore.getAllKeys() for an autoincrement store');
+
+promise_test(async testCase => {
+  const database = await setupAutoincrementDatabase(testCase);
+
+  const transaction = database.transaction(['store'], 'readonly');
+  const store = transaction.objectStore('store');
+
+  for (let i = 1; i <= 32; ++i) {
+    const request = store.get(i);
+    const result = await promiseForRequest(testCase, request);
+    assert_equals(result.id, i, 'Autoincrement key');
+    assert_equals(result.name, nameForId(i), 'String property');
+  }
+
+  database.close();
+}, 'IDBObjectStore.get() for an autoincrement store');
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support-promises.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support-promises.js
index d320ba0..433af50 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support-promises.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/support-promises.js
@@ -5,11 +5,39 @@
   return 'db' + self.location.pathname + '-' + testCase.name;
 }
 
-// Creates an EventWatcher covering all the events that can be issued by
-// IndexedDB requests and transactions.
+// EventWatcher covering all the events defined on IndexedDB requests.
+//
+// The events cover IDBRequest and IDBOpenDBRequest.
 function requestWatcher(testCase, request) {
   return new EventWatcher(testCase, request,
-      ['abort', 'blocked', 'complete', 'error', 'success', 'upgradeneeded']);
+                          ['blocked', 'error', 'success', 'upgradeneeded']);
+}
+
+// EventWatcher covering all the events defined on IndexedDB transactions.
+//
+// The events cover IDBTransaction.
+function transactionWatcher(testCase, request) {
+  return new EventWatcher(testCase, request, ['abort', 'complete', 'error']);
+}
+
+// Promise that resolves with an IDBRequest's result.
+//
+// The promise only resolves if IDBRequest receives the "success" event. Any
+// other event causes the promise to reject with an error. This is correct in
+// most cases, but insufficient for indexedDB.open(), which issues
+// "upgradeneded" events under normal operation.
+function promiseForRequest(testCase, request) {
+  const eventWatcher = requestWatcher(testCase, request);
+  return eventWatcher.wait_for('success').then(event => event.target.result);
+}
+
+// Promise that resolves when an IDBTransaction completes.
+//
+// The promise resolves with undefined if IDBTransaction receives the "complete"
+// event, and rejects with an error for any other event.
+function promiseForTransaction(testCase, request) {
+  const eventWatcher = transactionWatcher(testCase, request);
+  return eventWatcher.wait_for('complete').then(() => {});
 }
 
 // Migrates an IndexedDB database whose name is unique for the test case.
@@ -64,7 +92,7 @@
         requestEventPromise = new Promise((resolve, reject) => {
           request.onerror = event => {
             event.preventDefault();
-            resolve(event);
+            resolve(event.target.error);
           };
           request.onsuccess = () => reject(new Error(
               'indexedDB.open should not succeed for an aborted ' +
@@ -79,8 +107,7 @@
       if (!shouldBeAborted) {
         request.onerror = null;
         request.onsuccess = null;
-        requestEventPromise =
-            requestWatcher(testCase, request).wait_for('success');
+        requestEventPromise = promiseForRequest(testCase, request);
       }
 
       // requestEventPromise needs to be the last promise in the chain, because
@@ -95,12 +122,10 @@
           'indexedDB.open should not succeed without creating a ' +
           'versionchange transaction'));
     };
-  }).then(event => {
-    const database = event.target.result;
-    if (database) {
-      testCase.add_cleanup(() => { database.close(); });
-    }
-    return database || event.target.error;
+  }).then(databaseOrError => {
+    if (databaseOrError instanceof IDBDatabase)
+      testCase.add_cleanup(() => { databaseOrError.close(); });
+    return databaseOrError;
   });
 }
 
@@ -126,9 +151,7 @@
 // close the database.
 function createNamedDatabase(testCase, databaseName, setupCallback) {
   const request = indexedDB.deleteDatabase(databaseName);
-  const eventWatcher = requestWatcher(testCase, request);
-
-  return eventWatcher.wait_for('success').then(event => {
+  return promiseForRequest(testCase, request).then(() => {
     testCase.add_cleanup(() => { indexedDB.deleteDatabase(databaseName); });
     return migrateNamedDatabase(testCase, databaseName, 1, setupCallback)
   });
@@ -152,9 +175,7 @@
 // close the database.
 function openNamedDatabase(testCase, databaseName, version) {
   const request = indexedDB.open(databaseName, version);
-  const eventWatcher = requestWatcher(testCase, request);
-  return eventWatcher.wait_for('success').then(() => {
-    const database = request.result;
+  return promiseForRequest(testCase, request).then(database => {
     testCase.add_cleanup(() => { database.close(); });
     return database;
   });
@@ -215,9 +236,7 @@
 function checkStoreGenerator(testCase, store, expectedKey, errorMessage) {
   const request = store.put(
       { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
-  const eventWatcher = requestWatcher(testCase, request);
-  return eventWatcher.wait_for('success').then(() => {
-    const result = request.result;
+  return promiseForRequest(testCase, request).then(result => {
     assert_equals(result, expectedKey, errorMessage);
   });
 }
@@ -230,9 +249,7 @@
 // is using it incorrectly.
 function checkStoreContents(testCase, store, errorMessage) {
   const request = store.get(123456);
-  const eventWatcher = requestWatcher(testCase, request);
-  return eventWatcher.wait_for('success').then(() => {
-    const result = request.result;
+  return promiseForRequest(testCase, request).then(result => {
     assert_equals(result.isbn, BOOKS_RECORD_DATA[0].isbn, errorMessage);
     assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
     assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
@@ -247,9 +264,7 @@
 // is using it incorrectly.
 function checkAuthorIndexContents(testCase, index, errorMessage) {
   const request = index.get(BOOKS_RECORD_DATA[2].author);
-  const eventWatcher = requestWatcher(testCase, request);
-  return eventWatcher.wait_for('success').then(() => {
-    const result = request.result;
+  return promiseForRequest(testCase, request).then(result => {
     assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
     assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
   });
@@ -263,9 +278,7 @@
 // is using it incorrectly.
 function checkTitleIndexContents(testCase, index, errorMessage) {
   const request = index.get(BOOKS_RECORD_DATA[2].title);
-  const eventWatcher = requestWatcher(testCase, request);
-  return eventWatcher.wait_for('success').then(() => {
-    const result = request.result;
+  return promiseForRequest(testCase, request).then(result => {
     assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
     assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
   });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/bluetooth/idl/idlharness.tentative.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/bluetooth/idl/idlharness.tentative.https.window-expected.txt
index 4a16e4f..e5d18e75c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/bluetooth/idl/idlharness.tentative.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/bluetooth/idl/idlharness.tentative.https.window-expected.txt
@@ -179,6 +179,5 @@
 PASS BluetoothUUID interface: operation canonicalUUID(unsigned long)
 PASS Navigator interface: attribute bluetooth
 PASS Navigator interface: navigator must inherit property "bluetooth" with the proper type
-PASS WorkerNavigator interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/compat/idlharness.window-expected.txt
index 0104eb3..6deefcc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/compat/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/compat/idlharness.window-expected.txt
@@ -8,6 +8,5 @@
 FAIL Window interface: attribute onorientationchange assert_own_property: The global object must have a property "onorientationchange" expected property "onorientationchange" missing
 FAIL Window interface: window must inherit property "orientation" with the proper type assert_own_property: expected property "orientation" missing
 FAIL Window interface: window must inherit property "onorientationchange" with the proper type assert_own_property: expected property "onorientationchange" missing
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/idlharness-expected.txt
deleted file mode 100644
index 50b4cddb..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/idlharness-expected.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-This is a testharness.js-based test.
-Found 71 tests; 62 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS idl_test setup
-PASS Partial interface CSSRule: original interface defined
-PASS Partial interface mixin GlobalEventHandlers: original interface mixin defined
-PASS AnimationEvent interface: existence and properties of interface object
-PASS AnimationEvent interface object length
-PASS AnimationEvent interface object name
-PASS AnimationEvent interface: existence and properties of interface prototype object
-PASS AnimationEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS AnimationEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS AnimationEvent interface: attribute animationName
-PASS AnimationEvent interface: attribute elapsedTime
-PASS AnimationEvent interface: attribute pseudoElement
-PASS AnimationEvent must be primary interface of new AnimationEvent("animationstart")
-PASS Stringification of new AnimationEvent("animationstart")
-PASS AnimationEvent interface: new AnimationEvent("animationstart") must inherit property "animationName" with the proper type
-PASS AnimationEvent interface: new AnimationEvent("animationstart") must inherit property "elapsedTime" with the proper type
-PASS AnimationEvent interface: new AnimationEvent("animationstart") must inherit property "pseudoElement" with the proper type
-PASS CSSKeyframeRule interface: existence and properties of interface object
-PASS CSSKeyframeRule interface object length
-PASS CSSKeyframeRule interface object name
-PASS CSSKeyframeRule interface: existence and properties of interface prototype object
-PASS CSSKeyframeRule interface: existence and properties of interface prototype object's "constructor" property
-PASS CSSKeyframeRule interface: existence and properties of interface prototype object's @@unscopables property
-PASS CSSKeyframeRule interface: attribute keyText
-PASS CSSKeyframeRule interface: attribute style
-PASS CSSKeyframeRule must be primary interface of keyframes.cssRules[0]
-PASS Stringification of keyframes.cssRules[0]
-PASS CSSKeyframeRule interface: keyframes.cssRules[0] must inherit property "keyText" with the proper type
-PASS CSSKeyframeRule interface: keyframes.cssRules[0] must inherit property "style" with the proper type
-PASS CSSRule interface: keyframes.cssRules[0] must inherit property "KEYFRAMES_RULE" with the proper type
-PASS CSSRule interface: keyframes.cssRules[0] must inherit property "KEYFRAME_RULE" with the proper type
-PASS CSSKeyframesRule interface: existence and properties of interface object
-PASS CSSKeyframesRule interface object length
-PASS CSSKeyframesRule interface object name
-PASS CSSKeyframesRule interface: existence and properties of interface prototype object
-PASS CSSKeyframesRule interface: existence and properties of interface prototype object's "constructor" property
-PASS CSSKeyframesRule interface: existence and properties of interface prototype object's @@unscopables property
-PASS CSSKeyframesRule interface: attribute name
-PASS CSSKeyframesRule interface: attribute cssRules
-PASS CSSKeyframesRule interface: operation appendRule(CSSOMString)
-PASS CSSKeyframesRule interface: operation deleteRule(CSSOMString)
-PASS CSSKeyframesRule interface: operation findRule(CSSOMString)
-PASS CSSKeyframesRule must be primary interface of keyframes
-PASS Stringification of keyframes
-PASS CSSKeyframesRule interface: keyframes must inherit property "name" with the proper type
-PASS CSSKeyframesRule interface: keyframes must inherit property "cssRules" with the proper type
-PASS CSSKeyframesRule interface: keyframes must inherit property "appendRule(CSSOMString)" with the proper type
-PASS CSSKeyframesRule interface: calling appendRule(CSSOMString) on keyframes with too few arguments must throw TypeError
-PASS CSSKeyframesRule interface: keyframes must inherit property "deleteRule(CSSOMString)" with the proper type
-PASS CSSKeyframesRule interface: calling deleteRule(CSSOMString) on keyframes with too few arguments must throw TypeError
-PASS CSSKeyframesRule interface: keyframes must inherit property "findRule(CSSOMString)" with the proper type
-PASS CSSKeyframesRule interface: calling findRule(CSSOMString) on keyframes with too few arguments must throw TypeError
-PASS CSSRule interface: keyframes must inherit property "KEYFRAMES_RULE" with the proper type
-PASS CSSRule interface: keyframes must inherit property "KEYFRAME_RULE" with the proper type
-FAIL HTMLElement interface: attribute onanimationstart assert_true: The prototype object must have a property "onanimationstart" expected true got false
-FAIL HTMLElement interface: attribute onanimationiteration assert_true: The prototype object must have a property "onanimationiteration" expected true got false
-FAIL HTMLElement interface: attribute onanimationend assert_true: The prototype object must have a property "onanimationend" expected true got false
-FAIL HTMLElement interface: attribute onanimationcancel assert_true: The prototype object must have a property "onanimationcancel" expected true got false
-PASS Window interface: attribute onanimationstart
-PASS Window interface: attribute onanimationiteration
-PASS Window interface: attribute onanimationend
-FAIL Window interface: attribute onanimationcancel assert_own_property: The global object must have a property "onanimationcancel" expected property "onanimationcancel" missing
-PASS WorkerGlobalScope interface: existence and properties of interface object
-FAIL Document interface: attribute onanimationstart assert_true: The prototype object must have a property "onanimationstart" expected true got false
-FAIL Document interface: attribute onanimationiteration assert_true: The prototype object must have a property "onanimationiteration" expected true got false
-FAIL Document interface: attribute onanimationend assert_true: The prototype object must have a property "onanimationend" expected true got false
-FAIL Document interface: attribute onanimationcancel assert_true: The prototype object must have a property "onanimationcancel" expected true got false
-PASS CSSRule interface: constant KEYFRAMES_RULE on interface object
-PASS CSSRule interface: constant KEYFRAMES_RULE on interface prototype object
-PASS CSSRule interface: constant KEYFRAME_RULE on interface object
-PASS CSSRule interface: constant KEYFRAME_RULE on interface prototype object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt
index 002bd39..f188afc0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt
@@ -32,6 +32,5 @@
 PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "y" with the proper type
 PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "width" with the proper type
 PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "height" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/registered-property-computation.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/registered-property-computation.html
index 180cdf60..855d9f3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/registered-property-computation.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/registered-property-computation.html
@@ -147,5 +147,12 @@
         assert_computed_value('<angle>', '400grad', '360deg');
         assert_computed_value('<angle>', 'calc(360deg + 400grad)', '720deg');
     }, "<angle> values computed correctly for " + id);
+
+    test(function() {
+        assert_computed_value('*', '50s', '50s');
+        assert_computed_value('<time>', '1s', '1s');
+        assert_computed_value('<time>', '1000ms', '1s');
+        assert_computed_value('<time>', 'calc(1000ms + 1s)', '2s');
+    }, "<time> values computed correctly for " + id);
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/idlharness-expected.txt
index 8b356c83..4ccc625 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/idlharness-expected.txt
@@ -32,6 +32,5 @@
 FAIL Window interface: operation getPseudoElements(Element, CSSOMString) assert_own_property: global object missing non-static operation expected property "getPseudoElements" missing
 FAIL Window interface: window must inherit property "getPseudoElements(Element, CSSOMString)" with the proper type assert_own_property: expected property "getPseudoElements" missing
 FAIL Window interface: calling getPseudoElements(Element, CSSOMString) on window with too few arguments must throw TypeError assert_own_property: expected property "getPseudoElements" missing
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transforms/inheritance-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transforms/inheritance-expected.txt
new file mode 100644
index 0000000..7862d8b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transforms/inheritance-expected.txt
@@ -0,0 +1,23 @@
+This is a testharness.js-based test.
+PASS Property backface-visibility has initial value visible
+PASS Property backface-visibility does not inherit
+PASS Property perspective has initial value none
+PASS Property perspective does not inherit
+PASS Property perspective-origin has initial value 30px 20px
+PASS Property perspective-origin does not inherit
+PASS Property rotate has initial value none
+PASS Property rotate does not inherit
+PASS Property scale has initial value none
+PASS Property scale does not inherit
+PASS Property transform has initial value none
+PASS Property transform does not inherit
+PASS Property transform-box has initial value view-box
+PASS Property transform-box does not inherit
+PASS Property transform-origin has initial value 30px 20px
+PASS Property transform-origin does not inherit
+FAIL Property transform-style has initial value auto assert_equals: expected "auto" but got "flat"
+PASS Property transform-style does not inherit
+PASS Property translate has initial value none
+PASS Property translate does not inherit
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transforms/inheritance.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transforms/inheritance.html
new file mode 100644
index 0000000..2bc0cf5c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transforms/inheritance.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Inheritance of CSS Transforms properties</title>
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#property-index">
+<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#property-index">
+<meta name="assert" content="Properties inherit or not according to the spec.">
+<meta name="assert" content="Properties have initial values according to the spec.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/inheritance-testcommon.js"></script>
+</head>
+<body>
+<div id="container">
+<div id="target"></div>
+</div>
+<style>
+#container {
+  width: 70px;
+  height: 90px;
+}
+#target {
+  width: 60px;
+  height: 40px;
+}
+</style>
+<script>
+assert_not_inherited('backface-visibility', 'visible', 'hidden');
+assert_not_inherited('perspective', 'none', '7px');
+assert_not_inherited('perspective-origin', '30px 20px', '8px 9px'); // '50% 50%' is '30px 20px'
+assert_not_inherited('rotate', 'none', '90deg');
+assert_not_inherited('scale', 'none', '10 11 12');
+assert_not_inherited('transform', 'none', 'matrix(2, 0, 0, 3, 1, 4)');
+assert_not_inherited('transform-box', 'view-box', 'fill-box');
+assert_not_inherited('transform-origin', '30px 20px', '5px 6px'); // '50% 50%' is '30px 20px'
+assert_not_inherited('transform-style', 'auto', 'preserve-3d');
+assert_not_inherited('translate', 'none', '13px 14px 15px');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/idlharness-expected.txt
deleted file mode 100644
index 74256a1..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/idlharness-expected.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS Partial interface GlobalEventHandlers: original interface defined
-PASS TransitionEvent interface: existence and properties of interface object
-PASS TransitionEvent interface object length
-PASS TransitionEvent interface object name
-PASS TransitionEvent interface: existence and properties of interface prototype object
-PASS TransitionEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS TransitionEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS TransitionEvent interface: attribute propertyName
-PASS TransitionEvent interface: attribute elapsedTime
-PASS TransitionEvent interface: attribute pseudoElement
-PASS TransitionEvent must be primary interface of new TransitionEvent("transitionend")
-PASS Stringification of new TransitionEvent("transitionend")
-PASS TransitionEvent interface: new TransitionEvent("transitionend") must inherit property "propertyName" with the proper type
-PASS TransitionEvent interface: new TransitionEvent("transitionend") must inherit property "elapsedTime" with the proper type
-PASS TransitionEvent interface: new TransitionEvent("transitionend") must inherit property "pseudoElement" with the proper type
-FAIL HTMLElement interface: attribute ontransitionrun assert_true: The prototype object must have a property "ontransitionrun" expected true got false
-FAIL HTMLElement interface: attribute ontransitionstart assert_true: The prototype object must have a property "ontransitionstart" expected true got false
-FAIL HTMLElement interface: attribute ontransitionend assert_true: The prototype object must have a property "ontransitionend" expected true got false
-FAIL HTMLElement interface: attribute ontransitioncancel assert_true: The prototype object must have a property "ontransitioncancel" expected true got false
-FAIL HTMLElement interface: document must inherit property "ontransitionrun" with the proper type assert_inherits: property "ontransitionrun" not found in prototype chain
-FAIL HTMLElement interface: document must inherit property "ontransitionstart" with the proper type assert_inherits: property "ontransitionstart" not found in prototype chain
-FAIL HTMLElement interface: document must inherit property "ontransitionend" with the proper type assert_inherits: property "ontransitionend" not found in prototype chain
-FAIL HTMLElement interface: document must inherit property "ontransitioncancel" with the proper type assert_inherits: property "ontransitioncancel" not found in prototype chain
-FAIL Window interface: attribute ontransitionrun assert_own_property: The global object must have a property "ontransitionrun" expected property "ontransitionrun" missing
-FAIL Window interface: attribute ontransitionstart assert_own_property: The global object must have a property "ontransitionstart" expected property "ontransitionstart" missing
-PASS Window interface: attribute ontransitionend
-FAIL Window interface: attribute ontransitioncancel assert_own_property: The global object must have a property "ontransitioncancel" expected property "ontransitioncancel" missing
-FAIL Window interface: window must inherit property "ontransitionrun" with the proper type assert_own_property: expected property "ontransitionrun" missing
-FAIL Window interface: window must inherit property "ontransitionstart" with the proper type assert_own_property: expected property "ontransitionstart" missing
-PASS Window interface: window must inherit property "ontransitionend" with the proper type
-FAIL Window interface: window must inherit property "ontransitioncancel" with the proper type assert_own_property: expected property "ontransitioncancel" missing
-PASS WorkerGlobalScope interface: existence and properties of interface object
-FAIL Document interface: attribute ontransitionrun assert_true: The prototype object must have a property "ontransitionrun" expected true got false
-FAIL Document interface: attribute ontransitionstart assert_true: The prototype object must have a property "ontransitionstart" expected true got false
-FAIL Document interface: attribute ontransitionend assert_true: The prototype object must have a property "ontransitionend" expected true got false
-FAIL Document interface: attribute ontransitioncancel assert_true: The prototype object must have a property "ontransitioncancel" expected true got false
-FAIL Document interface: document must inherit property "ontransitionrun" with the proper type assert_inherits: property "ontransitionrun" not found in prototype chain
-FAIL Document interface: document must inherit property "ontransitionstart" with the proper type assert_inherits: property "ontransitionstart" not found in prototype chain
-FAIL Document interface: document must inherit property "ontransitionend" with the proper type assert_inherits: property "ontransitionend" not found in prototype chain
-FAIL Document interface: document must inherit property "ontransitioncancel" with the proper type assert_inherits: property "ontransitioncancel" not found in prototype chain
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt
index 7c325976..20b1327 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 439 tests; 406 PASS, 33 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 436 tests; 405 PASS, 31 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Element: original interface defined
 PASS Partial interface CSSStyleRule: original interface defined
@@ -453,9 +453,6 @@
 PASS CSS namespace: operation dpcm(double)
 PASS CSS namespace: operation dppx(double)
 PASS CSS namespace: operation fr(double)
-FAIL SVGElement interface: attribute attributeStyleMap assert_own_property: expected property "attributeStyleMap" missing
-FAIL HTMLElement interface: attribute attributeStyleMap assert_own_property: expected property "attributeStyleMap" missing
-PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS Element interface: operation computedStyleMap()
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt
index 97749137..62a5805 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 326 tests; 247 PASS, 79 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 325 tests; 246 PASS, 79 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Window: original interface defined
 PASS Partial interface Document: original interface defined
@@ -233,7 +233,6 @@
 PASS Window interface: window must inherit property "outerWidth" with the proper type
 PASS Window interface: window must inherit property "outerHeight" with the proper type
 PASS Window interface: window must inherit property "devicePixelRatio" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS Document interface: operation elementFromPoint(double, double)
 PASS Document interface: operation elementsFromPoint(double, double)
 FAIL Document interface: operation caretPositionFromPoint(double, double) assert_own_property: interface prototype object missing non-static operation expected property "caretPositionFromPoint" missing
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
index 706e87a3..a83ae3f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 377 tests; 322 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 376 tests; 321 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface Window: original interface defined
@@ -371,7 +371,6 @@
 PASS Window interface: operation getComputedStyle(Element, CSSOMString)
 PASS Window interface: window must inherit property "getComputedStyle(Element, CSSOMString)" with the proper type
 PASS Window interface: calling getComputedStyle(Element, CSSOMString) on window with too few arguments must throw TypeError
-PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS Document interface: attribute styleSheets
 PASS Document interface: document must inherit property "styleSheets" with the proper type
 PASS Document interface: new Document() must inherit property "styleSheets" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/motion/inheritance.html b/third_party/WebKit/LayoutTests/external/wpt/css/motion/inheritance.html
new file mode 100644
index 0000000..8af4f9b9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/motion/inheritance.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Inheritance of CSS Motion Path properties</title>
+<link rel="help" href="https://drafts.fxtf.org/motion-1/#property-index">
+<meta name="assert" content="Properties inherit or not according to the spec.">
+<meta name="assert" content="Properties have initial values according to the spec.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/inheritance-testcommon.js"></script>
+</head>
+<body>
+<div id="container">
+<div id="target"></div>
+</div>
+<script>
+assert_not_inherited('offset-anchor', 'auto', '2px 3px');
+assert_not_inherited('offset-distance', '0px', '4px');
+assert_not_inherited('offset-path', 'none', 'path("M 5 6 H 7")');
+assert_not_inherited('offset-position', 'auto', '8px 9px');
+assert_not_inherited('offset-rotate', 'auto 0deg', '90deg');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/support/computed-testcommon.js b/third_party/WebKit/LayoutTests/external/wpt/css/support/computed-testcommon.js
new file mode 100644
index 0000000..0999418e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/support/computed-testcommon.js
@@ -0,0 +1,22 @@
+'use strict';
+
+/**
+ * Create test that a CSS property computes to the expected value.
+ * The document element #target is used to perform the test.
+ *
+ * @param {string} property  The name of the CSS property being tested.
+ * @param {string} specified A specified value for the property.
+ * @param {string} computed  The expected computed value. If omitted,
+                             defaults to specified.
+ */
+function test_computed_value(property, specified, computed) {
+  if (!computed)
+    computed = specified;
+  test(() => {
+    if (!getComputedStyle(target)[property])
+      return;
+    target.style[property] = '';
+    target.style[property] = specified;
+    assert_equals(getComputedStyle(target)[property], computed);
+  }, "Property " + property + " value '" + specified + "' computes to '" + computed + "'");
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt
index 33ba630..41fe5fad 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces_exclude=Node-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1103 tests; 1079 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1102 tests; 1078 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
 PASS Partial interface Window: original interface defined
 PASS Event interface: existence and properties of interface object
@@ -1102,6 +1102,5 @@
 PASS DOMTokenList interface: calling supports(DOMString) on document.body.classList with too few arguments must throw TypeError
 PASS DOMTokenList interface: document.body.classList must inherit property "value" with the proper type
 FAIL Window interface: attribute event assert_true: property should be enumerable expected true got false
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt
index a7bebc63..ac6137d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt
@@ -11,16 +11,10 @@
 FAIL Stringification of new XMLSerializer() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: XMLSerializer is not defined"
 FAIL XMLSerializer interface: new XMLSerializer() must not have property "serializeToString" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: XMLSerializer is not defined"
 PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
 PASS Element interface: existence and properties of interface object
 FAIL Element interface: document.createElement("div") must not have property "innerHTML" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: document is not defined"
 FAIL Element interface: document.createElement("div") must not have property "outerHTML" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: document is not defined"
 FAIL Element interface: document.createElement("div") must not have property "insertAdjacentHTML" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: document is not defined"
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 PASS AbstractRange interface: existence and properties of interface object
 PASS Range interface: existence and properties of interface object
 FAIL Range interface: new Range() must not have property "createContextualFragment" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Range is not defined"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/idlharness.window-expected.txt
index c4a5606..71a041e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/idlharness.window-expected.txt
@@ -20,7 +20,6 @@
 FAIL FeaturePolicyViolationReportBody interface: attribute columnNumber assert_own_property: self does not have own property "FeaturePolicyViolationReportBody" expected property "FeaturePolicyViolationReportBody" missing
 FAIL FeaturePolicyViolationReportBody interface: attribute disposition assert_own_property: self does not have own property "FeaturePolicyViolationReportBody" expected property "FeaturePolicyViolationReportBody" missing
 PASS HTMLIFrameElement interface: attribute policy
-PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS Document interface: attribute policy
 PASS Document interface: document must inherit property "policy" with the proper type
 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any-expected.txt
index b013c5c..c0f63b02 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 139 tests; 133 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 135 tests; 129 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface mixin WindowOrWorkerGlobalScope: original interface mixin defined
 PASS Headers interface: existence and properties of interface object
@@ -135,9 +135,5 @@
 PASS Response interface: new Response() must inherit property "formData()" with the proper type
 PASS Response interface: new Response() must inherit property "json()" with the proper type
 PASS Response interface: new Response() must inherit property "text()" with the proper type
-PASS Window interface: operation fetch(RequestInfo, RequestInit)
-PASS Window interface: window must inherit property "fetch(RequestInfo, RequestInit)" with the proper type
-PASS Window interface: calling fetch(RequestInfo, RequestInit) on window with too few arguments must throw TypeError
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.serviceworker-expected.txt
index cf90de4..47b60333 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.serviceworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.serviceworker-expected.txt
@@ -134,20 +134,5 @@
 PASS Response interface: new Response() must inherit property "formData()" with the proper type
 PASS Response interface: new Response() must inherit property "json()" with the proper type
 PASS Response interface: new Response() must inherit property "text()" with the proper type
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-FAIL WorkerGlobalScope interface: operation fetch(RequestInfo, RequestInit) assert_unreached: Should have rejected: calling operation with this = null didn't throw TypeError Reached unreachable code
-FAIL WorkerGlobalScope interface: self must inherit property "fetch(RequestInfo, RequestInit)" with the proper type assert_inherits: property "fetch" found on object expected in prototype chain
-FAIL WorkerGlobalScope interface: calling fetch(RequestInfo, RequestInit) on self with too few arguments must throw TypeError assert_inherits: property "fetch" found on object expected in prototype chain
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.sharedworker-expected.txt
index 20b02f1..c0f63b02 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.sharedworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.sharedworker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 150 tests; 144 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 135 tests; 129 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface mixin WindowOrWorkerGlobalScope: original interface mixin defined
 PASS Headers interface: existence and properties of interface object
@@ -135,20 +135,5 @@
 PASS Response interface: new Response() must inherit property "formData()" with the proper type
 PASS Response interface: new Response() must inherit property "json()" with the proper type
 PASS Response interface: new Response() must inherit property "text()" with the proper type
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-PASS WorkerGlobalScope interface: operation fetch(RequestInfo, RequestInit)
-PASS WorkerGlobalScope interface: self must inherit property "fetch(RequestInfo, RequestInit)" with the proper type
-PASS WorkerGlobalScope interface: calling fetch(RequestInfo, RequestInit) on self with too few arguments must throw TypeError
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.worker-expected.txt
index 20b02f1..c0f63b02 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/idl.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 150 tests; 144 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 135 tests; 129 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface mixin WindowOrWorkerGlobalScope: original interface mixin defined
 PASS Headers interface: existence and properties of interface object
@@ -135,20 +135,5 @@
 PASS Response interface: new Response() must inherit property "formData()" with the proper type
 PASS Response interface: new Response() must inherit property "json()" with the proper type
 PASS Response interface: new Response() must inherit property "text()" with the proper type
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-PASS WorkerGlobalScope interface: operation fetch(RequestInfo, RequestInit)
-PASS WorkerGlobalScope interface: self must inherit property "fetch(RequestInfo, RequestInit)" with the proper type
-PASS WorkerGlobalScope interface: calling fetch(RequestInfo, RequestInit) on self with too few arguments must throw TypeError
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.serviceworker-expected.txt
index 2d89b44..8558fae 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.serviceworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.serviceworker-expected.txt
@@ -2,19 +2,9 @@
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface WorkerGlobalScope: original interface defined
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
 FAIL WorkerGlobalScope interface: attribute addressSpace assert_true: The prototype object must have a property "addressSpace" expected true got false
 FAIL WorkerGlobalScope interface: self must inherit property "addressSpace" with the proper type assert_inherits: property "addressSpace" not found in prototype chain
-PASS HTMLFrameSetElement interface: existence and properties of interface object
 PASS Node interface: existence and properties of interface object
 PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.sharedworker-expected.txt
index 2d89b44..8558fae 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.sharedworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.sharedworker-expected.txt
@@ -2,19 +2,9 @@
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface WorkerGlobalScope: original interface defined
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
 FAIL WorkerGlobalScope interface: attribute addressSpace assert_true: The prototype object must have a property "addressSpace" expected true got false
 FAIL WorkerGlobalScope interface: self must inherit property "addressSpace" with the proper type assert_inherits: property "addressSpace" not found in prototype chain
-PASS HTMLFrameSetElement interface: existence and properties of interface object
 PASS Node interface: existence and properties of interface object
 PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.worker-expected.txt
index 2d89b44..8558fae 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.worker-expected.txt
@@ -2,19 +2,9 @@
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface WorkerGlobalScope: original interface defined
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
 FAIL WorkerGlobalScope interface: attribute addressSpace assert_true: The prototype object must have a property "addressSpace" expected true got false
 FAIL WorkerGlobalScope interface: self must inherit property "addressSpace" with the proper type assert_inherits: property "addressSpace" not found in prototype chain
-PASS HTMLFrameSetElement interface: existence and properties of interface object
 PASS Node interface: existence and properties of interface object
 PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt
index dc95c50..915af064 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt
@@ -36,6 +36,5 @@
 PASS GamepadEvent interface: new GamepadEvent("gamepad") must inherit property "gamepad" with the proper type
 PASS Navigator interface: operation getGamepads()
 PASS Navigator interface: navigator must inherit property "getGamepads()" with the proper type
-PASS WorkerNavigator interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.serviceworker-expected.txt
deleted file mode 100644
index 02975ba..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS Partial interface mixin WindowOrWorkerGlobalScope: original interface mixin defined
-PASS Performance interface: existence and properties of interface object
-PASS Performance interface object length
-PASS Performance interface object name
-PASS Performance interface: existence and properties of interface prototype object
-PASS Performance interface: existence and properties of interface prototype object's "constructor" property
-PASS Performance interface: existence and properties of interface prototype object's @@unscopables property
-PASS Performance interface: operation now()
-PASS Performance interface: attribute timeOrigin
-PASS Performance interface: operation toJSON()
-PASS Performance must be primary interface of performance
-PASS Stringification of performance
-PASS Performance interface: performance must inherit property "now()" with the proper type
-PASS Performance interface: performance must inherit property "timeOrigin" with the proper type
-PASS Performance interface: performance must inherit property "toJSON()" with the proper type
-PASS Test default toJSON operation of Performance
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-FAIL WorkerGlobalScope interface: attribute performance assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined"
-PASS WorkerGlobalScope interface: self must inherit property "performance" with the proper type
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.sharedworker-expected.txt
deleted file mode 100644
index 02975ba..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS Partial interface mixin WindowOrWorkerGlobalScope: original interface mixin defined
-PASS Performance interface: existence and properties of interface object
-PASS Performance interface object length
-PASS Performance interface object name
-PASS Performance interface: existence and properties of interface prototype object
-PASS Performance interface: existence and properties of interface prototype object's "constructor" property
-PASS Performance interface: existence and properties of interface prototype object's @@unscopables property
-PASS Performance interface: operation now()
-PASS Performance interface: attribute timeOrigin
-PASS Performance interface: operation toJSON()
-PASS Performance must be primary interface of performance
-PASS Stringification of performance
-PASS Performance interface: performance must inherit property "now()" with the proper type
-PASS Performance interface: performance must inherit property "timeOrigin" with the proper type
-PASS Performance interface: performance must inherit property "toJSON()" with the proper type
-PASS Test default toJSON operation of Performance
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-FAIL WorkerGlobalScope interface: attribute performance assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined"
-PASS WorkerGlobalScope interface: self must inherit property "performance" with the proper type
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.worker-expected.txt
deleted file mode 100644
index 02975ba..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.any.worker-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS Partial interface mixin WindowOrWorkerGlobalScope: original interface mixin defined
-PASS Performance interface: existence and properties of interface object
-PASS Performance interface object length
-PASS Performance interface object name
-PASS Performance interface: existence and properties of interface prototype object
-PASS Performance interface: existence and properties of interface prototype object's "constructor" property
-PASS Performance interface: existence and properties of interface prototype object's @@unscopables property
-PASS Performance interface: operation now()
-PASS Performance interface: attribute timeOrigin
-PASS Performance interface: operation toJSON()
-PASS Performance must be primary interface of performance
-PASS Stringification of performance
-PASS Performance interface: performance must inherit property "now()" with the proper type
-PASS Performance interface: performance must inherit property "timeOrigin" with the proper type
-PASS Performance interface: performance must inherit property "toJSON()" with the proper type
-PASS Test default toJSON operation of Performance
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-FAIL WorkerGlobalScope interface: attribute performance assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined"
-PASS WorkerGlobalScope interface: self must inherit property "performance" with the proper type
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness.window-expected.txt
index b887ef5..c8248ba9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness.window-expected.txt
@@ -3,6 +3,5 @@
 PASS Partial interface HTMLInputElement: original interface defined
 FAIL HTMLInputElement interface: attribute capture assert_true: The prototype object must have a property "capture" expected true got false
 FAIL HTMLInputElement interface: input must inherit property "capture" with the proper type assert_inherits: property "capture" not found in prototype chain
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git "a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" "b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
index 32ee1e59..fa4972aa 100644
--- "a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
+++ "b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
@@ -1119,75 +1119,5 @@
 PASS Stringification of window.external
 PASS External interface: window.external must inherit property "AddSearchProvider()" with the proper type
 PASS External interface: window.external must inherit property "IsSearchProviderInstalled()" with the proper type
-PASS SVGElement interface: attribute onabort
-PASS SVGElement interface: attribute onauxclick
-PASS SVGElement interface: attribute onblur
-PASS SVGElement interface: attribute oncancel
-PASS SVGElement interface: attribute oncanplay
-PASS SVGElement interface: attribute oncanplaythrough
-PASS SVGElement interface: attribute onchange
-PASS SVGElement interface: attribute onclick
-PASS SVGElement interface: attribute onclose
-PASS SVGElement interface: attribute oncontextmenu
-PASS SVGElement interface: attribute oncuechange
-PASS SVGElement interface: attribute ondblclick
-PASS SVGElement interface: attribute ondrag
-PASS SVGElement interface: attribute ondragend
-PASS SVGElement interface: attribute ondragenter
-FAIL SVGElement interface: attribute ondragexit assert_true: The prototype object must have a property "ondragexit" expected true got false
-PASS SVGElement interface: attribute ondragleave
-PASS SVGElement interface: attribute ondragover
-PASS SVGElement interface: attribute ondragstart
-PASS SVGElement interface: attribute ondrop
-PASS SVGElement interface: attribute ondurationchange
-PASS SVGElement interface: attribute onemptied
-PASS SVGElement interface: attribute onended
-PASS SVGElement interface: attribute onerror
-PASS SVGElement interface: attribute onfocus
-PASS SVGElement interface: attribute oninput
-PASS SVGElement interface: attribute oninvalid
-PASS SVGElement interface: attribute onkeydown
-PASS SVGElement interface: attribute onkeypress
-PASS SVGElement interface: attribute onkeyup
-PASS SVGElement interface: attribute onload
-PASS SVGElement interface: attribute onloadeddata
-PASS SVGElement interface: attribute onloadedmetadata
-FAIL SVGElement interface: attribute onloadend assert_true: The prototype object must have a property "onloadend" expected true got false
-PASS SVGElement interface: attribute onloadstart
-PASS SVGElement interface: attribute onmousedown
-PASS SVGElement interface: attribute onmouseenter
-PASS SVGElement interface: attribute onmouseleave
-PASS SVGElement interface: attribute onmousemove
-PASS SVGElement interface: attribute onmouseout
-PASS SVGElement interface: attribute onmouseover
-PASS SVGElement interface: attribute onmouseup
-PASS SVGElement interface: attribute onwheel
-PASS SVGElement interface: attribute onpause
-PASS SVGElement interface: attribute onplay
-PASS SVGElement interface: attribute onplaying
-PASS SVGElement interface: attribute onprogress
-PASS SVGElement interface: attribute onratechange
-PASS SVGElement interface: attribute onreset
-PASS SVGElement interface: attribute onresize
-PASS SVGElement interface: attribute onscroll
-FAIL SVGElement interface: attribute onsecuritypolicyviolation assert_true: The prototype object must have a property "onsecuritypolicyviolation" expected true got false
-PASS SVGElement interface: attribute onseeked
-PASS SVGElement interface: attribute onseeking
-PASS SVGElement interface: attribute onselect
-PASS SVGElement interface: attribute onstalled
-PASS SVGElement interface: attribute onsubmit
-PASS SVGElement interface: attribute onsuspend
-PASS SVGElement interface: attribute ontimeupdate
-PASS SVGElement interface: attribute ontoggle
-PASS SVGElement interface: attribute onvolumechange
-PASS SVGElement interface: attribute onwaiting
-PASS SVGElement interface: attribute oncopy
-PASS SVGElement interface: attribute oncut
-PASS SVGElement interface: attribute onpaste
-PASS SVGElement interface: attribute dataset
-PASS SVGElement interface: attribute nonce
-PASS SVGElement interface: attribute tabIndex
-PASS SVGElement interface: operation focus(FocusOptions)
-PASS SVGElement interface: operation blur()
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/interaction/focus/processing-model/legend-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/interaction/focus/processing-model/legend-expected.txt
deleted file mode 100644
index e8e576ac..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/interaction/focus/processing-model/legend-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL legend assert_unreached: input in legend was focused Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html
new file mode 100644
index 0000000..26e5f33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+  <meta charset="utf-8">
+  <title>Reference: Combobox ignores CSS 'line-height'</title>
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <style type="text/css">
+html,body {
+  color:black; background-color:white; font:16px/1 monospace;
+}
+
+  </style>
+</head>
+<body>
+
+<select><option>aaaaaaaaaa<option>bbbbbbbbbb</select>
+
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height.html b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height.html
new file mode 100644
index 0000000..e6383f08
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/the-select-element/select-1-line-height.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+  <meta charset="utf-8">
+  <title>Test: Combobox ignores CSS 'line-height'</title>
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <link rel="match" href="select-1-line-height-ref.html">
+  <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+  <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1501908">
+  <style type="text/css">
+html,body {
+  color:black; background-color:white; font:16px/1 monospace;
+}
+
+select { line-height:100px; }
+
+  </style>
+</head>
+<body>
+
+<select><option>aaaaaaaaaa<option>bbbbbbbbbb</select>
+
+<script>
+document.body.offsetHeight;
+var cv = window.getComputedStyle(document.querySelector('select')).lineHeight;
+if (cv == "normal" || parseInt(cv) > 50) {
+  document.body.appendChild(document.createTextNode(
+    "FAIL: got computed line-height '" + cv + "', expected a length <= 50px"));
+}</script>
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-target/form-target-iframe-helper.py b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-target/form-target-iframe-helper.py
new file mode 100644
index 0000000..291221a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-target/form-target-iframe-helper.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    return ([("Content-Type", "text/plain")],
+            "OK")
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-target/form-target-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-target/form-target-iframe.html
new file mode 100644
index 0000000..f37bc33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/form-submission-target/form-target-iframe.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Form targetted at iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+  window.addEventListener("load", t.step_func(function() {
+    var frame = document.createElement("iframe");
+    frame.name = "frame";
+    document.documentElement.appendChild(frame);
+    var form = document.createElement("form");
+    form.target = "frame";
+    form.action = "form-target-iframe-helper.py";
+    form.method = "POST";
+    var input = document.createElement("input");
+    input.name = "n";
+    form.appendChild(input);
+    document.documentElement.appendChild(form);
+    form.submit();
+    frame.addEventListener("load", t.step_func(function() {
+      if (frame.contentWindow.location.href.includes("form-target-iframe-helper.py")) {
+        assert_equals(frame.contentWindow.document.body.textContent, "OK");
+        t.done();
+      }
+    }));
+  }));
+}, "Form targetted at iframe");
+</script>
+<body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.window-expected.txt
index 1243572..e2149ce 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.window-expected.txt
@@ -19,6 +19,5 @@
 PASS HTMLCanvasElement interface: operation captureStream(double)
 PASS HTMLCanvasElement interface: canvas must inherit property "captureStream(double)" with the proper type
 PASS HTMLCanvasElement interface: calling captureStream(double) on canvas with too few arguments must throw TypeError
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/idlharness.https.window-expected.txt
index aa959031..da7a86a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/idlharness.https.window-expected.txt
@@ -162,6 +162,5 @@
 PASS Navigator interface: navigator must inherit property "mediaDevices" with the proper type
 PASS Navigator interface: navigator must inherit property "getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback)" with the proper type
 PASS Navigator interface: calling getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback) on navigator with too few arguments must throw TypeError
-PASS WorkerNavigator interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/META.yml b/third_party/WebKit/LayoutTests/external/wpt/payment-request/META.yml
index 0a075e1..e608c0e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/META.yml
@@ -3,7 +3,7 @@
   - marcoscaceres
   - rsolomakhin
   - domenic
-  - MSFTkihans
+  - zouhir
   - mnoorenberghe
   - romandev
   - edenchuang
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/picture-in-picture-window.html b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/picture-in-picture-window.html
index 6d14cf5..47b8133 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/picture-in-picture-window.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/picture-in-picture-window.html
@@ -16,7 +16,7 @@
     assert_not_equals(pipWindow.height, 0);
     const videoAspectRatio = video.videoWidth / video.videoHeight;
     const pipWindowAspectRatio = pipWindow.width / pipWindow.height;
-    assert_equals(videoAspectRatio, pipWindowAspectRatio);
+    assert_approx_equals(videoAspectRatio, pipWindowAspectRatio, 0.01);
   });
 }, 'Picture-in-Picture window dimensions are set after entering Picture-in-Picture');
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness.window-expected.txt
index fb85fa0..fd20b3c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/idlharness.window-expected.txt
@@ -1,5 +1,4 @@
 This is a testharness.js-based test.
-Found 85 tests; 79 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Element: original interface defined
 PASS Partial interface GlobalEventHandlers: original interface defined
@@ -32,16 +31,6 @@
 PASS PointerEvent interface: new PointerEvent("type") must inherit property "twist" with the proper type
 PASS PointerEvent interface: new PointerEvent("type") must inherit property "pointerType" with the proper type
 PASS PointerEvent interface: new PointerEvent("type") must inherit property "isPrimary" with the proper type
-PASS Document interface: attribute ongotpointercapture
-PASS Document interface: attribute onlostpointercapture
-PASS Document interface: attribute onpointerdown
-PASS Document interface: attribute onpointermove
-PASS Document interface: attribute onpointerup
-PASS Document interface: attribute onpointercancel
-PASS Document interface: attribute onpointerover
-PASS Document interface: attribute onpointerout
-PASS Document interface: attribute onpointerenter
-PASS Document interface: attribute onpointerleave
 PASS Element interface: operation setPointerCapture(long)
 PASS Element interface: operation releasePointerCapture(long)
 PASS Element interface: operation hasPointerCapture(long)
@@ -51,39 +40,7 @@
 FAIL Element interface: calling releasePointerCapture(long) on document with too few arguments must throw TypeError assert_inherits: property "releasePointerCapture" not found in prototype chain
 FAIL Element interface: document must inherit property "hasPointerCapture(long)" with the proper type assert_inherits: property "hasPointerCapture" not found in prototype chain
 FAIL Element interface: calling hasPointerCapture(long) on document with too few arguments must throw TypeError assert_inherits: property "hasPointerCapture" not found in prototype chain
-PASS HTMLElement interface: attribute ongotpointercapture
-PASS HTMLElement interface: attribute onlostpointercapture
-PASS HTMLElement interface: attribute onpointerdown
-PASS HTMLElement interface: attribute onpointermove
-PASS HTMLElement interface: attribute onpointerup
-PASS HTMLElement interface: attribute onpointercancel
-PASS HTMLElement interface: attribute onpointerover
-PASS HTMLElement interface: attribute onpointerout
-PASS HTMLElement interface: attribute onpointerenter
-PASS HTMLElement interface: attribute onpointerleave
-PASS Window interface: attribute ongotpointercapture
-PASS Window interface: attribute onlostpointercapture
-PASS Window interface: attribute onpointerdown
-PASS Window interface: attribute onpointermove
-PASS Window interface: attribute onpointerup
-PASS Window interface: attribute onpointercancel
-PASS Window interface: attribute onpointerover
-PASS Window interface: attribute onpointerout
-PASS Window interface: attribute onpointerenter
-PASS Window interface: attribute onpointerleave
-PASS Window interface: window must inherit property "ongotpointercapture" with the proper type
-PASS Window interface: window must inherit property "onlostpointercapture" with the proper type
-PASS Window interface: window must inherit property "onpointerdown" with the proper type
-PASS Window interface: window must inherit property "onpointermove" with the proper type
-PASS Window interface: window must inherit property "onpointerup" with the proper type
-PASS Window interface: window must inherit property "onpointercancel" with the proper type
-PASS Window interface: window must inherit property "onpointerover" with the proper type
-PASS Window interface: window must inherit property "onpointerout" with the proper type
-PASS Window interface: window must inherit property "onpointerenter" with the proper type
-PASS Window interface: window must inherit property "onpointerleave" with the proper type
 PASS Navigator interface: attribute maxTouchPoints
 PASS Navigator interface: navigator must inherit property "maxTouchPoints" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-PASS WorkerNavigator interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.https.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.https.any.serviceworker-expected.txt
index 2a17bcb..d0869e0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.https.any.serviceworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.https.any.serviceworker-expected.txt
@@ -79,17 +79,5 @@
 FAIL ServiceWorkerGlobalScope interface: attribute onpushsubscriptionchange assert_own_property: The global object must have a property "onpushsubscriptionchange" expected property "onpushsubscriptionchange" missing
 PASS ServiceWorkerGlobalScope interface: self must inherit property "onpush" with the proper type
 FAIL ServiceWorkerGlobalScope interface: self must inherit property "onpushsubscriptionchange" with the proper type assert_own_property: expected property "onpushsubscriptionchange" missing
-PASS HTMLElement interface: existence and properties of interface object
-PASS HTMLBodyElement interface: existence and properties of interface object
-PASS Window interface: existence and properties of interface object
-PASS HTMLFrameSetElement interface: existence and properties of interface object
-PASS Node interface: existence and properties of interface object
-PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index 9e6ed23..40a5fa59 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -305,7 +305,13 @@
                 if (parsed[dep_type]) {
                     const inheriting = parsed[dep_type];
                     const inheritor = parsed.name || parsed.target;
-                    for (const dep of [inheriting, inheritor]) {
+                    const deps = [inheriting];
+                    // For A includes B, we can ignore A unless B is being tested.
+                    if (dep_type !== "includes"
+                        || (inheriting in this.members && !this.members[inheriting].untested)) {
+                        deps.push(inheritor);
+                    }
+                    for (const dep of deps) {
                         new_options.only.push(dep);
                         all_deps.add(dep);
                         follow_up.add(dep);
@@ -320,7 +326,7 @@
                     next.forEach(process);
                 }
             }
-        });
+        }.bind(this));
     }.bind(this);
 
     for (let parsed of parsed_idls) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html
new file mode 100644
index 0000000..caa4f94
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html
@@ -0,0 +1,211 @@
+<!DOCTYPE html>
+<title>Service Worker: postMessage to Client (message queue)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+// This function creates a message listener that captures all messages
+// sent to this window and matches them with corresponding requests.
+// This frees test code from having to use clunky constructs just to
+// avoid race conditions, since the relative order of message and
+// request arrival doesn't matter.
+function create_message_listener(t) {
+    const listener = {
+        messages: new Set(),
+        requests: new Set(),
+        waitFor: function(predicate) {
+            for (const event of this.messages) {
+                // If a message satisfying the predicate has already
+                // arrived, it gets matched to this request.
+                if (predicate(event)) {
+                    this.messages.delete(event);
+                    return Promise.resolve(event);
+                }
+            }
+
+            // If no match was found, the request is stored and a
+            // promise is returned.
+            const request = { predicate };
+            const promise = new Promise(resolve => request.resolve = resolve);
+            this.requests.add(request);
+            return promise;
+        }
+    };
+    window.onmessage = t.step_func(event => {
+        for (const request of listener.requests) {
+            // If the new message matches a stored request's
+            // predicate, the request's promise is resolved with this
+            // message.
+            if (request.predicate(event)) {
+                listener.requests.delete(request);
+                request.resolve(event);
+                return;
+            }
+        };
+
+        // No outstanding request for this message, store it in case
+        // it's requested later.
+        listener.messages.add(event);
+    });
+    return listener;
+}
+
+async function service_worker_register_and_activate(t, script, scope) {
+    const registration = await service_worker_unregister_and_register(t, script, scope);
+    t.add_cleanup(() => registration.unregister());
+    const worker = registration.installing;
+    await wait_for_state(t, worker, 'activated');
+    return worker;
+}
+
+// Add an iframe (parent) whose document contains a nested iframe
+// (child), then set the child's src attribute to child_url and return
+// its Window (without waiting for it to finish loading).
+async function with_nested_iframes(t, child_url) {
+    const parent = await with_iframe('resources/nested-iframe-parent.html?role=parent');
+    t.add_cleanup(() => parent.remove());
+    const child = parent.contentWindow.document.getElementById('child');
+    child.setAttribute('src', child_url);
+    return child.contentWindow;
+}
+
+// Returns a predicate matching a fetch message with the specified
+// key.
+function fetch_message(key) {
+    return event => event.data.type === 'fetch' && event.data.key === key;
+}
+
+// Returns a predicate matching a ping message with the specified
+// payload.
+function ping_message(data) {
+    return event => event.data.type === 'ping' && event.data.data === data;
+}
+
+// A client message queue test is a testharness.js test with some
+// additional setup:
+// 1. A listener (see create_message_listener)
+// 2. An active service worker
+// 3. Two nested iframes
+// 4. A state transition function that controls the order of events
+//    during the test
+function client_message_queue_test(url, test_function, description) {
+    promise_test(async t => {
+        t.listener = create_message_listener(t);
+
+        const script = 'resources/stalling-service-worker.js';
+        const scope = 'resources/';
+        t.service_worker = await service_worker_register_and_activate(t, script, scope);
+
+        // We create two nested iframes such that both are controlled by
+        // the newly installed service worker.
+        const child_url = url + '?role=child';
+        t.frame = await with_nested_iframes(t, child_url);
+
+        t.state_transition = async function(from, to, scripts) {
+            // A state transition begins with the child's parser
+            // fetching a script due to a <script> tag. The request
+            // arrives at the service worker, which notifies the
+            // parent, which in turn notifies the test. Note that the
+            // event loop keeps spinning while the parser is waiting.
+            const request = await this.listener.waitFor(fetch_message(to));
+
+            // The test instructs the service worker to send two ping
+            // messages through the Client interface: first to the
+            // child, then to the parent.
+            this.service_worker.postMessage(from);
+
+            // When the parent receives the ping message, it forwards
+            // it to the test. Assuming that messages to both child
+            // and parent are mapped to the same task queue (this is
+            // not [yet] required by the spec), receiving this message
+            // guarantees that the child has already dispatched its
+            // message if it was allowed to do so.
+            await this.listener.waitFor(ping_message(from));
+
+            // Finally, reply to the service worker's fetch
+            // notification with the script it should use as the fetch
+            // request's response. This is a defensive mechanism that
+            // ensures the child's parser really is blocked until the
+            // test is ready to continue.
+            request.ports[0].postMessage([`state = '${to}';`].concat(scripts));
+        };
+
+        await test_function(t);
+    }, description);
+}
+
+function client_message_queue_enable_test(
+    install_script,
+    start_script,
+    earliest_dispatch,
+    description)
+{
+    function later_state(state1, state2) {
+        const states = ['init', 'install', 'start', 'finish', 'loaded'];
+        const index1 = states.indexOf(state1);
+        const index2 = states.indexOf(state2);
+        const max_index = Math.max(index1, index2);
+        return states[max_index];
+    }
+
+    client_message_queue_test('enable-client-message-queue.html', async t => {
+        // While parsing the child's document, the child transitions
+        // from the 'init' state all the way to the 'finish' state.
+        // Once parsing is finished it would enter the final 'loaded'
+        // state. All but the last transition require assitance from
+        // the test.
+        await t.state_transition('init', 'install', [install_script]);
+        await t.state_transition('install', 'start', [start_script]);
+        await t.state_transition('start', 'finish', []);
+
+        // Wait for all messages to get dispatched on the child's
+        // ServiceWorkerContainer and then verify that each message
+        // was dispatched while the child was in the correct state.
+        const report = await t.frame.report;
+        ['init', 'install', 'start'].forEach(state => {
+            const dispatch = later_state(state, earliest_dispatch);
+            assert_equals(report[state], dispatch,
+                          `Message sent in state '${state}' dispatched in state '${dispatch}'`);
+        });
+    }, description);
+}
+
+const empty_script = ``;
+
+const add_event_listener =
+    `navigator.serviceWorker.addEventListener('message', handle_message);`;
+
+const set_onmessage = `navigator.serviceWorker.onmessage = handle_message;`;
+
+const start_messages = `navigator.serviceWorker.startMessages();`;
+
+client_message_queue_enable_test(add_event_listener, empty_script, 'loaded',
+    'Messages from ServiceWorker to Client only received after DOMContentLoaded event.');
+
+client_message_queue_enable_test(add_event_listener, start_messages, 'start',
+    'Messages from ServiceWorker to Client only received after calling startMessages().');
+
+client_message_queue_enable_test(set_onmessage, empty_script, 'install',
+    'Messages from ServiceWorker to Client only received after setting onmessage.');
+
+const resolve_manual_promise = `resolve_manual_promise();`
+
+async function test_microtasks_when_client_message_queue_enabled(t, scripts) {
+    await t.state_transition('init', 'start', scripts.concat([resolve_manual_promise]));
+    let result = await t.frame.result;
+    assert_equals(result[0], 'microtask', 'The microtask was executed first.');
+    assert_equals(result[1], 'message', 'The message was dispatched.');
+}
+
+client_message_queue_test('message-vs-microtask.html', t => {
+    return test_microtasks_when_client_message_queue_enabled(t, [
+        add_event_listener,
+        start_messages,
+    ]);
+}, 'Microtasks run before dispatching messages after calling startMessages().');
+
+client_message_queue_test('message-vs-microtask.html', t => {
+    return test_microtasks_when_client_message_queue_enabled(t, [set_onmessage]);
+}, 'Microtasks run before dispatching messages after setting onmessage.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client.https.html
index b1dc41a..15d2e88 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/postmessage-to-client.https.html
@@ -51,208 +51,4 @@
         })
       .then(e => { assert_equals(e.data, 'quit'); });
   }, 'postMessage from ServiceWorker to Client.');
-
-// This function creates a message listener that captures all messages
-// sent to this window and matches them with corresponding requests.
-// This frees test code from having to use clunky constructs just to
-// avoid race conditions, since the relative order of message and
-// request arrival doesn't matter.
-function create_message_listener(t) {
-    const listener = {
-        messages: new Set(),
-        requests: new Set(),
-        waitFor: function(predicate) {
-            for (const event of this.messages) {
-                // If a message satisfying the predicate has already
-                // arrived, it gets matched to this request.
-                if (predicate(event)) {
-                    this.messages.delete(event);
-                    return Promise.resolve(event);
-                }
-            }
-
-            // If no match was found, the request is stored and a
-            // promise is returned.
-            const request = { predicate };
-            const promise = new Promise(resolve => request.resolve = resolve);
-            this.requests.add(request);
-            return promise;
-        }
-    };
-    window.onmessage = t.step_func(event => {
-        for (const request of listener.requests) {
-            // If the new message matches a stored request's
-            // predicate, the request's promise is resolved with this
-            // message.
-            if (request.predicate(event)) {
-                listener.requests.delete(request);
-                request.resolve(event);
-                return;
-            }
-        };
-
-        // No outstanding request for this message, store it in case
-        // it's requested later.
-        listener.messages.add(event);
-    });
-    return listener;
-}
-
-async function service_worker_register_and_activate(t, script, scope) {
-    const registration = await service_worker_unregister_and_register(t, script, scope);
-    t.add_cleanup(() => registration.unregister());
-    const worker = registration.installing;
-    await wait_for_state(t, worker, 'activated');
-    return worker;
-}
-
-// Add an iframe (parent) whose document contains a nested iframe
-// (child), then set the child's src attribute to child_url and return
-// its Window (without waiting for it to finish loading).
-async function with_nested_iframes(t, child_url) {
-    const parent = await with_iframe('resources/nested-iframe-parent.html?role=parent');
-    t.add_cleanup(() => parent.remove());
-    const child = parent.contentWindow.document.getElementById('child');
-    child.setAttribute('src', child_url);
-    return child.contentWindow;
-}
-
-// Returns a predicate matching a fetch message with the specified
-// key.
-function fetch_message(key) {
-    return event => event.data.type === 'fetch' && event.data.key === key;
-}
-
-// Returns a predicate matching a ping message with the specified
-// payload.
-function ping_message(data) {
-    return event => event.data.type === 'ping' && event.data.data === data;
-}
-
-// A client message queue test is a testharness.js test with some
-// additional setup:
-// 1. A listener (see create_message_listener)
-// 2. An active service worker
-// 3. Two nested iframes
-// 4. A state transition function that controls the order of events
-//    during the test
-function client_message_queue_test(url, test_function, description) {
-    promise_test(async t => {
-        t.listener = create_message_listener(t);
-
-        const script = 'resources/stalling-service-worker.js';
-        const scope = 'resources/';
-        t.service_worker = await service_worker_register_and_activate(t, script, scope);
-
-        // We create two nested iframes such that both are controlled by
-        // the newly installed service worker.
-        const child_url = url + '?role=child';
-        t.frame = await with_nested_iframes(t, child_url);
-
-        t.state_transition = async function(from, to, scripts) {
-            // A state transition begins with the child's parser
-            // fetching a script due to a <script> tag. The request
-            // arrives at the service worker, which notifies the
-            // parent, which in turn notifies the test. Note that the
-            // event loop keeps spinning while the parser is waiting.
-            const request = await this.listener.waitFor(fetch_message(to));
-
-            // The test instructs the service worker to send two ping
-            // messages through the Client interface: first to the
-            // child, then to the parent.
-            this.service_worker.postMessage(from);
-
-            // When the parent receives the ping message, it forwards
-            // it to the test. Assuming that messages to both child
-            // and parent are mapped to the same task queue (this is
-            // not [yet] required by the spec), receiving this message
-            // guarantees that the child has already dispatched its
-            // message if it was allowed to do so.
-            await this.listener.waitFor(ping_message(from));
-
-            // Finally, reply to the service worker's fetch
-            // notification with the script it should use as the fetch
-            // request's response. This is a defensive mechanism that
-            // ensures the child's parser really is blocked until the
-            // test is ready to continue.
-            request.ports[0].postMessage([`state = '${to}';`].concat(scripts));
-        };
-
-        await test_function(t);
-    }, description);
-}
-
-function client_message_queue_enable_test(
-    install_script,
-    start_script,
-    earliest_dispatch,
-    description)
-{
-    function later_state(state1, state2) {
-        const states = ['init', 'install', 'start', 'finish', 'loaded'];
-        const index1 = states.indexOf(state1);
-        const index2 = states.indexOf(state2);
-        const max_index = Math.max(index1, index2);
-        return states[max_index];
-    }
-
-    client_message_queue_test('enable-client-message-queue.html', async t => {
-        // While parsing the child's document, the child transitions
-        // from the 'init' state all the way to the 'finish' state.
-        // Once parsing is finished it would enter the final 'loaded'
-        // state. All but the last transition require assitance from
-        // the test.
-        await t.state_transition('init', 'install', [install_script]);
-        await t.state_transition('install', 'start', [start_script]);
-        await t.state_transition('start', 'finish', []);
-
-        // Wait for all messages to get dispatched on the child's
-        // ServiceWorkerContainer and then verify that each message
-        // was dispatched while the child was in the correct state.
-        const report = await t.frame.report;
-        ['init', 'install', 'start'].forEach(state => {
-            const dispatch = later_state(state, earliest_dispatch);
-            assert_equals(report[state], dispatch,
-                          `Message sent in state '${state}' dispatched in state '${dispatch}'`);
-        });
-    }, description);
-}
-
-const empty_script = ``;
-
-const add_event_listener =
-    `navigator.serviceWorker.addEventListener('message', handle_message);`;
-
-const set_onmessage = `navigator.serviceWorker.onmessage = handle_message;`;
-
-const start_messages = `navigator.serviceWorker.startMessages();`;
-
-client_message_queue_enable_test(add_event_listener, empty_script, 'loaded',
-    'Messages from ServiceWorker to Client only received after DOMContentLoaded event.');
-
-client_message_queue_enable_test(add_event_listener, start_messages, 'start',
-    'Messages from ServiceWorker to Client only received after calling startMessages().');
-
-client_message_queue_enable_test(set_onmessage, empty_script, 'install',
-    'Messages from ServiceWorker to Client only received after setting onmessage.');
-
-const resolve_manual_promise = `resolve_manual_promise();`
-
-async function test_microtasks_when_client_message_queue_enabled(t, scripts) {
-    await t.state_transition('init', 'start', scripts.concat([resolve_manual_promise]));
-    let result = await t.frame.result;
-    assert_equals(result[0], 'microtask', 'The microtask was executed first.');
-    assert_equals(result[1], 'message', 'The message was dispatched.');
-}
-
-client_message_queue_test('message-vs-microtask.html', t => {
-    return test_microtasks_when_client_message_queue_enabled(t, [
-        add_event_listener,
-        start_messages,
-    ]);
-}, 'Microtasks run before dispatching messages after calling startMessages().');
-
-client_message_queue_test('message-vs-microtask.html', t => {
-    return test_microtasks_when_client_message_queue_enabled(t, [set_onmessage]);
-}, 'Microtasks run before dispatching messages after setting onmessage.');
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt
index e913d754..ee63d6d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt
@@ -1,6 +1,6 @@
 This is a testharness.js-based test.
-Found 216 tests; 67 PASS, 149 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS idl_test setup
+Found 222 tests; 65 PASS, 157 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL idl_test setup promise_test: Unhandled rejection with value: "Timed out waiting for voice"
 PASS Partial interface Window: original interface defined
 FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
 FAIL SpeechRecognition interface object length assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
@@ -213,8 +213,14 @@
 FAIL SpeechSynthesisVoice interface: attribute lang assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
 FAIL SpeechSynthesisVoice interface: attribute localService assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
 FAIL SpeechSynthesisVoice interface: attribute default assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
+FAIL SpeechSynthesisVoice must be primary interface of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
+FAIL Stringification of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
+FAIL SpeechSynthesisVoice interface: voice must inherit property "voiceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
+FAIL SpeechSynthesisVoice interface: voice must inherit property "name" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
+FAIL SpeechSynthesisVoice interface: voice must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
+FAIL SpeechSynthesisVoice interface: voice must inherit property "localService" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
+FAIL SpeechSynthesisVoice interface: voice must inherit property "default" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
 PASS Window interface: attribute speechSynthesis
 PASS Window interface: self must inherit property "speechSynthesis" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/svg/idlharness.window-expected.txt
index b4aa8b69..36ed012 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/svg/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/idlharness.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1601 tests; 1478 PASS, 123 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1600 tests; 1477 PASS, 123 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS SVGElement interface: existence and properties of interface object
@@ -1599,7 +1599,6 @@
 PASS SVGElement interface: objects.view must inherit property "viewportElement" with the proper type
 FAIL SVGElement interface: objects.view must inherit property "correspondingElement" with the proper type assert_inherits: property "correspondingElement" not found in prototype chain
 FAIL SVGElement interface: objects.view must inherit property "correspondingUseElement" with the proper type assert_inherits: property "correspondingUseElement" not found in prototype chain
-PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS Document interface: attribute rootElement
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/linking/reftests/use-hidden-attr-change.html b/third_party/WebKit/LayoutTests/external/wpt/svg/linking/reftests/use-hidden-attr-change.html
new file mode 100644
index 0000000..4fe535b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/linking/reftests/use-hidden-attr-change.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>use element reacts to attribute changes when it's not rendered</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseElement">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1502658">
+<link rel="match" href="/svg/linking/reftests/use-descendant-combinator-ref.html">
+<style>
+</style>
+<p>
+  You should see a green square, and no red.
+</p>
+<svg
+  version="1.1"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  style="display: none">
+  <defs>
+    <g id="square">
+      <rect width="100" height="100" fill="green" />
+    </g>
+  </defs>
+  <g id="test">
+    <use />
+  </g>
+</svg>
+<script>
+  onload = () => {
+    document.querySelector("use").setAttributeNS("http://www.w3.org/1999/xlink", "href", "#square");
+    document.querySelector("svg").style.display = "";
+  }
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/circle-01-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/circle-01-ref.svg
new file mode 100644
index 0000000..1d62e8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/circle-01-ref.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/circle-01.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/circle-01.svg
new file mode 100644
index 0000000..8eecd66
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/circle-01.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+  <metadata>
+    <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/SVG2/shapes.html#CircleElement"/>
+    <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="circle-01-ref.svg"/>
+    <meta xmlns="http://www.w3.org/1999/xhtml" name="assert" content="r 0 disables rendering."/>
+  </metadata>
+  <circle cx="50" cy="50" r="0" fill="red" stroke="red" stroke-width="5"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/ellipse-09.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/ellipse-09.svg
new file mode 100644
index 0000000..77e3f3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/ellipse-09.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+  <metadata>
+    <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/SVG2/shapes.html#EllipseElement"/>
+    <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="ellipse-04-ref.svg"/>
+    <meta xmlns="http://www.w3.org/1999/xhtml" name="assert" content="rx or ry 0 disables rendering."/>
+  </metadata>
+  <ellipse cx="30" cy="50" rx="0" ry="10" fill="red" stroke="red" stroke-width="5"/>
+  <ellipse cx="50" cy="50" rx="10" ry="0" fill="red" stroke="red" stroke-width="5"/>
+  <ellipse cx="70" cy="50" rx="0" ry="0" fill="red" stroke="red" stroke-width="5"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/rect-05-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/rect-05-ref.svg
new file mode 100644
index 0000000..1d62e8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/rect-05-ref.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/rect-05.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/rect-05.svg
new file mode 100644
index 0000000..27d01ef
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/shapes/rect-05.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+  <metadata>
+    <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="http://www.w3.org/TR/SVG2/shapes.html#RectElement"/>
+    <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="rect-05-ref.svg"/>
+    <meta xmlns="http://www.w3.org/1999/xhtml" name="assert" content="width or height 0 disables rendering."/>
+  </metadata>
+  <rect x="30" y="50" width="0" height="10" fill="red" stroke="red" stroke-width="4"/>
+  <rect x="50" y="50" width="10" height="0" fill="red" stroke="red" stroke-width="4"/>
+  <rect x="70" y="50" width="0" height="0" fill="red" stroke="red" stroke-width="4"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window-expected.txt
index 6105362..8ac9fbe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window-expected.txt
@@ -1,5 +1,86 @@
 This is a testharness.js-based test.
-FAIL idl_test setup promise_test: Unhandled rejection with value: "Document includes GlobalEventHandlers, but Document is undefined."
+Found 82 tests; 72 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS idl_test setup
 PASS Partial interface GlobalEventHandlers: original interface defined
+PASS Touch interface: existence and properties of interface object
+PASS Touch interface object length
+PASS Touch interface object name
+PASS Touch interface: existence and properties of interface prototype object
+PASS Touch interface: existence and properties of interface prototype object's "constructor" property
+PASS Touch interface: existence and properties of interface prototype object's @@unscopables property
+PASS Touch interface: attribute identifier
+PASS Touch interface: attribute target
+PASS Touch interface: attribute screenX
+PASS Touch interface: attribute screenY
+PASS Touch interface: attribute clientX
+PASS Touch interface: attribute clientY
+PASS Touch interface: attribute pageX
+PASS Touch interface: attribute pageY
+PASS Touch interface: attribute radiusX
+PASS Touch interface: attribute radiusY
+PASS Touch interface: attribute rotationAngle
+PASS Touch interface: attribute force
+FAIL Touch interface: attribute altitudeAngle assert_true: The prototype object must have a property "altitudeAngle" expected true got false
+FAIL Touch interface: attribute azimuthAngle assert_true: The prototype object must have a property "azimuthAngle" expected true got false
+FAIL Touch interface: attribute touchType assert_true: The prototype object must have a property "touchType" expected true got false
+PASS Touch must be primary interface of new Touch({identifier: 1, target: document})
+PASS Stringification of new Touch({identifier: 1, target: document})
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "identifier" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "target" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "screenX" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "screenY" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "clientX" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "clientY" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "pageX" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "pageY" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "radiusX" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "radiusY" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "rotationAngle" with the proper type
+PASS Touch interface: new Touch({identifier: 1, target: document}) must inherit property "force" with the proper type
+FAIL Touch interface: new Touch({identifier: 1, target: document}) must inherit property "altitudeAngle" with the proper type assert_inherits: property "altitudeAngle" not found in prototype chain
+FAIL Touch interface: new Touch({identifier: 1, target: document}) must inherit property "azimuthAngle" with the proper type assert_inherits: property "azimuthAngle" not found in prototype chain
+FAIL Touch interface: new Touch({identifier: 1, target: document}) must inherit property "touchType" with the proper type assert_inherits: property "touchType" not found in prototype chain
+PASS TouchList interface: existence and properties of interface object
+PASS TouchList interface object length
+PASS TouchList interface object name
+PASS TouchList interface: existence and properties of interface prototype object
+PASS TouchList interface: existence and properties of interface prototype object's "constructor" property
+PASS TouchList interface: existence and properties of interface prototype object's @@unscopables property
+PASS TouchList interface: attribute length
+PASS TouchList interface: operation item(unsigned long)
+PASS TouchEvent interface: existence and properties of interface object
+PASS TouchEvent interface object length
+PASS TouchEvent interface object name
+PASS TouchEvent interface: existence and properties of interface prototype object
+PASS TouchEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS TouchEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS TouchEvent interface: attribute touches
+PASS TouchEvent interface: attribute targetTouches
+PASS TouchEvent interface: attribute changedTouches
+PASS TouchEvent interface: attribute altKey
+PASS TouchEvent interface: attribute metaKey
+PASS TouchEvent interface: attribute ctrlKey
+PASS TouchEvent interface: attribute shiftKey
+PASS TouchEvent must be primary interface of new TouchEvent("name")
+PASS Stringification of new TouchEvent("name")
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "touches" with the proper type
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "targetTouches" with the proper type
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "changedTouches" with the proper type
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "altKey" with the proper type
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "metaKey" with the proper type
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "ctrlKey" with the proper type
+PASS TouchEvent interface: new TouchEvent("name") must inherit property "shiftKey" with the proper type
+FAIL GlobalEventHandlers interface: window must inherit property "ontouchstart" with the proper type assert_inherits: property "ontouchstart" found on object expected in prototype chain
+FAIL GlobalEventHandlers interface: window must inherit property "ontouchend" with the proper type assert_inherits: property "ontouchend" found on object expected in prototype chain
+FAIL GlobalEventHandlers interface: window must inherit property "ontouchmove" with the proper type assert_inherits: property "ontouchmove" found on object expected in prototype chain
+FAIL GlobalEventHandlers interface: window must inherit property "ontouchcancel" with the proper type assert_inherits: property "ontouchcancel" found on object expected in prototype chain
+PASS GlobalEventHandlers interface: document must inherit property "ontouchstart" with the proper type
+PASS GlobalEventHandlers interface: document must inherit property "ontouchend" with the proper type
+PASS GlobalEventHandlers interface: document must inherit property "ontouchmove" with the proper type
+PASS GlobalEventHandlers interface: document must inherit property "ontouchcancel" with the proper type
+PASS GlobalEventHandlers interface: document.body must inherit property "ontouchstart" with the proper type
+PASS GlobalEventHandlers interface: document.body must inherit property "ontouchend" with the proper type
+PASS GlobalEventHandlers interface: document.body must inherit property "ontouchmove" with the proper type
+PASS GlobalEventHandlers interface: document.body must inherit property "ontouchcancel" with the proper type
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt
index 64ec9f4..1e99acd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt
@@ -1124,6 +1124,5 @@
 PASS AudioNode interface: worklet_node must inherit property "channelCountMode" with the proper type
 PASS AudioNode interface: worklet_node must inherit property "channelInterpretation" with the proper type
 PASS AudioWorkletProcessor interface: existence and properties of interface object
-PASS WorkerGlobalScope interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webmidi/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webmidi/idlharness.https.window-expected.txt
index c2d675a6..85db0f6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webmidi/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webmidi/idlharness.https.window-expected.txt
@@ -82,6 +82,5 @@
 PASS Stringification of new MIDIConnectionEvent("type")
 PASS MIDIConnectionEvent interface: new MIDIConnectionEvent("type") must inherit property "port" with the proper type
 PASS Navigator interface: operation requestMIDIAccess(MIDIOptions)
-PASS WorkerNavigator interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt
index 794ad858..2528268 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -186,10 +186,7 @@
 FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
 FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
 FAIL XRCoordinateSystemEvent interface: attribute coordinateSystem assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
-PASS WebGLRenderingContext interface: operation setCompatibleXRDevice(XRDevice)
 PASS Navigator interface: attribute xr
 PASS Navigator interface: navigator must inherit property "xr" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-PASS WorkerNavigator interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.sharedworker-expected.txt
index a388bd7..50788e8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.sharedworker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.sharedworker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 170 tests; 168 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 164 tests; 162 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS XMLHttpRequestEventTarget interface: existence and properties of interface object
 PASS XMLHttpRequestEventTarget interface object length
@@ -164,11 +164,5 @@
 PASS ProgressEvent interface: new ProgressEvent("type") must inherit property "total" with the proper type
 PASS Node interface: existence and properties of interface object
 PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.worker-expected.txt
index a388bd7..50788e8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/xhr/idlharness.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 170 tests; 168 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 164 tests; 162 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS XMLHttpRequestEventTarget interface: existence and properties of interface object
 PASS XMLHttpRequestEventTarget interface object length
@@ -164,11 +164,5 @@
 PASS ProgressEvent interface: new ProgressEvent("type") must inherit property "total" with the proper type
 PASS Node interface: existence and properties of interface object
 PASS Document interface: existence and properties of interface object
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentFragment interface: existence and properties of interface object
-PASS ShadowRoot interface: existence and properties of interface object
-PASS Element interface: existence and properties of interface object
-PASS CharacterData interface: existence and properties of interface object
-PASS Text interface: existence and properties of interface object
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/access-key-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/access-key-expected.txt
index b6a637dd..96eae4b 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/access-key-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/access-key-expected.txt
@@ -18,7 +18,6 @@
 6 input type reset focussed
 6 input type reset clicked
 7 link clicked
-8 input type associated to legend focussed
 9 input type associated to label around input focussed
 a input type associated to label closed before input focussed
 b area 1 clicked
diff --git a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-access-key-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-access-key-expected.txt
deleted file mode 100644
index 33bce33..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-access-key-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This test checks to see if accesskey attributes work on legend elements.
-
-If the test passes, you should see one line saying "focused" and the text field should have focus.
-
-Information:
-
-focused
diff --git a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-access-key.html b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-access-key.html
deleted file mode 100644
index 58407c23..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-access-key.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-<head>
-<script>
-function log(message)
-{
-    var item = document.createElement("li");
-    item.appendChild(document.createTextNode(message));
-    document.getElementById("console").appendChild(item);
-}
-function test()
-{
-    if (window.testRunner) {
-        testRunner.dumpAsText();
-        eventSender.keyDown("f", "accessKey");
-    }
-}
-</script>
-</head>
-<body onload="test()">
-<p>This test checks to see if accesskey attributes work on legend elements.</p>
-<p>If the test passes, you should see one line saying "focused" and the text field should have focus.</p>
-<hr>
-<p><fieldset><legend accesskey="f">Information:</legend><input onfocus="log('focused')" type="text"></fieldset><p>
-<hr>
-<ol id="console"></ol>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-focus.html b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-focus.html
deleted file mode 100644
index 5925ace..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-focus.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<body>
-<div id="log"></div>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-
-<fieldset>
-<legend id="legend1">Legend</legend>
-<input>
-</fieldset>
-
-<fieldset>
-<legend id="legend2" tabindex=10>Legend</legend>
-<input>
-</fieldset>
-
-<script>
-test(function() {
-    document.getElementById('legend1').focus();
-    assert_equals(document.activeElement.tagName, 'INPUT');
-}, 'focus() for non-focusable LEGEND element delegates focus to the first control in the owner FIELDSET.');
-
-test(function() {
-    document.getElementById('legend2').focus();
-    assert_equals(document.activeElement.tagName, 'LEGEND');
-}, 'focus() for focusable LEGEND should not delgates focus.');
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/focus-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/focus-expected.txt
index 49db0e3..d124766 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/focus-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/focus-expected.txt
@@ -1,10 +1,11 @@
 This test checks to see if focus methods work on a couple types of elements.
 
-If the test passes, you should see a line saying "focused 1", then 2, then 3.
+If the test passes, you should see a line saying "focused 2", then 3.
+
+legend.focus() should not delegate focus.
 
 Legend
 
 Label2 Label3
-focused 1
 focused 2
 focused 3
diff --git a/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input-expected.txt
index b2017e84..2b82905 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input-expected.txt
@@ -6,8 +6,6 @@
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 <input type="text"> focus selection
 This test checks whether the selection is restored, cleared, or set to the full range when using different ways to focus a text field. These results all match Mozilla, except test 6, which selects the whole field contents to match all other cases of keyboard focus. When running manually, please follow the steps below. In the test harness, the test runs automatically.
 
@@ -18,9 +16,9 @@
 5) Click this label, only the word "SUCCESS" should be selected:  
 6) Hit Ctrl-Option-U (or Alt-U on Windows), the whole phrase "SUCCESS and SUCCESS" should be selected:  
 7) , only the word "SUCCESS" should be selected:  
-8)  , the whole phrase "SUCCESS and SUCCESS" should be selected:
+8)  , only the word "SUCCESS" should be selected:
 
-9) Hit Ctrl-Option-I (or Alt-I on Windows), the whole phrase "SUCCESS and SUCCESS" should be selected:
+9) Hit Ctrl-Option-I (or Alt-I on Windows), only the word "SUCCESS" should be selected:
 
 PASS successfullyParsed is true
 
@@ -53,11 +51,11 @@
 PASS seventh.selectionEnd is 18
 PASS seventh.selectionStart is 11
 PASS seventh.selectionEnd is 18
-PASS eighth.selectionStart is 12
-PASS eighth.selectionEnd is 19
-PASS eighth.selectionStart is 0
-PASS eighth.selectionEnd is 19
-PASS ninth.selectionStart is 12
-PASS ninth.selectionEnd is 19
-PASS ninth.selectionStart is 0
-PASS ninth.selectionEnd is 19
+PASS eighth.selectionStart is 11
+PASS eighth.selectionEnd is 18
+PASS eighth.selectionStart is 11
+PASS eighth.selectionEnd is 18
+PASS ninth.selectionStart is 11
+PASS ninth.selectionEnd is 18
+PASS ninth.selectionStart is 11
+PASS ninth.selectionEnd is 18
diff --git a/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input.html b/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input.html
index d7c8c2b..a4c986a 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/focus-selection-input.html
@@ -58,18 +58,18 @@
     shouldBe("seventh.selectionStart", "11");
     shouldBe("seventh.selectionEnd", "18");
 
-    shouldBe("eighth.selectionStart", "12");
-    shouldBe("eighth.selectionEnd", "19");
+    shouldBe("eighth.selectionStart", "11");
+    shouldBe("eighth.selectionEnd", "18");
     var eighthLegend = document.getElementById("eighthLegend");
     eighthLegend.focus();
-    shouldBe("eighth.selectionStart", "0");
-    shouldBe("eighth.selectionEnd", "19");
+    shouldBe("eighth.selectionStart", "11");
+    shouldBe("eighth.selectionEnd", "18");
 
-    shouldBe("ninth.selectionStart", "12");
-    shouldBe("ninth.selectionEnd", "19");
+    shouldBe("ninth.selectionStart", "11");
+    shouldBe("ninth.selectionEnd", "18");
     eventSender.keyDown("I", "accessKey");
-    shouldBe("ninth.selectionStart", "0");
-    shouldBe("ninth.selectionEnd", "19");
+    shouldBe("ninth.selectionStart", "11");
+    shouldBe("ninth.selectionEnd", "18");
 
 }
 </script>
@@ -162,12 +162,12 @@
 
 8) <input type="button" onclick="document.getElementById('eighthLegend').focus()" value="Click this button">
 <fieldset>
-<legend id="eighthLegend">, the whole phrase "SUCCESS and SUCCESS" should be selected:</legend>
-<input type="text" id="eighth" value="SUCCESS and SUCCESS">
+<legend id="eighthLegend">, only the word "SUCCESS" should be selected:</legend>
+<input type="text" id="eighth" value="FAILURE or SUCCESS">
 <script>
     var eighth = document.getElementById("eighth");
     eighth.focus();
-    eighth.setSelectionRange(12, 19);
+    eighth.setSelectionRange(11, 18);
     eighth.blur();
 </script>
 </fieldset>
@@ -175,12 +175,12 @@
 
 
 9) <fieldset>
-<legend id="eighthLegend" accesskey="i">Hit Ctrl-Option-I (or Alt-I on Windows), the whole phrase "SUCCESS and SUCCESS" should be selected:</legend>
-<input type="text" id="ninth" value="SUCCESS and SUCCESS">
+<legend id="ninthLegend" accesskey="i">Hit Ctrl-Option-I (or Alt-I on Windows), only the word "SUCCESS" should be selected:</legend>
+<input type="text" id="ninth" value="FAILURE or SUCCESS">
 <script>
     var ninth = document.getElementById("ninth");
     ninth.focus();
-    ninth.setSelectionRange(12, 19);
+    ninth.setSelectionRange(11, 18);
     ninth.blur();
 </script>
 </fieldset>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/focus-selection-textarea-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/focus-selection-textarea-expected.txt
index 97527fd4..4d89ffe 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/focus-selection-textarea-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/focus-selection-textarea-expected.txt
@@ -6,8 +6,6 @@
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 <textarea> focus selection
 This test checks whether the selection is restored, cleared, or set to the full range when using different ways to focus a text area. These results all match Mozilla. When running manually, please follow the steps below. In the test harness, the test runs automatically.
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/focus.html b/third_party/WebKit/LayoutTests/fast/forms/focus.html
index 79cdc1535..3b963132 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/focus.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/focus.html
@@ -20,7 +20,8 @@
 </head>
 <body onload="test()">
 <p>This test checks to see if focus methods work on a couple types of elements.</p>
-<p>If the test passes, you should see a line saying "focused 1", then 2, then 3.</p>
+<p>If the test passes, you should see a line saying "focused 2", then 3.</p>
+<p>legend.focus() should not delegate focus.</p>
 <hr>
 <p>
 <fieldset><legend id="1">Legend</legend><input onfocus="log('focused 1')" type="text"></fieldset>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/clip/control-clip-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/clip/control-clip-expected.txt
new file mode 100644
index 0000000..4e88c78
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/clip/control-clip-expected.txt
@@ -0,0 +1,54 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutButton BUTTON id='button'",
+          "rect": [8, 110, 200, 30],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMenuList SELECT id='popup'",
+          "rect": [8, 80, 200, 30],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'SUCCESS'",
+          "rect": [76, 117, 64, 16],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "InlineTextBox 'SUCCESS'",
+          "rect": [9, 87, 63, 16],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'FAILURE'",
+          "rect": [81, 117, 54, 16],
+          "reason": "chunk disappeared"
+        },
+        {
+          "object": "InlineTextBox 'FAILURE'",
+          "rect": [9, 87, 54, 16],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media-cross-origin.html b/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media-cross-origin.html
index c1b2e78..95c83ba 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media-cross-origin.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media-cross-origin.html
@@ -17,6 +17,7 @@
   // Set up video
   var video = document.querySelector("video");
   video.src = "http://localhost:8000/media/resources/test.ogv";
+  enableTestMode(video);
 
   video.onloadeddata = t.step_func(function() {
     // Click on the download button
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media.html b/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media.html
index e5a2608f..a46615d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/video-controls-download-button-saves-media.html
@@ -17,6 +17,7 @@
   // Set up video
   var video = document.querySelector("video");
   video.src = "resources/test.ogv";
+  enableTestMode(video);
 
   video.onloadeddata = t.step_func(function() {
     // Click on the download button
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-controls-overflow-menu-download-button.html b/third_party/WebKit/LayoutTests/http/tests/media/video-controls-overflow-menu-download-button.html
index a0b2479..9371fac 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-controls-overflow-menu-download-button.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/video-controls-overflow-menu-download-button.html
@@ -17,6 +17,7 @@
   video.src = "resources/test.ogv";
   video.setAttribute("width", "60");
   video.setAttribute("height", "100");
+  enableTestMode(video);
 
   var controlID = "-internal-media-controls-download-button";
   var downloadButton = mediaControlsElement(internals.shadowRoot(video).firstChild, controlID);
diff --git a/third_party/WebKit/LayoutTests/media/controls/closed-captions-dynamic-update.html b/third_party/WebKit/LayoutTests/media/controls/closed-captions-dynamic-update.html
index dc376bd3..306e1f4 100644
--- a/third_party/WebKit/LayoutTests/media/controls/closed-captions-dynamic-update.html
+++ b/third_party/WebKit/LayoutTests/media/controls/closed-captions-dynamic-update.html
@@ -10,6 +10,7 @@
 <script>
 async_test(t => {
   var video = document.querySelector('video');
+  enableTestMode(video);
 
   video.oncanplaythrough = t.step_func(_ => {
     assert_true(isClosedCaptionsButtonEnabled(video));
diff --git a/third_party/WebKit/LayoutTests/media/controls/closed-captions-on-off.html b/third_party/WebKit/LayoutTests/media/controls/closed-captions-on-off.html
index f742d18..587687b 100644
--- a/third_party/WebKit/LayoutTests/media/controls/closed-captions-on-off.html
+++ b/third_party/WebKit/LayoutTests/media/controls/closed-captions-on-off.html
@@ -9,6 +9,8 @@
   var captions = ['First', 'Second', 'Third'];
   var video = document.querySelector('video');
 
+  enableTestMode(video);
+
   video.oncanplaythrough = t.step_func(_ => {
     var track1 = video.addTextTrack('captions');
     var track2 = video.addTextTrack('captions');
diff --git a/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html b/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html
index bf9ea5c..217b301 100644
--- a/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html
+++ b/third_party/WebKit/LayoutTests/media/controls/closed-captions-single-track.html
@@ -8,6 +8,7 @@
 async_test(t => {
   var captions = ["Caption"];
   var video = document.querySelector("video");
+  enableTestMode(video);
 
   video.oncanplaythrough = t.step_func(_ => {
     var track1 = video.addTextTrack("captions");
diff --git a/third_party/WebKit/LayoutTests/media/controls/closed-captions-switch-track.html b/third_party/WebKit/LayoutTests/media/controls/closed-captions-switch-track.html
index 741714804..2bfb6ba7 100644
--- a/third_party/WebKit/LayoutTests/media/controls/closed-captions-switch-track.html
+++ b/third_party/WebKit/LayoutTests/media/controls/closed-captions-switch-track.html
@@ -11,6 +11,8 @@
   var trackLanguages = ['en', 'ru', 'fr', 'jp', 'de'];
   var trackCueText = ['English', 'Russian', 'French', 'Japanese', 'German'];
 
+  enableTestMode(video);
+
   video.oncanplaythrough = t.step_func(_ => {
     for (var i = 0; i < trackLanguages.length; i++) {
       var track = video.addTextTrack('captions', trackCueText[i], trackLanguages[i]);
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-overlay-closes-overflow-menu.html b/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-overlay-closes-overflow-menu.html
index 0948e16..2d4e7c0 100644
--- a/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-overlay-closes-overflow-menu.html
+++ b/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-overlay-closes-overflow-menu.html
@@ -38,14 +38,12 @@
     const overlayCoordinates = coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
     singleTapAtCoordinates(overlayCoordinates[0] + 1,
                            overlayCoordinates[1] + 1,
-                           t.step_func(checkOverflowMenuDisappeared));
+                           t.step_func_done(checkOverflowMenuDisappeared));
   }
 
   function checkOverflowMenuDisappeared() {
     // The overflow menu should disappear.
-    setTimeout(t.step_func_done(() => {
-      assert_false(isControlVisible(menu));
-    }));
+    assert_false(isControlVisible(menu));
   }
 });
 </script>
diff --git a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-item.html b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-item.html
index 1c0233e..0fc0581 100644
--- a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-item.html
+++ b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-item.html
@@ -8,6 +8,7 @@
 async_test(t => {
   const video = document.querySelector('video');
   video.src = '../content/test.ogv';
+  enableTestMode(video);
   const track = video.addTextTrack('captions');
 
   video.onloadeddata = t.step_func(() => {
diff --git a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html
index e26e8e5..86ef1d0f 100644
--- a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html
+++ b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html
@@ -7,6 +7,7 @@
 <script>
 async_test(t => {
   const video = document.querySelector('video');
+  enableTestMode(video);
   video.src = '../content/test.ogv';
   const track = video.addTextTrack('captions');
 
@@ -21,10 +22,8 @@
 
       // Click anywhere outside the overflow menu should close overflow list.
       const coords = coordinatesOutsideElement(menu);
-      singleTapAtCoordinates(coords[0], coords[1], t.step_func(() => {
-        setTimeout(t.step_func_done(() => {
-          assert_equals(getComputedStyle(menu).display, 'none');
-        }));
+      singleTapAtCoordinates(coords[0], coords[1], t.step_func_done(() => {
+        assert_equals(getComputedStyle(menu).display, 'none');
       }));
     }));
   });
diff --git a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside.html b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside.html
index 6b0757a..eb468382 100644
--- a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside.html
+++ b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-outside.html
@@ -7,6 +7,7 @@
 <script>
 async_test(t => {
   const video = document.querySelector('video');
+  enableTestMode(video);
   video.src = '../content/test.ogv';
   const track = video.addTextTrack('captions');
 
@@ -18,10 +19,8 @@
 
       // Click anywhere outside the overflow menu should close overflow list.
       const coords = coordinatesOutsideElement(menu);
-      singleTapAtCoordinates(coords[0], coords[1], t.step_func(() =>{
-        setTimeout(t.step_func_done(() => {
-          assert_equals(getComputedStyle(menu).display, 'none');
-        }));
+      singleTapAtCoordinates(coords[0], coords[1], t.step_func_done(() =>{
+        assert_equals(getComputedStyle(menu).display, 'none');
       }));
     }));
   });
diff --git a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-panel.html b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-panel.html
index c9890cd..1c7418a 100644
--- a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-panel.html
+++ b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-hide-on-click-panel.html
@@ -7,6 +7,7 @@
 <script>
 async_test(t => {
   const video = document.querySelector('video');
+  enableTestMode(video);
   video.src = '../content/test.ogv';
   const track = video.addTextTrack('captions');
 
@@ -16,10 +17,8 @@
     singleTapOnControl(overflowButton(video), t.step_func(() => {
       assert_not_equals(getComputedStyle(menu).display, 'none');
 
-      singleTapOnControl(timelineElement(video), t.step_func(() => {
-        setTimeout(t.step_func_done(() => {
-          assert_equals(getComputedStyle(menu).display, 'none');
-        }));
+      singleTapOnControl(timelineElement(video), t.step_func_done(() => {
+        assert_equals(getComputedStyle(menu).display, 'none');
       }));
     }));
   });
diff --git a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-pointer-selection.html b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-pointer-selection.html
index ad4965b..40c4246 100644
--- a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-pointer-selection.html
+++ b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-pointer-selection.html
@@ -55,6 +55,7 @@
   assert_equals(video.textTracks.length, 2);
 
   document.body.appendChild(video);
+  enableTestMode(video);
 
   video.addEventListener('loadedmetadata', t.step_func(() => {
     assert_true(isVisible(overflowButton(video)));
diff --git a/third_party/WebKit/LayoutTests/media/controls/overflow-menu-toggle-class-for-animation.html b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-toggle-class-for-animation.html
new file mode 100644
index 0000000..f5bb6929
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/overflow-menu-toggle-class-for-animation.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<title>Media Controls: overflow menu toggle class for animation.</title>
+<script src='../../resources/testharness.js'></script>
+<script src='../../resources/testharnessreport.js'></script>
+<script src='../media-controls.js'></script>
+<video controls width=400></video>
+<script>
+async_test(t => {
+  const video = document.querySelector('video');
+  enableTestMode(video);
+  video.src = '../content/test.ogv';
+  video.addTextTrack('captions', 'foo');
+  video.addTextTrack('captions', 'bar');
+
+  video.onloadeddata = t.step_func(() => {
+    const menu = overflowMenu(video);
+    const captionsList = textTrackMenu(video);
+
+    // Open overflow => close overflow
+    expectAllMenuClosed();
+    singleTapOnControl(overflowButton(video), t.step_func(() => {
+      expectOpenMenu();
+
+      singleTapOutsideControl(menu, t.step_func(() => {
+        expectAllMenuClosed();
+        // End of scenario
+
+        // Open overflow => open captions list => close captions list
+        clickCaptionButton(video, t.step_func(() => {
+          expectOpenMenu();
+
+          singleTapOutsideControl(captionsList, t.step_func(() => {
+            expectAllMenuClosed();
+            // End of scenario
+
+            // Open overflow => open captions list => select track
+            clickTextTrackAtIndex(video, 0, t.step_func(() => {
+              expectAllMenuClosed();
+              // End of scenario
+
+              // Open overflow => open captions list => click back to overflow => close overflow
+              clickCaptionButton(video, t.step_func(() => {
+                expectOpenMenu();
+                const trackListHeader = textTrackListHeader(video);
+
+                singleTapOnControl(trackListHeader, t.step_func(() => {
+                  expectOpenMenu();
+
+                  singleTapOutsideControl(menu, t.step_func_done(() => {
+                    expectAllMenuClosed();
+                    // End of scenario
+                  }));
+                }));
+              }));
+            }));
+          }));
+        }));
+      }));
+    }));
+
+    function expectClosedMenu() {
+      assert_true(menu.classList.contains('closed'));
+    }
+
+    function expectOpenMenu() {
+      assert_false(menu.classList.contains('closed'));
+    }
+
+    function expectAllMenuClosed() {
+      assert_equals(getComputedStyle(menu).display, 'none');
+      assert_equals(getComputedStyle(captionsList).display, 'none');
+      expectClosedMenu();
+    }
+  });
+
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/media/controls/text-track-menu-keyboard-navigation.html b/third_party/WebKit/LayoutTests/media/controls/text-track-menu-keyboard-navigation.html
index 94376151..ee1a449 100644
--- a/third_party/WebKit/LayoutTests/media/controls/text-track-menu-keyboard-navigation.html
+++ b/third_party/WebKit/LayoutTests/media/controls/text-track-menu-keyboard-navigation.html
@@ -66,9 +66,11 @@
   assert_equals(video.textTracks.length, 2);
 
   document.body.appendChild(video);
+  enableTestMode(video);
 
   video.addEventListener('loadedmetadata', t.step_func(() => {
     assert_true(isVisible(overflowButton(video)));
+
     openOverflowAndClickButton(video, captionsOverflowItem(video), t.step_func_done(() => {
       const menu = textTrackMenu(video);
       assert_true(isVisible(menu));
diff --git a/third_party/WebKit/LayoutTests/media/controls/text-track-menu-pointer-selection.html b/third_party/WebKit/LayoutTests/media/controls/text-track-menu-pointer-selection.html
index 7a2b0c7..797c738 100644
--- a/third_party/WebKit/LayoutTests/media/controls/text-track-menu-pointer-selection.html
+++ b/third_party/WebKit/LayoutTests/media/controls/text-track-menu-pointer-selection.html
@@ -55,9 +55,11 @@
   assert_equals(video.textTracks.length, 2);
 
   document.body.appendChild(video);
+  enableTestMode(video);
 
   video.addEventListener('loadedmetadata', t.step_func(() => {
     assert_true(isVisible(overflowButton(video)));
+
     openOverflowAndClickButton(video, captionsOverflowItem(video), t.step_func(() => {
       const menu = textTrackMenu(video);
       assert_true(isVisible(menu));
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js
index ce3fde540..5a9c225 100644
--- a/third_party/WebKit/LayoutTests/media/media-controls.js
+++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -106,6 +106,14 @@
   return element;
 }
 
+function textTrackListHeader(video)
+{
+  var element = textTrackMenu(video).childNodes[0];
+  if (!element)
+    throw 'Failed to find the track list header'
+  return element;
+}
+
 function overflowMenu(video)
 {
   var controlID = '-internal-media-controls-overflow-menu-list';
@@ -518,6 +526,7 @@
 }
 
 function singleTapAtCoordinates(xPos, yPos, callback) {
+  let delayCallback = function() { setTimeout(callback); };
   chrome.gpuBenchmarking.pointerActionSequence([
     {
       source: 'mouse',
@@ -526,7 +535,12 @@
         { name: 'pointerUp' }
       ]
     }
-  ], callback);
+  ], delayCallback);
+}
+
+function singleTapOutsideControl(control, callback) {
+  const coordinates = coordinatesOutsideElement(control);
+  singleTapAtCoordinates(coordinates[0], coordinates[1], callback);
 }
 
 function singleTapOnControl(control, callback) {
diff --git a/third_party/WebKit/LayoutTests/media/picture-in-picture/controls/picture-in-picture-button.html b/third_party/WebKit/LayoutTests/media/picture-in-picture/controls/picture-in-picture-button.html
index 6356d2f6..6560b2f 100644
--- a/third_party/WebKit/LayoutTests/media/picture-in-picture/controls/picture-in-picture-button.html
+++ b/third_party/WebKit/LayoutTests/media/picture-in-picture/controls/picture-in-picture-button.html
@@ -13,6 +13,7 @@
 
   var video = document.querySelector("video");
   video.src = "../../content/test.ogv";
+  enableTestMode(video);
 
   video.onloadedmetadata = t.step_func(function() {
     assert_true(isPictureInPictureButtonEnabled(video), "button should exist");
diff --git a/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial-sizing.html b/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial-sizing.html
index d05c14c..f40aa09 100644
--- a/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial-sizing.html
+++ b/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial-sizing.html
@@ -16,6 +16,7 @@
 ];
 
 const video = document.getElementsByTagName('video')[0];
+enableTestMode(video);
 
 function runSizingTest(t, num) {
   if (num >= testCases.length)
diff --git a/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial.html b/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial.html
index 15c6745..61c8fe8 100644
--- a/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial.html
+++ b/third_party/WebKit/LayoutTests/media/picture-in-picture/picture-in-picture-interstitial.html
@@ -13,6 +13,7 @@
 
   var video = document.querySelector("video");
   video.src = "../content/test.ogv";
+  enableTestMode(video);
 
   video.onloadedmetadata = t.step_func(function() {
     assert_true(isPictureInPictureButtonEnabled(video), "button should exist");
diff --git a/third_party/WebKit/LayoutTests/media/track/text-track-selection-menu-add-track.html b/third_party/WebKit/LayoutTests/media/track/text-track-selection-menu-add-track.html
index 985d39a..f50edcd 100644
--- a/third_party/WebKit/LayoutTests/media/track/text-track-selection-menu-add-track.html
+++ b/third_party/WebKit/LayoutTests/media/track/text-track-selection-menu-add-track.html
@@ -11,6 +11,7 @@
 async_test(function(t) {
     var trackCueText = "Bonjour";
     var video = document.querySelector("video");
+    enableTestMode(video);
 
     video.oncanplaythrough = t.step_func(function() {
         var track = video.addTextTrack("captions", "French", "fr");
diff --git a/third_party/WebKit/LayoutTests/media/video-controls-labels.html b/third_party/WebKit/LayoutTests/media/video-controls-labels.html
index 6c7ade9..7a7febe 100644
--- a/third_party/WebKit/LayoutTests/media/video-controls-labels.html
+++ b/third_party/WebKit/LayoutTests/media/video-controls-labels.html
@@ -11,6 +11,7 @@
 <script>
 async_test(function(t) {
     var video = document.querySelector("video");
+    enableTestMode(video);
 
     video.oncanplaythrough = t.step_func(function() {
       clickCaptionButton(video, t.step_func_done(function() {
diff --git a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-closed-captions-button.html b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-closed-captions-button.html
index aa22213..20ed698 100644
--- a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-closed-captions-button.html
+++ b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-closed-captions-button.html
@@ -19,6 +19,8 @@
   video.addTextTrack("captions");
   video.addTextTrack("captions");
 
+  enableTestMode(video);
+
   video.onloadeddata = t.step_func_done(function() {
     var overflowList = getOverflowList(video);
     var overflowMenu = getOverflowMenuButton(video);
diff --git a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-fullscreen-button.html b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-fullscreen-button.html
index d5708b9..8982077 100644
--- a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-fullscreen-button.html
+++ b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-fullscreen-button.html
@@ -16,6 +16,8 @@
   video.setAttribute("width", "60");
   video.setAttribute("height", "100");
 
+  enableTestMode(video);
+
   window.addEventListener("load", t.step_func(function() {
     var overflowList = getOverflowList(video);
     var overflowMenu = getOverflowMenuButton(video);
diff --git a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-mute-button.html b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-mute-button.html
index 5e3d1a99..890c81a0 100644
--- a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-mute-button.html
+++ b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-mute-button.html
@@ -16,6 +16,8 @@
   video.setAttribute("width", "60");
   video.setAttribute("height", "100");
 
+  enableTestMode(video);
+
   video.onloadeddata = t.step_func_done(function() {
     var overflowList = getOverflowList(video);
     var overflowMenu = getOverflowMenuButton(video);
diff --git a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-play-button.html b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-play-button.html
index c3ee7235..30078aa 100644
--- a/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-play-button.html
+++ b/third_party/WebKit/LayoutTests/media/video-controls-overflow-menu-play-button.html
@@ -16,6 +16,8 @@
   video.setAttribute("width", "60");
   video.setAttribute("height", "100");
 
+  enableTestMode(video);
+
   video.onloadeddata = t.step_func_done(function() {
     var overflowList = getOverflowList(video);
     var overflowMenu = getOverflowMenuButton(video);
diff --git a/third_party/WebKit/LayoutTests/media/video-controls-track-selection-menu.html b/third_party/WebKit/LayoutTests/media/video-controls-track-selection-menu.html
index 5df3723c..6a1a74e 100644
--- a/third_party/WebKit/LayoutTests/media/video-controls-track-selection-menu.html
+++ b/third_party/WebKit/LayoutTests/media/video-controls-track-selection-menu.html
@@ -11,6 +11,7 @@
 <script>
 async_test(function(t) {
     var video = document.querySelector("video");
+    enableTestMode(video);
 
     var trackElements = document.querySelectorAll("track");
     var textTracks = video.textTracks;
diff --git a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/speech-api/idlharness.window-expected.txt
deleted file mode 100644
index e0bc129a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/speech-api/idlharness.window-expected.txt
+++ /dev/null
@@ -1,227 +0,0 @@
-This is a testharness.js-based test.
-Found 223 tests; 66 PASS, 157 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL idl_test setup promise_test: Unhandled rejection with value: "Timed out waiting for voice"
-PASS Partial interface Window: original interface defined
-FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object length assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object name assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute grammars assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute lang assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute continuous assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute interimResults assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute maxAlternatives assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute serviceURI assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation start() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation stop() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation abort() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudiostart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudioend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onresult assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onnomatch assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onerror assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition must be primary interface of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL Stringification of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "grammars" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "continuous" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "interimResults" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "maxAlternatives" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "serviceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "start()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "abort()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudiostart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudioend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onresult" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onnomatch" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onerror" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute error assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute message assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object length assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object name assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute transcript assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute confidence assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object name assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute isFinal assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object name assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute resultIndex assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute results assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute interpretation assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute emma assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechGrammar interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object length assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object name assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute src assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute weight assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar must be primary interface of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL Stringification of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "src" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "weight" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammarList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object name assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: attribute length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromURI(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromString(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList must be primary interface of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL Stringification of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "length" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "item(unsigned long)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling item(unsigned long) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromURI(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromURI(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromString(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromString(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechSynthesis interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object length assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object name assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute pending assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute speaking assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute paused assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute onvoiceschanged assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation speak(SpeechSynthesisUtterance) assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation cancel() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation pause() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation resume() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation getVoices() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis must be primary interface of speechSynthesis assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-PASS Stringification of speechSynthesis
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pending" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speaking" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "paused" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "onvoiceschanged" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speak(SpeechSynthesisUtterance)" with the proper type
-PASS SpeechSynthesis interface: calling speak(SpeechSynthesisUtterance) on speechSynthesis with too few arguments must throw TypeError
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "cancel()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pause()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "resume()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "getVoices()" with the proper type
-PASS SpeechSynthesisUtterance interface: existence and properties of interface object
-PASS SpeechSynthesisUtterance interface object length
-PASS SpeechSynthesisUtterance interface object name
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisUtterance interface: attribute text
-PASS SpeechSynthesisUtterance interface: attribute lang
-PASS SpeechSynthesisUtterance interface: attribute voice
-PASS SpeechSynthesisUtterance interface: attribute volume
-PASS SpeechSynthesisUtterance interface: attribute rate
-PASS SpeechSynthesisUtterance interface: attribute pitch
-PASS SpeechSynthesisUtterance interface: attribute onstart
-PASS SpeechSynthesisUtterance interface: attribute onend
-PASS SpeechSynthesisUtterance interface: attribute onerror
-PASS SpeechSynthesisUtterance interface: attribute onpause
-PASS SpeechSynthesisUtterance interface: attribute onresume
-PASS SpeechSynthesisUtterance interface: attribute onmark
-PASS SpeechSynthesisUtterance interface: attribute onboundary
-PASS SpeechSynthesisUtterance must be primary interface of new SpeechSynthesisUtterance()
-PASS Stringification of new SpeechSynthesisUtterance()
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "text" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "lang" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "voice" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "volume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "rate" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "pitch" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onstart" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onend" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onerror" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onpause" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onresume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onmark" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onboundary" with the proper type
-PASS SpeechSynthesisEvent interface: existence and properties of interface object
-PASS SpeechSynthesisEvent interface object length
-PASS SpeechSynthesisEvent interface object name
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisEvent interface: attribute utterance
-PASS SpeechSynthesisEvent interface: attribute charIndex
-PASS SpeechSynthesisEvent interface: attribute elapsedTime
-PASS SpeechSynthesisEvent interface: attribute name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface object
-PASS SpeechSynthesisErrorEvent interface object length
-PASS SpeechSynthesisErrorEvent interface object name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisErrorEvent interface: attribute error
-FAIL SpeechSynthesisVoice interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object length assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute voiceURI assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute lang assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute localService assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute default assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice must be primary interface of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL Stringification of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "voiceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "name" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "localService" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "default" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-PASS Window interface: attribute speechSynthesis
-PASS Window interface: self must inherit property "speechSynthesis" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/speech-api/idlharness.window-expected.txt
deleted file mode 100644
index e0bc129a..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/speech-api/idlharness.window-expected.txt
+++ /dev/null
@@ -1,227 +0,0 @@
-This is a testharness.js-based test.
-Found 223 tests; 66 PASS, 157 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL idl_test setup promise_test: Unhandled rejection with value: "Timed out waiting for voice"
-PASS Partial interface Window: original interface defined
-FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object length assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object name assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute grammars assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute lang assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute continuous assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute interimResults assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute maxAlternatives assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute serviceURI assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation start() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation stop() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation abort() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudiostart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudioend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onresult assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onnomatch assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onerror assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition must be primary interface of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL Stringification of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "grammars" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "continuous" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "interimResults" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "maxAlternatives" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "serviceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "start()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "abort()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudiostart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudioend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onresult" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onnomatch" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onerror" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute error assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute message assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object length assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object name assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute transcript assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute confidence assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object name assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute isFinal assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object name assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute resultIndex assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute results assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute interpretation assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute emma assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechGrammar interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object length assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object name assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute src assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute weight assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar must be primary interface of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL Stringification of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "src" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "weight" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammarList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object name assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: attribute length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromURI(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromString(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList must be primary interface of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL Stringification of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "length" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "item(unsigned long)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling item(unsigned long) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromURI(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromURI(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromString(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromString(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechSynthesis interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object length assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object name assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute pending assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute speaking assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute paused assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute onvoiceschanged assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation speak(SpeechSynthesisUtterance) assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation cancel() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation pause() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation resume() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation getVoices() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis must be primary interface of speechSynthesis assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-PASS Stringification of speechSynthesis
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pending" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speaking" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "paused" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "onvoiceschanged" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speak(SpeechSynthesisUtterance)" with the proper type
-PASS SpeechSynthesis interface: calling speak(SpeechSynthesisUtterance) on speechSynthesis with too few arguments must throw TypeError
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "cancel()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pause()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "resume()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "getVoices()" with the proper type
-PASS SpeechSynthesisUtterance interface: existence and properties of interface object
-PASS SpeechSynthesisUtterance interface object length
-PASS SpeechSynthesisUtterance interface object name
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisUtterance interface: attribute text
-PASS SpeechSynthesisUtterance interface: attribute lang
-PASS SpeechSynthesisUtterance interface: attribute voice
-PASS SpeechSynthesisUtterance interface: attribute volume
-PASS SpeechSynthesisUtterance interface: attribute rate
-PASS SpeechSynthesisUtterance interface: attribute pitch
-PASS SpeechSynthesisUtterance interface: attribute onstart
-PASS SpeechSynthesisUtterance interface: attribute onend
-PASS SpeechSynthesisUtterance interface: attribute onerror
-PASS SpeechSynthesisUtterance interface: attribute onpause
-PASS SpeechSynthesisUtterance interface: attribute onresume
-PASS SpeechSynthesisUtterance interface: attribute onmark
-PASS SpeechSynthesisUtterance interface: attribute onboundary
-PASS SpeechSynthesisUtterance must be primary interface of new SpeechSynthesisUtterance()
-PASS Stringification of new SpeechSynthesisUtterance()
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "text" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "lang" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "voice" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "volume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "rate" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "pitch" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onstart" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onend" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onerror" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onpause" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onresume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onmark" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onboundary" with the proper type
-PASS SpeechSynthesisEvent interface: existence and properties of interface object
-PASS SpeechSynthesisEvent interface object length
-PASS SpeechSynthesisEvent interface object name
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisEvent interface: attribute utterance
-PASS SpeechSynthesisEvent interface: attribute charIndex
-PASS SpeechSynthesisEvent interface: attribute elapsedTime
-PASS SpeechSynthesisEvent interface: attribute name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface object
-PASS SpeechSynthesisErrorEvent interface object length
-PASS SpeechSynthesisErrorEvent interface object name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisErrorEvent interface: attribute error
-FAIL SpeechSynthesisVoice interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object length assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute voiceURI assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute lang assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute localService assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute default assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice must be primary interface of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL Stringification of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "voiceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "name" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "localService" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "default" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-PASS Window interface: attribute speechSynthesis
-PASS Window interface: self must inherit property "speechSynthesis" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/external/wpt/speech-api/idlharness.window-expected.txt
deleted file mode 100644
index e0bc129a..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/speech-api/idlharness.window-expected.txt
+++ /dev/null
@@ -1,227 +0,0 @@
-This is a testharness.js-based test.
-Found 223 tests; 66 PASS, 157 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL idl_test setup promise_test: Unhandled rejection with value: "Timed out waiting for voice"
-PASS Partial interface Window: original interface defined
-FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object length assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object name assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute grammars assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute lang assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute continuous assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute interimResults assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute maxAlternatives assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute serviceURI assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation start() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation stop() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation abort() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudiostart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudioend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onresult assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onnomatch assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onerror assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition must be primary interface of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL Stringification of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "grammars" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "continuous" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "interimResults" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "maxAlternatives" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "serviceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "start()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "abort()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudiostart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudioend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onresult" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onnomatch" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onerror" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute error assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute message assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object length assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object name assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute transcript assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute confidence assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object name assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute isFinal assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object name assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute resultIndex assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute results assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute interpretation assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute emma assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechGrammar interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object length assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object name assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute src assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute weight assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar must be primary interface of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL Stringification of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "src" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "weight" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammarList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object name assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: attribute length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromURI(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromString(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList must be primary interface of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL Stringification of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "length" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "item(unsigned long)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling item(unsigned long) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromURI(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromURI(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromString(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromString(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechSynthesis interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object length assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object name assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute pending assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute speaking assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute paused assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute onvoiceschanged assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation speak(SpeechSynthesisUtterance) assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation cancel() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation pause() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation resume() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation getVoices() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis must be primary interface of speechSynthesis assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-PASS Stringification of speechSynthesis
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pending" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speaking" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "paused" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "onvoiceschanged" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speak(SpeechSynthesisUtterance)" with the proper type
-PASS SpeechSynthesis interface: calling speak(SpeechSynthesisUtterance) on speechSynthesis with too few arguments must throw TypeError
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "cancel()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pause()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "resume()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "getVoices()" with the proper type
-PASS SpeechSynthesisUtterance interface: existence and properties of interface object
-PASS SpeechSynthesisUtterance interface object length
-PASS SpeechSynthesisUtterance interface object name
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisUtterance interface: attribute text
-PASS SpeechSynthesisUtterance interface: attribute lang
-PASS SpeechSynthesisUtterance interface: attribute voice
-PASS SpeechSynthesisUtterance interface: attribute volume
-PASS SpeechSynthesisUtterance interface: attribute rate
-PASS SpeechSynthesisUtterance interface: attribute pitch
-PASS SpeechSynthesisUtterance interface: attribute onstart
-PASS SpeechSynthesisUtterance interface: attribute onend
-PASS SpeechSynthesisUtterance interface: attribute onerror
-PASS SpeechSynthesisUtterance interface: attribute onpause
-PASS SpeechSynthesisUtterance interface: attribute onresume
-PASS SpeechSynthesisUtterance interface: attribute onmark
-PASS SpeechSynthesisUtterance interface: attribute onboundary
-PASS SpeechSynthesisUtterance must be primary interface of new SpeechSynthesisUtterance()
-PASS Stringification of new SpeechSynthesisUtterance()
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "text" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "lang" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "voice" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "volume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "rate" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "pitch" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onstart" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onend" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onerror" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onpause" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onresume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onmark" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onboundary" with the proper type
-PASS SpeechSynthesisEvent interface: existence and properties of interface object
-PASS SpeechSynthesisEvent interface object length
-PASS SpeechSynthesisEvent interface object name
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisEvent interface: attribute utterance
-PASS SpeechSynthesisEvent interface: attribute charIndex
-PASS SpeechSynthesisEvent interface: attribute elapsedTime
-PASS SpeechSynthesisEvent interface: attribute name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface object
-PASS SpeechSynthesisErrorEvent interface object length
-PASS SpeechSynthesisErrorEvent interface object name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisErrorEvent interface: attribute error
-FAIL SpeechSynthesisVoice interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object length assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute voiceURI assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute lang assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute localService assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute default assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice must be primary interface of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL Stringification of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "voiceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "name" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "localService" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "default" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-PASS Window interface: attribute speechSynthesis
-PASS Window interface: self must inherit property "speechSynthesis" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/virtual/speech-with-unified-autoplay/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/speech-with-unified-autoplay/external/wpt/speech-api/idlharness.window-expected.txt
deleted file mode 100644
index e0bc129a..0000000
--- a/third_party/WebKit/LayoutTests/virtual/speech-with-unified-autoplay/external/wpt/speech-api/idlharness.window-expected.txt
+++ /dev/null
@@ -1,227 +0,0 @@
-This is a testharness.js-based test.
-Found 223 tests; 66 PASS, 157 FAIL, 0 TIMEOUT, 0 NOTRUN.
-FAIL idl_test setup promise_test: Unhandled rejection with value: "Timed out waiting for voice"
-PASS Partial interface Window: original interface defined
-FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object length assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface object name assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute grammars assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute lang assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute continuous assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute interimResults assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute maxAlternatives assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute serviceURI assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation start() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation stop() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: operation abort() assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudiostart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onspeechend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onsoundend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onaudioend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onresult assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onnomatch assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onerror assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onstart assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition interface: attribute onend assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
-FAIL SpeechRecognition must be primary interface of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL Stringification of new SpeechRecognition() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "grammars" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "continuous" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "interimResults" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "maxAlternatives" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "serviceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "start()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "abort()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudiostart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onspeechend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onsoundend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onaudioend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onresult" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onnomatch" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onerror" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognition interface: new SpeechRecognition() must inherit property "onend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechRecognition is not defined"
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute error assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionErrorEvent interface: attribute message assert_own_property: self does not have own property "SpeechRecognitionErrorEvent" expected property "SpeechRecognitionErrorEvent" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object length assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface object name assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute transcript assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionAlternative interface: attribute confidence assert_own_property: self does not have own property "SpeechRecognitionAlternative" expected property "SpeechRecognitionAlternative" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface object name assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResult interface: attribute isFinal assert_own_property: self does not have own property "SpeechRecognitionResult" expected property "SpeechRecognitionResult" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface object name assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: attribute length assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionResultList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechRecognitionResultList" expected property "SpeechRecognitionResultList" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object length assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface object name assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute resultIndex assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute results assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute interpretation assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechRecognitionEvent interface: attribute emma assert_own_property: self does not have own property "SpeechRecognitionEvent" expected property "SpeechRecognitionEvent" missing
-FAIL SpeechGrammar interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object length assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface object name assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute src assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar interface: attribute weight assert_own_property: self does not have own property "SpeechGrammar" expected property "SpeechGrammar" missing
-FAIL SpeechGrammar must be primary interface of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL Stringification of new SpeechGrammar() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "src" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammar interface: new SpeechGrammar() must inherit property "weight" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammar is not defined"
-FAIL SpeechGrammarList interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface object name assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: attribute length assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation item(unsigned long) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromURI(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList interface: operation addFromString(DOMString, float) assert_own_property: self does not have own property "SpeechGrammarList" expected property "SpeechGrammarList" missing
-FAIL SpeechGrammarList must be primary interface of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL Stringification of new SpeechGrammarList() assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "length" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "item(unsigned long)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling item(unsigned long) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromURI(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromURI(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: new SpeechGrammarList() must inherit property "addFromString(DOMString, float)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechGrammarList interface: calling addFromString(DOMString, float) on new SpeechGrammarList() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: SpeechGrammarList is not defined"
-FAIL SpeechSynthesis interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object length assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface object name assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute pending assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute speaking assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute paused assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: attribute onvoiceschanged assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation speak(SpeechSynthesisUtterance) assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation cancel() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation pause() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation resume() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis interface: operation getVoices() assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-FAIL SpeechSynthesis must be primary interface of speechSynthesis assert_own_property: self does not have own property "SpeechSynthesis" expected property "SpeechSynthesis" missing
-PASS Stringification of speechSynthesis
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pending" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speaking" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "paused" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "onvoiceschanged" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "speak(SpeechSynthesisUtterance)" with the proper type
-PASS SpeechSynthesis interface: calling speak(SpeechSynthesisUtterance) on speechSynthesis with too few arguments must throw TypeError
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "cancel()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "pause()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "resume()" with the proper type
-PASS SpeechSynthesis interface: speechSynthesis must inherit property "getVoices()" with the proper type
-PASS SpeechSynthesisUtterance interface: existence and properties of interface object
-PASS SpeechSynthesisUtterance interface object length
-PASS SpeechSynthesisUtterance interface object name
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisUtterance interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisUtterance interface: attribute text
-PASS SpeechSynthesisUtterance interface: attribute lang
-PASS SpeechSynthesisUtterance interface: attribute voice
-PASS SpeechSynthesisUtterance interface: attribute volume
-PASS SpeechSynthesisUtterance interface: attribute rate
-PASS SpeechSynthesisUtterance interface: attribute pitch
-PASS SpeechSynthesisUtterance interface: attribute onstart
-PASS SpeechSynthesisUtterance interface: attribute onend
-PASS SpeechSynthesisUtterance interface: attribute onerror
-PASS SpeechSynthesisUtterance interface: attribute onpause
-PASS SpeechSynthesisUtterance interface: attribute onresume
-PASS SpeechSynthesisUtterance interface: attribute onmark
-PASS SpeechSynthesisUtterance interface: attribute onboundary
-PASS SpeechSynthesisUtterance must be primary interface of new SpeechSynthesisUtterance()
-PASS Stringification of new SpeechSynthesisUtterance()
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "text" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "lang" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "voice" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "volume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "rate" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "pitch" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onstart" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onend" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onerror" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onpause" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onresume" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onmark" with the proper type
-PASS SpeechSynthesisUtterance interface: new SpeechSynthesisUtterance() must inherit property "onboundary" with the proper type
-PASS SpeechSynthesisEvent interface: existence and properties of interface object
-PASS SpeechSynthesisEvent interface object length
-PASS SpeechSynthesisEvent interface object name
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisEvent interface: attribute utterance
-PASS SpeechSynthesisEvent interface: attribute charIndex
-PASS SpeechSynthesisEvent interface: attribute elapsedTime
-PASS SpeechSynthesisEvent interface: attribute name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface object
-PASS SpeechSynthesisErrorEvent interface object length
-PASS SpeechSynthesisErrorEvent interface object name
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS SpeechSynthesisErrorEvent interface: attribute error
-FAIL SpeechSynthesisVoice interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object length assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface object name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute voiceURI assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute lang assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute localService assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice interface: attribute default assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
-FAIL SpeechSynthesisVoice must be primary interface of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL Stringification of voice assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "voiceURI" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "name" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "lang" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "localService" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-FAIL SpeechSynthesisVoice interface: voice must inherit property "default" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: voice is not defined"
-PASS Window interface: attribute speechSynthesis
-PASS Window interface: self must inherit property "speechSynthesis" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt
index 0feb337..4ccb15b 100644
--- a/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt
@@ -32,7 +32,6 @@
 PASS HTMLVideoElement interface: video must inherit property "onenterpictureinpicture" with the proper type
 PASS HTMLVideoElement interface: video must inherit property "onleavepictureinpicture" with the proper type
 PASS HTMLVideoElement interface: video must inherit property "disablePictureInPicture" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS DocumentOrShadowRoot interface: document must inherit property "pictureInPictureElement" with the proper type
 PASS Document interface: attribute pictureInPictureEnabled
 PASS Document interface: operation exitPictureInPicture()
@@ -40,6 +39,5 @@
 PASS Document interface: document must inherit property "pictureInPictureEnabled" with the proper type
 PASS Document interface: document must inherit property "exitPictureInPicture()" with the proper type
 PASS Document interface: document must inherit property "pictureInPictureElement" with the proper type
-PASS ShadowRoot interface: attribute pictureInPictureElement
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 197432e..52f5d93 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -36,7 +36,7 @@
     "indexeddb/indexeddb_key_path.cc",
     "indexeddb/indexeddb_key_range.cc",
     "indexeddb/indexeddb_metadata.cc",
-    "indexeddb/indexeddb_mojom_traits.cc",
+    "indexeddb/indexeddb_struct_traits.cc",
     "manifest/manifest.cc",
     "manifest/manifest_icon_selector.cc",
     "messaging/cloneable_message.cc",
diff --git a/third_party/blink/common/indexeddb/OWNERS b/third_party/blink/common/indexeddb/OWNERS
index 4d50d63..3b5f7f5 100644
--- a/third_party/blink/common/indexeddb/OWNERS
+++ b/third_party/blink/common/indexeddb/OWNERS
@@ -1,7 +1,7 @@
 file://content/browser/indexed_db/OWNERS
 
-per-file *_mojom_traits*.*=set noparent
-per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=set noparent
+per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
 per-file *.typemap=set noparent
 per-file *.typemap=file://ipc/SECURITY_OWNERS
 
diff --git a/third_party/blink/common/indexeddb/indexeddb_key.cc b/third_party/blink/common/indexeddb/indexeddb_key.cc
index 022e1f2f..9f5e6fe2 100644
--- a/third_party/blink/common/indexeddb/indexeddb_key.cc
+++ b/third_party/blink/common/indexeddb/indexeddb_key.cc
@@ -23,10 +23,10 @@
 // Very rough estimate of minimum key size overhead.
 const size_t kOverheadSize = 16;
 
-size_t CalculateArraySize(const IndexedDBKey::KeyArray& keys) {
+static size_t CalculateArraySize(const IndexedDBKey::KeyArray& keys) {
   size_t size(0);
-  for (const auto& key : keys)
-    size += key.size_estimate();
+  for (size_t i = 0; i < keys.size(); ++i)
+    size += keys[i].size_estimate();
   return size;
 }
 
diff --git a/third_party/blink/common/indexeddb/indexeddb_mojom_traits.cc b/third_party/blink/common/indexeddb/indexeddb_struct_traits.cc
similarity index 99%
rename from third_party/blink/common/indexeddb/indexeddb_mojom_traits.cc
rename to third_party/blink/common/indexeddb/indexeddb_struct_traits.cc
index 988aca94..d775ecd 100644
--- a/third_party/blink/common/indexeddb/indexeddb_mojom_traits.cc
+++ b/third_party/blink/common/indexeddb/indexeddb_struct_traits.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h"
+#include "third_party/blink/public/common/indexeddb/indexeddb_struct_traits.h"
 
 #include "base/stl_util.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 50f0ad2..db0c7eb 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -128,11 +128,13 @@
     "platform/mac/web_sandbox_support.h",
     "platform/mac/web_scrollbar_theme.h",
     "platform/modules/background_fetch/web_background_fetch_registration.h",
-    "platform/modules/indexeddb/indexed_db_key_builder.h",
     "platform/modules/indexeddb/web_idb_callbacks.h",
+    "platform/modules/indexeddb/web_idb_cursor.h",
+    "platform/modules/indexeddb/web_idb_database.h",
     "platform/modules/indexeddb/web_idb_database_callbacks.h",
     "platform/modules/indexeddb/web_idb_database_error.h",
     "platform/modules/indexeddb/web_idb_database_exception.h",
+    "platform/modules/indexeddb/web_idb_factory.h",
     "platform/modules/indexeddb/web_idb_key.h",
     "platform/modules/indexeddb/web_idb_key_path.h",
     "platform/modules/indexeddb/web_idb_key_range.h",
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index 256e4c16..25d4fa9 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -15,7 +15,7 @@
 
   public_deps = [
     "//third_party/blink/public/common:headers",
-    "//third_party/blink/public/mojom:mojom_modules",
+    "//third_party/blink/public/mojom:mojom_core",
   ]
   deps = [
     "//third_party/blink/common",
@@ -55,7 +55,7 @@
     "indexeddb/indexeddb_key_path.h",
     "indexeddb/indexeddb_key_range.h",
     "indexeddb/indexeddb_metadata.h",
-    "indexeddb/indexeddb_mojom_traits.h",
+    "indexeddb/indexeddb_struct_traits.h",
     "indexeddb/web_idb_types.h",
     "manifest/manifest.h",
     "manifest/manifest_icon_selector.h",
@@ -86,7 +86,7 @@
 
   public_deps = [
     "//skia",
-    "//third_party/blink/public/mojom:mojom_modules_headers",
+    "//third_party/blink/public/mojom:mojom_core_headers",
   ]
 
   deps = [
diff --git a/third_party/blink/public/common/indexeddb/OWNERS b/third_party/blink/public/common/indexeddb/OWNERS
index 4d50d63..3b5f7f5 100644
--- a/third_party/blink/public/common/indexeddb/OWNERS
+++ b/third_party/blink/public/common/indexeddb/OWNERS
@@ -1,7 +1,7 @@
 file://content/browser/indexed_db/OWNERS
 
-per-file *_mojom_traits*.*=set noparent
-per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=set noparent
+per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
 per-file *.typemap=set noparent
 per-file *.typemap=file://ipc/SECURITY_OWNERS
 
diff --git a/third_party/blink/public/common/indexeddb/indexeddb.typemap b/third_party/blink/public/common/indexeddb/indexeddb.typemap
index f46637a..cc75494 100644
--- a/third_party/blink/public/common/indexeddb/indexeddb.typemap
+++ b/third_party/blink/public/common/indexeddb/indexeddb.typemap
@@ -12,20 +12,20 @@
 ]
 traits_headers = [
   "//mojo/public/cpp/bindings/array_traits_span.h",
-  "//third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h",
+  "//third_party/blink/public/common/indexeddb/indexeddb_struct_traits.h",
 ]
 type_mappings = [
-  "blink.mojom.IDBCursorDirection=::blink::WebIDBCursorDirection",
-  "blink.mojom.IDBDataLoss=::blink::WebIDBDataLoss",
-  "blink.mojom.IDBDatabaseMetadata=::blink::IndexedDBDatabaseMetadata",
-  "blink.mojom.IDBIndexKeys=::blink::IndexedDBIndexKeys",
-  "blink.mojom.IDBIndexMetadata=::blink::IndexedDBIndexMetadata",
-  "blink.mojom.IDBKey=::blink::IndexedDBKey",
-  "blink.mojom.IDBKeyPath=::blink::IndexedDBKeyPath",
-  "blink.mojom.IDBKeyRange=::blink::IndexedDBKeyRange",
-  "blink.mojom.IDBObjectStoreMetadata=::blink::IndexedDBObjectStoreMetadata",
-  "blink.mojom.IDBOperationType=::blink::WebIDBOperationType",
-  "blink.mojom.IDBPutMode=::blink::WebIDBPutMode",
-  "blink.mojom.IDBTaskType=::blink::WebIDBTaskType",
-  "blink.mojom.IDBTransactionMode=::blink::WebIDBTransactionMode",
+  "blink.mojom.IDBCursorDirection=blink::WebIDBCursorDirection",
+  "blink.mojom.IDBDataLoss=blink::WebIDBDataLoss",
+  "blink.mojom.IDBDatabaseMetadata=blink::IndexedDBDatabaseMetadata",
+  "blink.mojom.IDBIndexKeys=blink::IndexedDBIndexKeys",
+  "blink.mojom.IDBIndexMetadata=blink::IndexedDBIndexMetadata",
+  "blink.mojom.IDBKey=blink::IndexedDBKey",
+  "blink.mojom.IDBKeyPath=blink::IndexedDBKeyPath",
+  "blink.mojom.IDBKeyRange=blink::IndexedDBKeyRange",
+  "blink.mojom.IDBObjectStoreMetadata=blink::IndexedDBObjectStoreMetadata",
+  "blink.mojom.IDBOperationType=blink::WebIDBOperationType",
+  "blink.mojom.IDBPutMode=blink::WebIDBPutMode",
+  "blink.mojom.IDBTaskType=blink::WebIDBTaskType",
+  "blink.mojom.IDBTransactionMode=blink::WebIDBTransactionMode",
 ]
diff --git a/third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h b/third_party/blink/public/common/indexeddb/indexeddb_struct_traits.h
similarity index 94%
rename from third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h
rename to third_party/blink/public/common/indexeddb/indexeddb_struct_traits.h
index 583b2ba..4eb928cf 100644
--- a/third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h
+++ b/third_party/blink/public/common/indexeddb/indexeddb_struct_traits.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_INDEXEDDB_INDEXEDDB_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_INDEXEDDB_INDEXEDDB_MOJOM_TRAITS_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_INDEXEDDB_INDEXEDDB_STRUCT_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_INDEXEDDB_INDEXEDDB_STRUCT_TRAITS_H_
 
 #include "base/containers/span.h"
 #include "third_party/blink/public/common/common_export.h"
@@ -36,8 +36,7 @@
   static int64_t id(const blink::IndexedDBDatabaseMetadata& metadata) {
     return metadata.id;
   }
-  static const base::string16& name(
-      const blink::IndexedDBDatabaseMetadata& metadata) {
+  static base::string16 name(const blink::IndexedDBDatabaseMetadata& metadata) {
     return metadata.name;
   }
   static int64_t version(const blink::IndexedDBDatabaseMetadata& metadata) {
@@ -75,8 +74,7 @@
   static int64_t id(const blink::IndexedDBIndexMetadata& metadata) {
     return metadata.id;
   }
-  static const base::string16& name(
-      const blink::IndexedDBIndexMetadata& metadata) {
+  static base::string16 name(const blink::IndexedDBIndexMetadata& metadata) {
     return metadata.name;
   }
   static const blink::IndexedDBKeyPath& key_path(
@@ -172,7 +170,7 @@
   static int64_t id(const blink::IndexedDBObjectStoreMetadata& metadata) {
     return metadata.id;
   }
-  static const base::string16& name(
+  static base::string16 name(
       const blink::IndexedDBObjectStoreMetadata& metadata) {
     return metadata.name;
   }
@@ -232,4 +230,4 @@
 
 }  // namespace mojo
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_INDEXEDDB_INDEXEDDB_MOJOM_TRAITS_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_INDEXEDDB_INDEXEDDB_STRUCT_TRAITS_H_
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 83d6e66..0721716 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -5,7 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 # This target includes all mojom interfaces which can be used from
-# renderer/platform. In particular these mojom interfaces can't use types that
+# Source/platform. In particular these mojom interfaces can't use types that
 # are typemapped to a type in Source/core.
 mojom("mojom_platform") {
   sources = [
@@ -31,6 +31,7 @@
     "filesystem/file_writer.mojom",
     "frame/find_in_page.mojom",
     "frame/navigation_initiator.mojom",
+    "indexeddb/indexeddb.mojom",
     "leak_detector/leak_detector.mojom",
     "loader/code_cache.mojom",
     "loader/navigation_predictor.mojom",
@@ -121,8 +122,8 @@
 }
 
 # This target can include mojom interfaces which do use types that are
-# typemapped to a type in renderer/core. This also means these interfaces are
-# not available from renderer/platform.
+# typemapped to a type in Source/core. This also means these interfaces are not
+# available from Source/platform.
 # Note that service_worker_object.mojom and service_worker.mojom depend
 # on transferable_message.mojom, and service_worker_registration.mojom depends
 # on service_worker_object.mojom, so we put these three service worker
@@ -159,38 +160,3 @@
   export_define_blink = "BLINK_CORE_IMPLEMENTATION=1"
   export_header_blink = "third_party/blink/renderer/core/core_export.h"
 }
-
-# This target can include mojom interfaces which use types that are typemapped
-# to a type in renderer/modules. This also means these interfaces are not
-# available from renderer/platform or renderer/core.
-mojom("mojom_modules") {
-  sources = [
-    "indexeddb/indexeddb.mojom",
-  ]
-
-  public_deps = [
-    ":mojom_core",
-
-    # TODO(https://crbug.com/822804): Remove when mojom bindings deps checks
-    # get fixed.
-    ":mojom_platform",
-    "//mojo/public/mojom/base",
-    "//skia/public/interfaces",
-    "//url/mojom:url_mojom_gurl",
-    "//url/mojom:url_mojom_origin",
-  ]
-
-  overridden_deps_blink = [
-    ":mojom_core",
-    ":mojom_platform",
-  ]
-  component_deps_blink = [ "//third_party/blink/renderer/core" ]
-
-  export_class_attribute = "BLINK_COMMON_EXPORT"
-  export_define = "BLINK_COMMON_IMPLEMENTATION=1"
-  export_header = "third_party/blink/public/common/common_export.h"
-
-  export_class_attribute_blink = "MODULES_EXPORT"
-  export_define_blink = "BLINK_MODULES_IMPLEMENTATION=1"
-  export_header_blink = "third_party/blink/renderer/modules/modules_export.h"
-}
diff --git a/third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h b/third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h
deleted file mode 100644
index 28a5e8f..0000000
--- a/third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_INDEXED_DB_KEY_BUILDER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_INDEXED_DB_KEY_BUILDER_H_
-
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
-#include "third_party/blink/public/platform/web_common.h"
-
-namespace blink {
-
-class IndexedDBKeyRange;
-class WebIDBKeyPath;
-class WebIDBKeyRange;
-
-class BLINK_EXPORT IndexedDBKeyBuilder {
- public:
-  static IndexedDBKey Build(WebIDBKeyView key);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyBuilder);
-};
-
-class BLINK_EXPORT WebIDBKeyBuilder {
- public:
-  static WebIDBKey Build(const IndexedDBKey& key);
-  static WebIDBKey Build(const WebIDBKeyView& key);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebIDBKeyBuilder);
-};
-
-class BLINK_EXPORT IndexedDBKeyRangeBuilder {
- public:
-  static IndexedDBKeyRange Build(const WebIDBKeyRange& key_range);
-
-  // Builds a point range (containing a single key).
-  static IndexedDBKeyRange Build(WebIDBKeyView key);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyRangeBuilder);
-};
-
-class BLINK_EXPORT WebIDBKeyRangeBuilder {
- public:
-  static WebIDBKeyRange Build(const IndexedDBKeyRange& key);
-
-  // Builds a point range (containing a single key).
-  static WebIDBKeyRange Build(WebIDBKeyView key);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebIDBKeyRangeBuilder);
-};
-
-class BLINK_EXPORT IndexedDBKeyPathBuilder {
- public:
-  static IndexedDBKeyPath Build(const WebIDBKeyPath& key_path);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyPathBuilder);
-};
-
-class BLINK_EXPORT WebIDBKeyPathBuilder {
- public:
-  static WebIDBKeyPath Build(const IndexedDBKeyPath& key_path);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebIDBKeyPathBuilder);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_INDEXED_DB_KEY_BUILDER_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h b/third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h
similarity index 88%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h
rename to third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h
index 7e03aa02..248df14 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h
+++ b/third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h
@@ -23,18 +23,18 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
 
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
+#include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
 
 namespace blink {
 
-class MODULES_EXPORT WebIDBCursor {
+class WebIDBCursor {
  public:
   virtual ~WebIDBCursor() = default;
 
@@ -65,4 +65,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_CURSOR_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database.h b/third_party/blink/public/platform/modules/indexeddb/web_idb_database.h
similarity index 84%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_database.h
rename to third_party/blink/public/platform/modules/indexeddb/web_idb_database.h
index f5e28eb..782d60fa 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_database.h
+++ b/third_party/blink/public/platform/modules/indexeddb/web_idb_database.h
@@ -23,17 +23,16 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
-
-#include <bitset>
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
 
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
 #include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/blink/public/platform/web_common.h"
+
+#include <bitset>
 
 namespace blink {
 
@@ -42,22 +41,22 @@
 class WebIDBKeyPath;
 class WebIDBKeyRange;
 
-class MODULES_EXPORT WebIDBDatabase {
+class WebIDBDatabase {
  public:
   virtual ~WebIDBDatabase() = default;
 
   virtual void CreateObjectStore(long long transaction_id,
                                  long long object_store_id,
-                                 const String& name,
+                                 const WebString& name,
                                  const WebIDBKeyPath&,
                                  bool auto_increment) = 0;
   virtual void DeleteObjectStore(long long transaction_id,
                                  long long object_store_id) = 0;
   virtual void RenameObjectStore(long long transaction_id,
                                  long long object_store_id,
-                                 const String& name) = 0;
+                                 const WebString& name) = 0;
   virtual void CreateTransaction(long long id,
-                                 const Vector<int64_t>& scope,
+                                 const WebVector<long long>& scope,
                                  WebIDBTransactionMode) = 0;
   virtual void Close() = 0;
   virtual void VersionChangeIgnored() = 0;
@@ -68,7 +67,7 @@
   virtual void CreateIndex(long long transaction_id,
                            long long object_store_id,
                            long long index_id,
-                           const String& name,
+                           const WebString& name,
                            const WebIDBKeyPath&,
                            bool unique,
                            bool multi_entry) = 0;
@@ -78,7 +77,7 @@
   virtual void RenameIndex(long long transaction_id,
                            long long object_store_id,
                            long long index_id,
-                           const String& new_name) = 0;
+                           const WebString& new_name) = 0;
 
   static const long long kMinimumIndexId = 30;
 
@@ -90,7 +89,7 @@
       bool values,
       const std::bitset<kWebIDBOperationTypeCount>& operation_types) = 0;
   virtual void RemoveObservers(
-      const Vector<int32_t>& observer_ids_to_remove) = 0;
+      const WebVector<int32_t>& observer_ids_to_remove) = 0;
   virtual void Get(long long transaction_id,
                    long long object_store_id,
                    long long index_id,
@@ -107,18 +106,18 @@
   virtual void Put(long long transaction_id,
                    long long object_store_id,
                    const WebData& value,
-                   const Vector<WebBlobInfo>&,
+                   const WebVector<WebBlobInfo>&,
                    WebIDBKeyView primary_key,
                    WebIDBPutMode,
                    WebIDBCallbacks*,
-                   const Vector<WebIDBIndexKeys>&) = 0;
+                   const WebVector<WebIDBIndexKeys>&) = 0;
   virtual void SetIndexKeys(long long transaction_id,
                             long long object_store_id,
                             WebIDBKeyView primary_key,
-                            const Vector<WebIDBIndexKeys>&) = 0;
+                            const WebVector<WebIDBIndexKeys>&) = 0;
   virtual void SetIndexesReady(long long transaction_id,
                                long long object_store_id,
-                               const Vector<int64_t>& index_ids) = 0;
+                               const WebVector<long long>& index_ids) = 0;
   virtual void OpenCursor(long long transaction_id,
                           long long object_store_id,
                           long long index_id,
@@ -150,4 +149,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_DATABASE_H_
diff --git a/third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h b/third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h
index dd8b27d..2343315 100644
--- a/third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h
+++ b/third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h
@@ -40,11 +40,11 @@
 
 class WebIDBDatabaseCallbacks {
  public:
-  using ObservationIndexMap = std::unordered_map<int32_t, WebVector<int32_t>>;
+  using ObservationIndexMap = std::unordered_map<int32_t, std::vector<int32_t>>;
 
   // Maps observer to transaction, which needs an id and a scope.
   using TransactionMap =
-      std::unordered_map<int32_t, std::pair<int64_t, WebVector<int64_t>>>;
+      std::unordered_map<int32_t, std::pair<int64_t, std::vector<int64_t>>>;
 
   virtual ~WebIDBDatabaseCallbacks() = default;
 
@@ -56,8 +56,8 @@
                        const WebIDBDatabaseError&) = 0;
   virtual void OnComplete(long long transaction_id) = 0;
   virtual void OnChanges(const ObservationIndexMap&,
-                         WebVector<WebIDBObservation>,
-                         const TransactionMap&) = 0;
+                         WebVector<WebIDBObservation> observations,
+                         const TransactionMap& transactions) = 0;
   virtual void Detach() = 0;
 };
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_factory.h b/third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h
similarity index 89%
rename from third_party/blink/renderer/modules/indexeddb/web_idb_factory.h
rename to third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h
index 71a2ce0..b99e5d8 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_factory.h
+++ b/third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h
@@ -26,11 +26,11 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_FACTORY_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_FACTORY_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_FACTORY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_FACTORY_H_
 
 #include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/public/platform/web_common.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -43,7 +43,7 @@
 class WebSecurityOrigin;
 class WebString;
 
-class MODULES_EXPORT WebIDBFactory {
+class WebIDBFactory {
  public:
   virtual ~WebIDBFactory() = default;
 
@@ -70,4 +70,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_FACTORY_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_INDEXEDDB_WEB_IDB_FACTORY_H_
diff --git a/third_party/blink/public/platform/modules/indexeddb/web_idb_key.h b/third_party/blink/public/platform/modules/indexeddb/web_idb_key.h
index 7255f7d..cdacdfe 100644
--- a/third_party/blink/public/platform/modules/indexeddb/web_idb_key.h
+++ b/third_party/blink/public/platform/modules/indexeddb/web_idb_key.h
@@ -62,7 +62,7 @@
 // The Blink object wrapped by WebIDBKey is immutable, so WebIDBKeyView
 // instances are implicitly const references.
 //
-// Having both WebIDBKeyView and WebIDBKey is extra complexity, and we pay this
+// Having both WebIDBKeyView and WebIDBView is extra complexity, and we pay this
 // price to avoid unnecessary memory copying. Specifically, WebIDBKeyView is
 // used to issue requests to the IndexedDB backing store.
 //
@@ -99,19 +99,6 @@
   // Only valid for NumberType.
   BLINK_EXPORT double Number() const;
 
-  BLINK_EXPORT size_t SizeEstimate() const;
-
-  // TODO(cmp): Ensure |private_| can never be null.
-  //
-  // SizeEstimate() can be called when |private_| is null.  That happens if and
-  // only if the |WebIDBKey| instance is created using WebIDBKey::CreateNull().
-  //
-  // Eventually, WebIDBKey::CreateNull() will change so that case will lead to
-  // a non-null |private_|.  At that time, this null check can change to a
-  // DCHECK that |private_| is not null and the special null case handling can
-  // be removed.
-  BLINK_EXPORT bool IsNull() const { return !private_; }
-
  private:
   const IDBKey* const private_;
 };
@@ -137,25 +124,18 @@
   BLINK_EXPORT static WebIDBKey CreateNull() noexcept { return WebIDBKey(); }
 
   // The default constructor must not be used explicitly.
-  // It is only provided for WebVector and Mojo's use.
+  // It is only provided for WebVector's use.
   BLINK_EXPORT WebIDBKey() noexcept;
 
   BLINK_EXPORT WebIDBKey(WebIDBKey&&) noexcept;
   BLINK_EXPORT WebIDBKey& operator=(WebIDBKey&&) noexcept;
 
-  // TODO(cmp): Remove copy and assignment constructors when Vector<->WebVector
-  //            conversions are no longer needed.
-  BLINK_EXPORT WebIDBKey(const WebIDBKey& rkey);
-  BLINK_EXPORT WebIDBKey& operator=(const WebIDBKey& rkey);
-
   BLINK_EXPORT ~WebIDBKey();
 
   BLINK_EXPORT WebIDBKeyView View() const {
     return WebIDBKeyView(private_.get());
   }
 
-  BLINK_EXPORT size_t SizeEstimate() const { return View().SizeEstimate(); }
-
 #if INSIDE_BLINK
   explicit WebIDBKey(std::unique_ptr<IDBKey>) noexcept;
   WebIDBKey& operator=(std::unique_ptr<IDBKey>) noexcept;
@@ -167,6 +147,11 @@
 #endif  // INSIDE_BLINK
 
  private:
+  // WebIDBKey has to be move-only, because std::unique_ptr is move-only. Making
+  // the restriction explicit results in slightly better compilation error
+  // messages in code that attempts copying.
+  WebIDBKey(const WebIDBKey&) = delete;
+  WebIDBKey& operator=(const WebIDBKey&) = delete;
 
   std::unique_ptr<IDBKey> private_;
 };
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index 6225f1f..b9acf77 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -50,6 +50,7 @@
 #include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h"
 #include "third_party/blink/public/platform/blame_context.h"
 #include "third_party/blink/public/platform/code_cache_loader.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/public/platform/user_metrics_action.h"
 #include "third_party/blink/public/platform/web_audio_device.h"
 #include "third_party/blink/public/platform/web_common.h"
@@ -297,6 +298,11 @@
 
   virtual WebString ConvertIDNToUnicode(const WebString& host) { return host; }
 
+  // IndexedDB ----------------------------------------------------------
+
+  // Must return non-null.
+  virtual std::unique_ptr<WebIDBFactory> CreateIdbFactory() { return nullptr; }
+
   // History -------------------------------------------------------------
 
   // Returns the hash for the given canonicalized URL for use in visited
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom
index 112cc3e..77a94f6 100644
--- a/third_party/blink/public/platform/web_feature.mojom
+++ b/third_party/blink/public/platform/web_feature.mojom
@@ -1985,7 +1985,6 @@
   kV8WasmSharedMemory = 2532,
   kV8WasmThreadOpcodes = 2533,
   kCacheStorageAddAllSuccessWithDuplicate = 2534,
-  kLegendDelegateFocusOrAccessKey = 2535,
   kFeaturePolicyReport = 2536,
   kV8Window_WebkitRTCPeerConnection_ConstructorGetter = 2537,
   kV8Window_WebkitMediaStream_ConstructorGetter = 2538,
@@ -2064,6 +2063,7 @@
   kHTMLCanvasElementLowLatency = 2611,
   kV8OptimizedFunctionWithOneShotBytecode = 2612,
   kSVGGeometryPropertyHasNonZeroUnitlessValue = 2613,
+  kCSSValueAppearanceNoImplementationSkipBorder = 2614,
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
   // Also, run update_use_counter_feature_enum.py in
diff --git a/third_party/blink/public/web/web_origin_trials.h b/third_party/blink/public/web/web_origin_trials.h
index e161570..2c79a0f 100644
--- a/third_party/blink/public/web/web_origin_trials.h
+++ b/third_party/blink/public/web/web_origin_trials.h
@@ -12,13 +12,12 @@
 class WebDocument;
 class WebString;
 
-// A namespace with tests for experimental features which can be enabled by the
+// A class with tests for experimental features which can be enabled by the
 // origin trials framework via origin trial tokens.
-namespace WebOriginTrials {
-
-CORE_EXPORT bool isTrialEnabled(const WebDocument*, const WebString&);
-
-}  // namespace WebOriginTrials
+class WebOriginTrials {
+ public:
+  CORE_EXPORT static bool isTrialEnabled(const WebDocument*, const WebString&);
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc
index ff1de20..633b9b94 100644
--- a/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc
+++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc
@@ -131,7 +131,7 @@
   MessagePortArray* port_array = nullptr;
   const int kPortArrayIndex = 7;
   if (!IsUndefinedOrNull(info[kPortArrayIndex])) {
-    port_array = new MessagePortArray;
+    port_array = MakeGarbageCollected<MessagePortArray>();
     *port_array = NativeValueTraits<IDLSequence<MessagePort>>::NativeValue(
         info.GetIsolate(), info[kPortArrayIndex], exception_state);
     if (exception_state.HadException())
diff --git a/third_party/blink/renderer/bindings/core/v8/script_source_code.cc b/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
index 376817d..312f893 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
@@ -38,12 +38,12 @@
 }
 
 String SourceMapUrlFromResponse(const ResourceResponse& response) {
-  String source_map_url = response.HttpHeaderField(HTTPNames::SourceMap);
+  String source_map_url = response.HttpHeaderField(http_names::kSourceMap);
   if (!source_map_url.IsEmpty())
     return source_map_url;
 
   // Try to get deprecated header.
-  return response.HttpHeaderField(HTTPNames::X_SourceMap);
+  return response.HttpHeaderField(http_names::kXSourceMap);
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
index a75067b..adf921cd 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
@@ -69,7 +69,7 @@
 
   // If message ports are requested, make some.
   if (hash & kFuzzMessagePorts) {
-    MessagePortArray* message_ports = new MessagePortArray(3);
+    MessagePortArray* message_ports = MakeGarbageCollected<MessagePortArray>(3);
     std::generate(message_ports->begin(), message_ports->end(), []() {
       MessagePort* port = MessagePort::Create(g_page_holder->GetDocument());
       port->Entangle(mojo::MessagePipe().handle0);
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
index 2fe1a2a..e4a8764 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
@@ -931,20 +931,20 @@
   }
   {
     V8ScriptValueDeserializer::Options options;
-    options.message_ports = new MessagePortArray;
+    options.message_ports = MakeGarbageCollected<MessagePortArray>();
     V8ScriptValueDeserializer deserializer(script_state, input, options);
     ASSERT_TRUE(deserializer.Deserialize()->IsNull());
   }
   {
     V8ScriptValueDeserializer::Options options;
-    options.message_ports = new MessagePortArray;
+    options.message_ports = MakeGarbageCollected<MessagePortArray>();
     options.message_ports->push_back(port1);
     V8ScriptValueDeserializer deserializer(script_state, input, options);
     ASSERT_TRUE(deserializer.Deserialize()->IsNull());
   }
   {
     V8ScriptValueDeserializer::Options options;
-    options.message_ports = new MessagePortArray;
+    options.message_ports = MakeGarbageCollected<MessagePortArray>();
     options.message_ports->push_back(port1);
     options.message_ports->push_back(port2);
     V8ScriptValueDeserializer deserializer(script_state, input, options);
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index c048c382..154434a 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1728,6 +1728,7 @@
     "css/css_gradient_value_test.cc",
     "css/css_page_rule_test.cc",
     "css/css_paint_value_test.cc",
+    "css/css_primitive_value_test.cc",
     "css/css_selector_test.cc",
     "css/css_selector_watch_test.cc",
     "css/css_style_declaration_test.cc",
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 9933886..d9be8e9 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -254,7 +254,7 @@
   HeapVector<Member<StringKeyframe>>* CreateCompositableFloatKeyframeVector(
       Vector<double>& values) {
     HeapVector<Member<StringKeyframe>>* frames =
-        new HeapVector<Member<StringKeyframe>>();
+        MakeGarbageCollected<HeapVector<Member<StringKeyframe>>>();
     for (wtf_size_t i = 0; i < values.size(); i++) {
       double offset = 1.0 / (values.size() - 1) * i;
       String value = String::Number(values[i]);
@@ -1679,7 +1679,7 @@
   element->SetLayoutObject(layout_object);
 
   Persistent<HeapVector<Member<StringKeyframe>>> key_frames =
-      new HeapVector<Member<StringKeyframe>>;
+      MakeGarbageCollected<HeapVector<Member<StringKeyframe>>>();
   key_frames->push_back(CreateDefaultKeyframe(
       CSSPropertyOpacity, EffectModel::kCompositeReplace, 0.0));
   key_frames->push_back(CreateDefaultKeyframe(
diff --git a/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
index 22f11ff..504e59f 100644
--- a/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
@@ -51,7 +51,7 @@
 InterpolationValue CSSImageListInterpolationType::MaybeConvertInitial(
     const StyleResolverState&,
     ConversionCheckers& conversion_checkers) const {
-  StyleImageList* initial_image_list = new StyleImageList;
+  StyleImageList* initial_image_list = MakeGarbageCollected<StyleImageList>();
   ImageListPropertyFunctions::GetInitialImageList(CssProperty(),
                                                   initial_image_list);
   return MaybeConvertStyleImageList(initial_image_list);
@@ -88,7 +88,8 @@
 
   bool IsValid(const StyleResolverState& state,
                const InterpolationValue& underlying) const final {
-    StyleImageList* inherited_image_list = new StyleImageList;
+    StyleImageList* inherited_image_list =
+        MakeGarbageCollected<StyleImageList>();
     ImageListPropertyFunctions::GetImageList(property_, *state.ParentStyle(),
                                              inherited_image_list);
     return inherited_image_list_ == inherited_image_list;
@@ -104,7 +105,7 @@
   if (!state.ParentStyle())
     return nullptr;
 
-  StyleImageList* inherited_image_list = new StyleImageList();
+  StyleImageList* inherited_image_list = MakeGarbageCollected<StyleImageList>();
   ImageListPropertyFunctions::GetImageList(CssProperty(), *state.ParentStyle(),
                                            inherited_image_list);
   conversion_checkers.push_back(
@@ -159,7 +160,8 @@
 InterpolationValue
 CSSImageListInterpolationType::MaybeConvertStandardPropertyUnderlyingValue(
     const ComputedStyle& style) const {
-  StyleImageList* underlying_image_list = new StyleImageList();
+  StyleImageList* underlying_image_list =
+      MakeGarbageCollected<StyleImageList>();
   ImageListPropertyFunctions::GetImageList(CssProperty(), style,
                                            underlying_image_list);
   return MaybeConvertStyleImageList(underlying_image_list);
@@ -184,7 +186,7 @@
   const NonInterpolableList& non_interpolable_list =
       ToNonInterpolableList(*non_interpolable_value);
   DCHECK_EQ(non_interpolable_list.length(), length);
-  StyleImageList* image_list = new StyleImageList(length);
+  StyleImageList* image_list = MakeGarbageCollected<StyleImageList>(length);
   for (wtf_size_t i = 0; i < length; i++) {
     image_list->at(i) = CSSImageInterpolationType::ResolveStyleImage(
         CssProperty(), *interpolable_list.Get(i), non_interpolable_list.Get(i),
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.cc b/third_party/blink/renderer/core/clipboard/data_transfer.cc
index f1e09d62..3c2f733f 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer.cc
+++ b/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -481,7 +481,7 @@
   data_object->AddSharedBuffer(
       image_buffer, image_url, image->FilenameExtension(),
       cached_image->GetResponse().HttpHeaderFields().Get(
-          HTTPNames::Content_Disposition));
+          http_names::kContentDisposition));
 }
 
 void DataTransfer::DeclareAndWriteDragImage(Element* element,
diff --git a/third_party/blink/renderer/core/core_initializer.cc b/third_party/blink/renderer/core/core_initializer.cc
index 014147c..f62cee21f 100644
--- a/third_party/blink/renderer/core/core_initializer.cc
+++ b/third_party/blink/renderer/core/core_initializer.cc
@@ -99,8 +99,8 @@
       kQualifiedNamesCount + EventNames::kNamesCount +
       EventTargetNames::kNamesCount + EventTypeNames::kNamesCount +
       FetchInitiatorTypeNames::kNamesCount + FontFamilyNames::kNamesCount +
-      HTMLTokenizerNames::kNamesCount + HTTPNames::kNamesCount +
-      InputModeNames::kNamesCount + input_type_names::kNamesCount +
+      HTMLTokenizerNames::kNamesCount + http_names::kNamesCount +
+      input_mode_names::kNamesCount + input_type_names::kNamesCount +
       media_feature_names::kNamesCount + media_type_names::kNamesCount +
       performance_entry_names::kNamesCount;
 
@@ -123,8 +123,8 @@
   FetchInitiatorTypeNames::init();
   FontFamilyNames::init();
   HTMLTokenizerNames::init();
-  HTTPNames::init();
-  InputModeNames::init();
+  http_names::init();
+  input_mode_names::init();
   input_type_names::init();
   media_feature_names::init();
   media_type_names::init();
@@ -133,7 +133,7 @@
   MediaQueryEvaluator::Init();
   CSSParserTokenRange::InitStaticEOFToken();
 
-  StyleChangeExtraData::Init();
+  style_change_extra_data::Init();
 
   KURL::Initialize();
   SchemeRegistry::Initialize();
diff --git a/third_party/blink/renderer/core/css/css_paint_value.cc b/third_party/blink/renderer/core/css/css_paint_value.cc
index f5878b3c..57f3a3d 100644
--- a/third_party/blink/renderer/core/css/css_paint_value.cc
+++ b/third_party/blink/renderer/core/css/css_paint_value.cc
@@ -82,7 +82,7 @@
     return false;
   }
 
-  parsed_input_arguments_ = new CSSStyleValueVector();
+  parsed_input_arguments_ = MakeGarbageCollected<CSSStyleValueVector>();
 
   for (wtf_size_t i = 0; i < argument_variable_data_.size(); ++i) {
     // If we are parsing a paint() function, we must be a secure context.
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.h b/third_party/blink/renderer/core/css/css_primitive_value.h
index a00ce66f..feddff5 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value.h
+++ b/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -199,7 +199,7 @@
   static bool IsTime(UnitType unit) {
     return unit == UnitType::kSeconds || unit == UnitType::kMilliseconds;
   }
-  bool IsTime() const { return IsTime(GetType()); }
+  bool IsTime() const { return IsTime(TypeWithCalcResolved()); }
   static bool IsFrequency(UnitType unit) {
     return unit == UnitType::kHertz || unit == UnitType::kKilohertz;
   }
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_test.cc b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
new file mode 100644
index 0000000..4de530e
--- /dev/null
+++ b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
@@ -0,0 +1,52 @@
+// 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 "third_party/blink/renderer/core/css/css_primitive_value.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/css_calculation_value.h"
+
+namespace blink {
+namespace {
+
+using UnitType = CSSPrimitiveValue::UnitType;
+
+struct UnitValue {
+  double value;
+  UnitType unit_type;
+};
+
+CSSPrimitiveValue* Create(UnitValue v) {
+  return CSSPrimitiveValue::Create(v.value, v.unit_type);
+}
+
+CSSPrimitiveValue* CreateAddition(UnitValue a, UnitValue b) {
+  return CSSPrimitiveValue::Create(
+      CSSCalcValue::Create(CSSCalcValue::CreateExpressionNode(
+          CSSCalcValue::CreateExpressionNode(Create(a)),
+          CSSCalcValue::CreateExpressionNode(Create(b)), kCalcAdd)));
+}
+
+TEST(CSSPrimitiveValueTest, IsTime) {
+  EXPECT_FALSE(Create({5.0, UnitType::kNumber})->IsTime());
+  EXPECT_FALSE(Create({5.0, UnitType::kDegrees})->IsTime());
+  EXPECT_TRUE(Create({5.0, UnitType::kSeconds})->IsTime());
+  EXPECT_TRUE(Create({5.0, UnitType::kMilliseconds})->IsTime());
+}
+
+TEST(CSSPrimitiveValueTest, IsTimeCalc) {
+  {
+    UnitValue a = {1.0, UnitType::kSeconds};
+    UnitValue b = {1000.0, UnitType::kMilliseconds};
+    EXPECT_TRUE(CreateAddition(a, b)->IsTime());
+  }
+  {
+    UnitValue a = {1.0, UnitType::kDegrees};
+    UnitValue b = {1000.0, UnitType::kGradians};
+    EXPECT_FALSE(CreateAddition(a, b)->IsTime());
+  }
+}
+
+}  // namespace
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc
index 3402dc1..56c6073 100644
--- a/third_party/blink/renderer/core/css/css_selector.cc
+++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -409,24 +409,6 @@
     {"where", CSSSelector::kPseudoWhere},
 };
 
-class NameToPseudoCompare {
- public:
-  NameToPseudoCompare(const AtomicString& key) : key_(key) {
-    DCHECK(key_.Is8Bit());
-  }
-
-  bool operator()(const NameToPseudoStruct& entry, const NameToPseudoStruct&) {
-    DCHECK(entry.string);
-    const char* key = reinterpret_cast<const char*>(key_.Characters8());
-    // If strncmp returns 0, then either the keys are equal, or |key_| sorts
-    // before |entry|.
-    return strncmp(entry.string, key, key_.length()) < 0;
-  }
-
- private:
-  const AtomicString& key_;
-};
-
 static CSSSelector::PseudoType NameToPseudoType(const AtomicString& name,
                                                 bool has_arguments) {
   if (name.IsNull() || !name.Is8Bit())
@@ -443,10 +425,17 @@
     pseudo_type_map_end = kPseudoTypeWithoutArgumentsMap +
                           arraysize(kPseudoTypeWithoutArgumentsMap);
   }
-  NameToPseudoStruct dummy_key = {nullptr, CSSSelector::kPseudoUnknown};
-  const NameToPseudoStruct* match =
-      std::lower_bound(pseudo_type_map, pseudo_type_map_end, dummy_key,
-                       NameToPseudoCompare(name));
+  const NameToPseudoStruct* match = std::lower_bound(
+      pseudo_type_map, pseudo_type_map_end, name,
+      [](const NameToPseudoStruct& entry, const AtomicString& name) -> bool {
+        DCHECK(name.Is8Bit());
+        DCHECK(entry.string);
+        // If strncmp returns 0, then either the keys are equal, or |name| sorts
+        // before |entry|.
+        return strncmp(entry.string,
+                       reinterpret_cast<const char*>(name.Characters8()),
+                       name.length()) < 0;
+      });
   if (match == pseudo_type_map_end || match->string != name.GetString())
     return CSSSelector::kPseudoUnknown;
 
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc
index 5dc4c06..636a6e2 100644
--- a/third_party/blink/renderer/core/css/element_rule_collector.cc
+++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -84,7 +84,7 @@
 
 inline StyleRuleList* ElementRuleCollector::EnsureStyleRuleList() {
   if (!style_rule_list_)
-    style_rule_list_ = new StyleRuleList();
+    style_rule_list_ = MakeGarbageCollected<StyleRuleList>();
   return style_rule_list_;
 }
 
diff --git a/third_party/blink/renderer/core/css/resolver/match_result_test.cc b/third_party/blink/renderer/core/css/resolver/match_result_test.cc
index 1b2775e..027bf590 100644
--- a/third_party/blink/renderer/core/css/resolver/match_result_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/match_result_test.cc
@@ -22,7 +22,8 @@
 };
 
 void MatchResultTest::SetUp() {
-  property_sets = new HeapVector<Member<MutableCSSPropertyValueSet>, 8>();
+  property_sets =
+      MakeGarbageCollected<HeapVector<Member<MutableCSSPropertyValueSet>, 8>>();
   for (unsigned i = 0; i < 8; i++) {
     property_sets->push_back(
         MutableCSSPropertyValueSet::Create(kHTMLQuirksMode));
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
index 32b534b..80335c4 100644
--- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -326,7 +326,8 @@
     AddRules(rule_set_for_scope, author_rules.ContentPseudoElementRules());
 
   if (!tree_boundary_crossing_rule_set_) {
-    tree_boundary_crossing_rule_set_ = new CSSStyleSheetRuleSubSet();
+    tree_boundary_crossing_rule_set_ =
+        MakeGarbageCollected<CSSStyleSheetRuleSubSet>();
     GetTreeScope().GetDocument().GetStyleEngine().AddTreeBoundaryCrossingScope(
         GetTreeScope());
   }
@@ -341,7 +342,8 @@
     return;
 
   if (!tree_boundary_crossing_rule_set_) {
-    tree_boundary_crossing_rule_set_ = new CSSStyleSheetRuleSubSet();
+    tree_boundary_crossing_rule_set_ =
+        MakeGarbageCollected<CSSStyleSheetRuleSubSet>();
     GetTreeScope().GetDocument().GetStyleEngine().AddTreeBoundaryCrossingScope(
         GetTreeScope());
   }
@@ -369,7 +371,8 @@
   // rule sets. See V0ShadowAddedOnV1Document().
   if (GetTreeScope().GetDocument().MayContainV0Shadow()) {
     if (!tree_boundary_crossing_rule_set_) {
-      tree_boundary_crossing_rule_set_ = new CSSStyleSheetRuleSubSet();
+      tree_boundary_crossing_rule_set_ =
+          MakeGarbageCollected<CSSStyleSheetRuleSubSet>();
       GetTreeScope()
           .GetDocument()
           .GetStyleEngine()
@@ -380,7 +383,7 @@
     return;
   }
   if (!slotted_rule_set_)
-    slotted_rule_set_ = new CSSStyleSheetRuleSubSet();
+    slotted_rule_set_ = MakeGarbageCollected<CSSStyleSheetRuleSubSet>();
   slotted_rule_set_->push_back(
       RuleSubSet::Create(parent_style_sheet, sheet_index, slotted_rule_set));
 }
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index 375ed22..7219119 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1719,6 +1719,11 @@
       return *CSSPrimitiveValue::Create(primitive_value.ComputeDegrees(),
                                         CSSPrimitiveValue::UnitType::kDegrees);
     }
+
+    if (primitive_value.IsTime()) {
+      return *CSSPrimitiveValue::Create(primitive_value.ComputeSeconds(),
+                                        CSSPrimitiveValue::UnitType::kSeconds);
+    }
   }
 
   if (value.IsIdentifierValue()) {
diff --git a/third_party/blink/renderer/core/css/rule_set.cc b/third_party/blink/renderer/core/css/rule_set.cc
index d5c8b79..957664ee 100644
--- a/third_party/blink/renderer/core/css/rule_set.cc
+++ b/third_party/blink/renderer/core/css/rule_set.cc
@@ -359,7 +359,7 @@
     Member<HeapVector<Member<const RuleData>>>& rules =
         compact_map.insert(item.key, nullptr).stored_value->value;
     if (!rules) {
-      rules = new HeapVector<Member<const RuleData>>();
+      rules = MakeGarbageCollected<HeapVector<Member<const RuleData>>>();
       rules->ReserveInitialCapacity(pending_rules->size());
     } else {
       rules->ReserveCapacity(pending_rules->size());
diff --git a/third_party/blink/renderer/core/css/style_change_reason.cc b/third_party/blink/renderer/core/css/style_change_reason.cc
index 705dc78..7fed20e 100644
--- a/third_party/blink/renderer/core/css/style_change_reason.cc
+++ b/third_party/blink/renderer/core/css/style_change_reason.cc
@@ -52,7 +52,7 @@
 const char kZoom[] = "Zoom";
 }  // namespace style_change_reason
 
-namespace StyleChangeExtraData {
+namespace style_change_extra_data {
 DEFINE_GLOBAL(AtomicString, g_active);
 DEFINE_GLOBAL(AtomicString, g_disabled);
 DEFINE_GLOBAL(AtomicString, g_drag);
@@ -77,6 +77,6 @@
   new (NotNull, (void*)&g_unresolved) AtomicString(":unresolved");
 }
 
-}  // namespace StyleChangeExtraData
+}  // namespace style_change_extra_data
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_change_reason.h b/third_party/blink/renderer/core/css/style_change_reason.h
index e738e08..7d21ac9 100644
--- a/third_party/blink/renderer/core/css/style_change_reason.h
+++ b/third_party/blink/renderer/core/css/style_change_reason.h
@@ -53,7 +53,7 @@
 }  // namespace style_change_reason
 typedef const char StyleChangeReasonString[];
 
-namespace StyleChangeExtraData {
+namespace style_change_extra_data {
 extern const AtomicString& g_active;
 extern const AtomicString& g_disabled;
 extern const AtomicString& g_drag;
@@ -65,7 +65,7 @@
 extern const AtomicString& g_unresolved;
 
 void Init();
-}  // namespace StyleChangeExtraData
+}  // namespace style_change_extra_data
 
 // |StyleChangeReasonForTracing| is used to trace the reason a
 // |Node::setNeedsStyleRecalc| call was made to show it in DevTools or in
diff --git a/third_party/blink/renderer/core/css/style_sheet_contents.cc b/third_party/blink/renderer/core/css/style_sheet_contents.cc
index 0725d4d7..38d11f45 100644
--- a/third_party/blink/renderer/core/css/style_sheet_contents.cc
+++ b/third_party/blink/renderer/core/css/style_sheet_contents.cc
@@ -360,10 +360,10 @@
       cached_style_sheet->SheetText(parser_context_, mime_type_check);
 
   const ResourceResponse& response = cached_style_sheet->GetResponse();
-  source_map_url_ = response.HttpHeaderField(HTTPNames::SourceMap);
+  source_map_url_ = response.HttpHeaderField(http_names::kSourceMap);
   if (source_map_url_.IsEmpty()) {
     // Try to get deprecated header.
-    source_map_url_ = response.HttpHeaderField(HTTPNames::X_SourceMap);
+    source_map_url_ = response.HttpHeaderField(http_names::kXSourceMap);
   }
 
   const CSSParserContext* context =
diff --git a/third_party/blink/renderer/core/css/style_traversal_root_test.cc b/third_party/blink/renderer/core/css/style_traversal_root_test.cc
index cfeaf500..ca8c7277 100644
--- a/third_party/blink/renderer/core/css/style_traversal_root_test.cc
+++ b/third_party/blink/renderer/core/css/style_traversal_root_test.cc
@@ -49,7 +49,7 @@
   enum ElementIndex { kA, kB, kC, kD, kE, kF, kG, kElementCount };
   void SetUp() final {
     document_ = Document::CreateForTest();
-    elements_ = new HeapVector<Member<Element>, 7>;
+    elements_ = MakeGarbageCollected<HeapVector<Member<Element>, 7>>();
     for (size_t i = 0; i < kElementCount; i++) {
       elements_->push_back(GetDocument().CreateRawElement(html_names::kDivTag));
     }
diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc
index 8021ceb..fb866b0 100644
--- a/third_party/blink/renderer/core/dom/container_node.cc
+++ b/third_party/blink/renderer/core/dom/container_node.cc
@@ -1042,7 +1042,7 @@
   SetNeedsStyleRecalc(
       change_type,
       StyleChangeReasonForTracing::CreateWithExtraData(
-          style_change_reason::kPseudoClass, StyleChangeExtraData::g_focus));
+          style_change_reason::kPseudoClass, style_change_extra_data::g_focus));
 
   if (IsElementNode() && ToElement(this)->ChildrenOrSiblingsAffectedByFocus())
     ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoFocus);
@@ -1062,7 +1062,7 @@
   SetNeedsStyleRecalc(change_type,
                       StyleChangeReasonForTracing::CreateWithExtraData(
                           style_change_reason::kPseudoClass,
-                          StyleChangeExtraData::g_focus_visible));
+                          style_change_extra_data::g_focus_visible));
 
   if (IsElementNode() &&
       ToElement(this)->ChildrenOrSiblingsAffectedByFocusVisible())
@@ -1078,7 +1078,7 @@
     SetNeedsStyleRecalc(change_type,
                         StyleChangeReasonForTracing::CreateWithExtraData(
                             style_change_reason::kPseudoClass,
-                            StyleChangeExtraData::g_focus_within));
+                            style_change_extra_data::g_focus_within));
   }
   if (IsElementNode() &&
       ToElement(this)->ChildrenOrSiblingsAffectedByFocusWithin())
@@ -1118,10 +1118,10 @@
   if (IsElementNode() && ToElement(this)->ChildrenOrSiblingsAffectedByFocus()) {
     ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoFocus);
   } else {
-    SetNeedsStyleRecalc(
-        kLocalStyleChange,
-        StyleChangeReasonForTracing::CreateWithExtraData(
-            style_change_reason::kPseudoClass, StyleChangeExtraData::g_focus));
+    SetNeedsStyleRecalc(kLocalStyleChange,
+                        StyleChangeReasonForTracing::CreateWithExtraData(
+                            style_change_reason::kPseudoClass,
+                            style_change_extra_data::g_focus));
   }
 
   if (RuntimeEnabledFeatures::CSSFocusVisibleEnabled()) {
@@ -1132,7 +1132,7 @@
       SetNeedsStyleRecalc(kLocalStyleChange,
                           StyleChangeReasonForTracing::CreateWithExtraData(
                               style_change_reason::kPseudoClass,
-                              StyleChangeExtraData::g_focus_visible));
+                              style_change_extra_data::g_focus_visible));
     }
   }
 
@@ -1143,7 +1143,7 @@
     SetNeedsStyleRecalc(kLocalStyleChange,
                         StyleChangeReasonForTracing::CreateWithExtraData(
                             style_change_reason::kPseudoClass,
-                            StyleChangeExtraData::g_focus_within));
+                            style_change_extra_data::g_focus_within));
   }
 }
 
@@ -1169,7 +1169,7 @@
       SetNeedsStyleRecalc(kLocalStyleChange,
                           StyleChangeReasonForTracing::CreateWithExtraData(
                               style_change_reason::kPseudoClass,
-                              StyleChangeExtraData::g_active));
+                              style_change_extra_data::g_active));
     }
     return;
   }
@@ -1179,10 +1179,10 @@
         GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
             ? kSubtreeStyleChange
             : kLocalStyleChange;
-    SetNeedsStyleRecalc(
-        change_type,
-        StyleChangeReasonForTracing::CreateWithExtraData(
-            style_change_reason::kPseudoClass, StyleChangeExtraData::g_active));
+    SetNeedsStyleRecalc(change_type,
+                        StyleChangeReasonForTracing::CreateWithExtraData(
+                            style_change_reason::kPseudoClass,
+                            style_change_extra_data::g_active));
   }
   if (IsElementNode() && ToElement(this)->ChildrenOrSiblingsAffectedByActive())
     ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoActive);
@@ -1206,10 +1206,10 @@
       ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoDrag);
 
     } else {
-      SetNeedsStyleRecalc(
-          kLocalStyleChange,
-          StyleChangeReasonForTracing::CreateWithExtraData(
-              style_change_reason::kPseudoClass, StyleChangeExtraData::g_drag));
+      SetNeedsStyleRecalc(kLocalStyleChange,
+                          StyleChangeReasonForTracing::CreateWithExtraData(
+                              style_change_reason::kPseudoClass,
+                              style_change_extra_data::g_drag));
     }
     return;
   }
@@ -1219,10 +1219,10 @@
         GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
             ? kSubtreeStyleChange
             : kLocalStyleChange;
-    SetNeedsStyleRecalc(
-        change_type,
-        StyleChangeReasonForTracing::CreateWithExtraData(
-            style_change_reason::kPseudoClass, StyleChangeExtraData::g_drag));
+    SetNeedsStyleRecalc(change_type,
+                        StyleChangeReasonForTracing::CreateWithExtraData(
+                            style_change_reason::kPseudoClass,
+                            style_change_extra_data::g_drag));
   }
   if (IsElementNode() && ToElement(this)->ChildrenOrSiblingsAffectedByDrag())
     ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoDrag);
@@ -1239,10 +1239,10 @@
     StyleChangeType change_type = kLocalStyleChange;
     if (style && style->HasPseudoStyle(kPseudoIdFirstLetter))
       change_type = kSubtreeStyleChange;
-    SetNeedsStyleRecalc(
-        change_type,
-        StyleChangeReasonForTracing::CreateWithExtraData(
-            style_change_reason::kPseudoClass, StyleChangeExtraData::g_hover));
+    SetNeedsStyleRecalc(change_type,
+                        StyleChangeReasonForTracing::CreateWithExtraData(
+                            style_change_reason::kPseudoClass,
+                            style_change_extra_data::g_hover));
   }
   if (IsElementNode() && ToElement(this)->ChildrenOrSiblingsAffectedByHover())
     ToElement(this)->PseudoStateChanged(CSSSelector::kPseudoHover);
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 418579ac..a5b727b 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -5487,7 +5487,7 @@
     if (DocumentLoader* document_loader = Loader()) {
       const AtomicString& http_last_modified =
           document_loader->GetResponse().HttpHeaderField(
-              HTTPNames::Last_Modified);
+              http_names::kLastModified);
       if (!http_last_modified.IsEmpty()) {
         double date_value = ParseDate(http_last_modified);
         if (!std::isnan(date_value)) {
diff --git a/third_party/blink/renderer/core/dom/element_rare_data.cc b/third_party/blink/renderer/core/dom/element_rare_data.cc
index 641ebf8..c300ff2 100644
--- a/third_party/blink/renderer/core/dom/element_rare_data.cc
+++ b/third_party/blink/renderer/core/dom/element_rare_data.cc
@@ -79,7 +79,7 @@
 
 AttrNodeList& ElementRareData::EnsureAttrNodeList() {
   if (!attr_node_list_)
-    attr_node_list_ = new AttrNodeList;
+    attr_node_list_ = MakeGarbageCollected<AttrNodeList>();
   return *attr_node_list_;
 }
 
diff --git a/third_party/blink/renderer/core/dom/events/event_listener_map.cc b/third_party/blink/renderer/core/dom/events/event_listener_map.cc
index de30076..1c98599 100644
--- a/third_party/blink/renderer/core/dom/events/event_listener_map.cc
+++ b/third_party/blink/renderer/core/dom/events/event_listener_map.cc
@@ -120,7 +120,8 @@
                                  registered_listener);
   }
 
-  entries_.push_back(std::make_pair(event_type, new EventListenerVector));
+  entries_.push_back(
+      std::make_pair(event_type, MakeGarbageCollected<EventListenerVector>()));
   return AddListenerToVector(entries_.back().second.Get(), listener, options,
                              registered_listener);
 }
diff --git a/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc b/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
index c45ab23c..3409af0 100644
--- a/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
+++ b/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
@@ -42,7 +42,8 @@
 ScopedEventQueue* ScopedEventQueue::instance_ = nullptr;
 
 ScopedEventQueue::ScopedEventQueue()
-    : queued_events_(new HeapVector<Member<Event>>()), scoping_level_(0) {}
+    : queued_events_(MakeGarbageCollected<HeapVector<Member<Event>>>()),
+      scoping_level_(0) {}
 
 ScopedEventQueue::~ScopedEventQueue() {
   DCHECK(!scoping_level_);
diff --git a/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc b/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc
index 866c2a6d..503da88 100644
--- a/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc
+++ b/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc
@@ -67,7 +67,7 @@
   if (event_path_)
     return *event_path_;
 
-  event_path_ = new HeapVector<Member<EventTarget>>();
+  event_path_ = MakeGarbageCollected<HeapVector<Member<EventTarget>>>();
   LocalDOMWindow* window = path.GetWindowEventContext().Window();
   event_path_->ReserveCapacity(path.size() + (window ? 1 : 0));
 
diff --git a/third_party/blink/renderer/core/dom/mutation_observer.cc b/third_party/blink/renderer/core/dom/mutation_observer.cc
index ac2ea235..1a814d3 100644
--- a/third_party/blink/renderer/core/dom/mutation_observer.cc
+++ b/third_party/blink/renderer/core/dom/mutation_observer.cc
@@ -231,7 +231,7 @@
 // https://html.spec.whatwg.org/multipage/browsers.html#unit-of-related-similar-origin-browsing-contexts
 static SlotChangeList& ActiveSlotChangeList() {
   DEFINE_STATIC_LOCAL(Persistent<SlotChangeList>, slot_change_list,
-                      (new SlotChangeList));
+                      (MakeGarbageCollected<SlotChangeList>()));
   return *slot_change_list;
 }
 
diff --git a/third_party/blink/renderer/core/dom/shadow_root_v0.cc b/third_party/blink/renderer/core/dom/shadow_root_v0.cc
index 41971ed..64c9cc4 100644
--- a/third_party/blink/renderer/core/dom/shadow_root_v0.cc
+++ b/third_party/blink/renderer/core/dom/shadow_root_v0.cc
@@ -125,8 +125,9 @@
 
 const HeapVector<Member<V0InsertionPoint>>&
 ShadowRootV0::DescendantInsertionPoints() {
-  DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<V0InsertionPoint>>>,
-                      empty_list, (new HeapVector<Member<V0InsertionPoint>>));
+  DEFINE_STATIC_LOCAL(
+      Persistent<HeapVector<Member<V0InsertionPoint>>>, empty_list,
+      (MakeGarbageCollected<HeapVector<Member<V0InsertionPoint>>>()));
   if (descendant_insertion_points_is_valid_)
     return descendant_insertion_points_;
 
@@ -195,8 +196,10 @@
                                      V0InsertionPoint* insertion_point) {
   NodeToDestinationInsertionPoints::AddResult result =
       node_to_insertion_points_.insert(node, nullptr);
-  if (result.is_new_entry)
-    result.stored_value->value = new DestinationInsertionPoints;
+  if (result.is_new_entry) {
+    result.stored_value->value =
+        MakeGarbageCollected<DestinationInsertionPoints>();
+  }
   result.stored_value->value->push_back(insertion_point);
 }
 
diff --git a/third_party/blink/renderer/core/dom/tree_ordered_map.cc b/third_party/blink/renderer/core/dom/tree_ordered_map.cc
index 820f734..7a90b23f 100644
--- a/third_party/blink/renderer/core/dom/tree_ordered_map.cc
+++ b/third_party/blink/renderer/core/dom/tree_ordered_map.cc
@@ -154,7 +154,7 @@
     const TreeScope& scope) const {
   DCHECK(key);
   DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<Element>>>, empty_vector,
-                      (new HeapVector<Member<Element>>));
+                      (MakeGarbageCollected<HeapVector<Member<Element>>>()));
 
   Map::iterator it = map_.find(key);
   if (it == map_.end())
diff --git a/third_party/blink/renderer/core/dom/tree_scope.cc b/third_party/blink/renderer/core/dom/tree_scope.cc
index d5d8a91d..7aa6bd0 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -128,7 +128,7 @@
 const HeapVector<Member<Element>>& TreeScope::GetAllElementsById(
     const AtomicString& element_id) const {
   DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<Element>>>, empty_vector,
-                      (new HeapVector<Member<Element>>));
+                      (MakeGarbageCollected<HeapVector<Member<Element>>>()));
   if (element_id.IsEmpty())
     return *empty_vector;
   if (!elements_by_id_)
diff --git a/third_party/blink/renderer/core/editing/commands/editor_command.cc b/third_party/blink/renderer/core/editing/commands/editor_command.cc
index a878da7..16a589ba 100644
--- a/third_party/blink/renderer/core/editing/commands/editor_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/editor_command.cc
@@ -202,7 +202,7 @@
   if (selection_modifier.Selection().IsCaret())
     selection_modifier.Modify(SelectionModifyAlteration::kExtend, direction,
                               granularity);
-  StaticRangeVector* ranges = new StaticRangeVector;
+  StaticRangeVector* ranges = MakeGarbageCollected<StaticRangeVector>();
   // We only supports single selections.
   if (selection_modifier.Selection().IsNone())
     return ranges;
@@ -899,10 +899,11 @@
     return false;
   const String& transposed = text.Right(1) + text.Left(1);
 
-  if (DispatchBeforeInputInsertText(
-          EventTargetNodeForDocument(document), transposed,
-          InputEvent::InputType::kInsertTranspose,
-          new StaticRangeVector(1, StaticRange::Create(range))) !=
+  if (DispatchBeforeInputInsertText(EventTargetNodeForDocument(document),
+                                    transposed,
+                                    InputEvent::InputType::kInsertTranspose,
+                                    MakeGarbageCollected<StaticRangeVector>(
+                                        1, StaticRange::Create(range))) !=
       DispatchEventResult::kNotCanceled)
     return false;
 
diff --git a/third_party/blink/renderer/core/editing/editing_style.cc b/third_party/blink/renderer/core/editing/editing_style.cc
index 71bae8f..f11de2a 100644
--- a/third_party/blink/renderer/core/editing/editing_style.cc
+++ b/third_party/blink/renderer/core/editing/editing_style.cc
@@ -970,9 +970,10 @@
 
 static const HeapVector<Member<HTMLElementEquivalent>>&
 HtmlElementEquivalents() {
-  DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<HTMLElementEquivalent>>>,
-                      html_element_equivalents,
-                      (new HeapVector<Member<HTMLElementEquivalent>>));
+  DEFINE_STATIC_LOCAL(
+      Persistent<HeapVector<Member<HTMLElementEquivalent>>>,
+      html_element_equivalents,
+      (MakeGarbageCollected<HeapVector<Member<HTMLElementEquivalent>>>()));
   if (!html_element_equivalents->size()) {
     html_element_equivalents->push_back(HTMLElementEquivalent::Create(
         CSSPropertyFontWeight, CSSValueBold, html_names::kBTag));
@@ -1023,9 +1024,10 @@
 
 static const HeapVector<Member<HTMLAttributeEquivalent>>&
 HtmlAttributeEquivalents() {
-  DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<HTMLAttributeEquivalent>>>,
-                      html_attribute_equivalents,
-                      (new HeapVector<Member<HTMLAttributeEquivalent>>));
+  DEFINE_STATIC_LOCAL(
+      Persistent<HeapVector<Member<HTMLAttributeEquivalent>>>,
+      html_attribute_equivalents,
+      (MakeGarbageCollected<HeapVector<Member<HTMLAttributeEquivalent>>>()));
   if (!html_attribute_equivalents->size()) {
     // elementIsStyledSpanOrHTMLEquivalent depends on the fact each
     // HTMLAttriuteEquivalent matches exactly one attribute of exactly one
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index 888ed30..080ccfede 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -637,22 +637,6 @@
       position);
 }
 
-VisiblePosition FirstEditableVisiblePositionAfterPositionInRoot(
-    const Position& position,
-    ContainerNode& highest_root) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  return CreateVisiblePosition(
-      FirstEditablePositionAfterPositionInRoot(position, highest_root));
-}
-
-VisiblePositionInFlatTree FirstEditableVisiblePositionAfterPositionInRoot(
-    const PositionInFlatTree& position,
-    ContainerNode& highest_root) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  return CreateVisiblePosition(
-      FirstEditablePositionAfterPositionInRoot(position, highest_root));
-}
-
 template <typename Strategy>
 PositionTemplate<Strategy> FirstEditablePositionAfterPositionInRootAlgorithm(
     const PositionTemplate<Strategy>& position,
@@ -714,22 +698,6 @@
       EditingInFlatTreeStrategy>(position, highest_root);
 }
 
-VisiblePosition LastEditableVisiblePositionBeforePositionInRoot(
-    const Position& position,
-    ContainerNode& highest_root) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  return CreateVisiblePosition(
-      LastEditablePositionBeforePositionInRoot(position, highest_root));
-}
-
-VisiblePositionInFlatTree LastEditableVisiblePositionBeforePositionInRoot(
-    const PositionInFlatTree& position,
-    ContainerNode& highest_root) {
-  DCHECK(!NeedsLayoutTreeUpdate(position));
-  return CreateVisiblePosition(
-      LastEditablePositionBeforePositionInRoot(position, highest_root));
-}
-
 template <typename Strategy>
 PositionTemplate<Strategy> LastEditablePositionBeforePositionInRootAlgorithm(
     const PositionTemplate<Strategy>& position,
@@ -1596,7 +1564,7 @@
                                 .ComputeVisibleSelectionInDOMTree());
   if (range.IsNull())
     return nullptr;
-  return new StaticRangeVector(1, StaticRange::Create(range));
+  return MakeGarbageCollected<StaticRangeVector>(1, StaticRange::Create(range));
 }
 
 DispatchEventResult DispatchBeforeInputInsertText(
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.h b/third_party/blink/renderer/core/editing/editing_utilities.h
index f4fea2ac..aae5482d 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.h
+++ b/third_party/blink/renderer/core/editing/editing_utilities.h
@@ -266,26 +266,6 @@
 
 // Functions returning VisiblePosition
 
-// TODO(yosin) We should rename
-// |firstEditableVisiblePositionAfterPositionInRoot()| to a better name which
-// describes what this function returns, since it returns a position before
-// specified position due by canonicalization.
-CORE_EXPORT VisiblePosition
-FirstEditableVisiblePositionAfterPositionInRoot(const Position&,
-                                                ContainerNode&);
-CORE_EXPORT VisiblePositionInFlatTree
-FirstEditableVisiblePositionAfterPositionInRoot(const PositionInFlatTree&,
-                                                ContainerNode&);
-// TODO(yosin) We should rename
-// |lastEditableVisiblePositionBeforePositionInRoot()| to a better name which
-// describes what this function returns, since it returns a position after
-// specified position due by canonicalization.
-CORE_EXPORT VisiblePosition
-LastEditableVisiblePositionBeforePositionInRoot(const Position&,
-                                                ContainerNode&);
-CORE_EXPORT VisiblePositionInFlatTree
-LastEditableVisiblePositionBeforePositionInRoot(const PositionInFlatTree&,
-                                                ContainerNode&);
 CORE_EXPORT VisiblePosition VisiblePositionBeforeNode(const Node&);
 VisiblePosition VisiblePositionAfterNode(const Node&);
 
diff --git a/third_party/blink/renderer/core/editing/editing_utilities_test.cc b/third_party/blink/renderer/core/editing/editing_utilities_test.cc
index cb6102d..c7d8c52d 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities_test.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities_test.cc
@@ -42,32 +42,32 @@
 
   EXPECT_EQ(Position(one, 0),
             FirstEditablePositionAfterPositionInRoot(Position(one, 0), *host));
-  EXPECT_EQ(
-      Position(one->firstChild(), 0),
-      FirstEditableVisiblePositionAfterPositionInRoot(Position(one, 0), *host)
-          .DeepEquivalent());
+  EXPECT_EQ(Position(one->firstChild(), 0),
+            CreateVisiblePosition(FirstEditablePositionAfterPositionInRoot(
+                                      Position(one, 0), *host))
+                .DeepEquivalent());
 
   EXPECT_EQ(PositionInFlatTree(one, 0),
             FirstEditablePositionAfterPositionInRoot(PositionInFlatTree(one, 0),
                                                      *host));
   EXPECT_EQ(PositionInFlatTree(two->firstChild(), 2),
-            FirstEditableVisiblePositionAfterPositionInRoot(
-                PositionInFlatTree(one, 0), *host)
+            CreateVisiblePosition(FirstEditablePositionAfterPositionInRoot(
+                                      PositionInFlatTree(one, 0), *host))
                 .DeepEquivalent());
 
   EXPECT_EQ(
       Position::FirstPositionInNode(*host),
       FirstEditablePositionAfterPositionInRoot(Position(three, 0), *host));
-  EXPECT_EQ(
-      Position(one->firstChild(), 0),
-      FirstEditableVisiblePositionAfterPositionInRoot(Position(three, 0), *host)
-          .DeepEquivalent());
+  EXPECT_EQ(Position(one->firstChild(), 0),
+            CreateVisiblePosition(FirstEditablePositionAfterPositionInRoot(
+                                      Position(three, 0), *host))
+                .DeepEquivalent());
   EXPECT_EQ(PositionInFlatTree::AfterNode(*host),
             FirstEditablePositionAfterPositionInRoot(
                 PositionInFlatTree(three, 0), *host));
   EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*host),
-            FirstEditableVisiblePositionAfterPositionInRoot(
-                PositionInFlatTree(three, 0), *host)
+            CreateVisiblePosition(FirstEditablePositionAfterPositionInRoot(
+                                      PositionInFlatTree(three, 0), *host))
                 .DeepEquivalent());
 }
 
@@ -194,32 +194,32 @@
 
   EXPECT_EQ(Position(one, 0),
             LastEditablePositionBeforePositionInRoot(Position(one, 0), *host));
-  EXPECT_EQ(
-      Position(one->firstChild(), 0),
-      LastEditableVisiblePositionBeforePositionInRoot(Position(one, 0), *host)
-          .DeepEquivalent());
+  EXPECT_EQ(Position(one->firstChild(), 0),
+            CreateVisiblePosition(LastEditablePositionBeforePositionInRoot(
+                                      Position(one, 0), *host))
+                .DeepEquivalent());
 
   EXPECT_EQ(PositionInFlatTree(one, 0),
             LastEditablePositionBeforePositionInRoot(PositionInFlatTree(one, 0),
                                                      *host));
   EXPECT_EQ(PositionInFlatTree(two->firstChild(), 2),
-            LastEditableVisiblePositionBeforePositionInRoot(
-                PositionInFlatTree(one, 0), *host)
+            CreateVisiblePosition(LastEditablePositionBeforePositionInRoot(
+                                      PositionInFlatTree(one, 0), *host))
                 .DeepEquivalent());
 
   EXPECT_EQ(
       Position::FirstPositionInNode(*host),
       LastEditablePositionBeforePositionInRoot(Position(three, 0), *host));
-  EXPECT_EQ(
-      Position(one->firstChild(), 0),
-      LastEditableVisiblePositionBeforePositionInRoot(Position(three, 0), *host)
-          .DeepEquivalent());
+  EXPECT_EQ(Position(one->firstChild(), 0),
+            CreateVisiblePosition(LastEditablePositionBeforePositionInRoot(
+                                      Position(three, 0), *host))
+                .DeepEquivalent());
   EXPECT_EQ(PositionInFlatTree::FirstPositionInNode(*host),
             LastEditablePositionBeforePositionInRoot(
                 PositionInFlatTree(three, 0), *host));
   EXPECT_EQ(PositionInFlatTree(two->firstChild(), 0),
-            LastEditableVisiblePositionBeforePositionInRoot(
-                PositionInFlatTree(three, 0), *host)
+            CreateVisiblePosition(LastEditablePositionBeforePositionInRoot(
+                                      PositionInFlatTree(three, 0), *host))
                 .DeepEquivalent());
 }
 
diff --git a/third_party/blink/renderer/core/editing/ime/input_method_controller.cc b/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
index 664a292..2c5b077 100644
--- a/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
+++ b/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
@@ -1396,21 +1396,21 @@
 
   if (mode.IsEmpty())
     return kWebTextInputModeDefault;
-  if (mode == InputModeNames::none)
+  if (mode == input_mode_names::kNone)
     return kWebTextInputModeNone;
-  if (mode == InputModeNames::text)
+  if (mode == input_mode_names::kText)
     return kWebTextInputModeText;
-  if (mode == InputModeNames::tel)
+  if (mode == input_mode_names::kTel)
     return kWebTextInputModeTel;
-  if (mode == InputModeNames::url)
+  if (mode == input_mode_names::kUrl)
     return kWebTextInputModeUrl;
-  if (mode == InputModeNames::email)
+  if (mode == input_mode_names::kEmail)
     return kWebTextInputModeEmail;
-  if (mode == InputModeNames::numeric)
+  if (mode == input_mode_names::kNumeric)
     return kWebTextInputModeNumeric;
-  if (mode == InputModeNames::decimal)
+  if (mode == input_mode_names::kDecimal)
     return kWebTextInputModeDecimal;
-  if (mode == InputModeNames::search)
+  if (mode == input_mode_names::kSearch)
     return kWebTextInputModeSearch;
   return kWebTextInputModeDefault;
 }
diff --git a/third_party/blink/renderer/core/editing/input_mode_names.json5 b/third_party/blink/renderer/core/editing/input_mode_names.json5
index e210b74..ff05487 100644
--- a/third_party/blink/renderer/core/editing/input_mode_names.json5
+++ b/third_party/blink/renderer/core/editing/input_mode_names.json5
@@ -1,6 +1,6 @@
 {
   metadata: {
-    namespace: "InputMode",
+    namespace: "input_mode_names",
     export: "CORE_EXPORT",
   },
 
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
index 82e723f..f09ec916 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -282,7 +282,7 @@
   Member<MarkerLists>& markers =
       markers_.insert(&text, nullptr).stored_value->value;
   if (!markers) {
-    markers = new MarkerLists;
+    markers = MakeGarbageCollected<MarkerLists>();
     markers->Grow(DocumentMarker::kMarkerTypeIndexesCount);
   }
 
@@ -313,8 +313,8 @@
     return;
 
   if (!markers_.Contains(&dst_node)) {
-    markers_.insert(&dst_node,
-                    new MarkerLists(DocumentMarker::kMarkerTypeIndexesCount));
+    markers_.insert(&dst_node, MakeGarbageCollected<MarkerLists>(
+                                   DocumentMarker::kMarkerTypeIndexesCount));
   }
   MarkerLists* const dst_markers = markers_.at(&dst_node);
 
diff --git a/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor_test.cc b/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor_test.cc
index 2783c29..2a7d8d16 100644
--- a/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor_test.cc
+++ b/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor_test.cc
@@ -16,7 +16,8 @@
 class UnsortedDocumentMarkerListEditorTest : public testing::Test {
  public:
   UnsortedDocumentMarkerListEditorTest()
-      : marker_list_(new HeapVector<Member<DocumentMarker>>) {}
+      : marker_list_(
+            MakeGarbageCollected<HeapVector<Member<DocumentMarker>>>()) {}
 
  protected:
   DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) {
diff --git a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
index dc4e797..a72296d 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
@@ -163,8 +163,9 @@
 
     if (!GetFrame().GetDocument()->documentElement())
       return;
-    position = FirstEditableVisiblePositionAfterPositionInRoot(
-                   position, *GetFrame().GetDocument()->documentElement())
+    position = CreateVisiblePosition(
+                   FirstEditablePositionAfterPositionInRoot(
+                       position, *GetFrame().GetDocument()->documentElement()))
                    .DeepEquivalent();
     if (position.IsNull())
       return;
diff --git a/third_party/blink/renderer/core/editing/visible_units.cc b/third_party/blink/renderer/core/editing/visible_units.cc
index d3c3e77..9b488c0 100644
--- a/third_party/blink/renderer/core/editing/visible_units.cc
+++ b/third_party/blink/renderer/core/editing/visible_units.cc
@@ -1079,8 +1079,8 @@
   // That must mean that |pos| is not editable. Return the next position after
   // |pos| that is in the same editable region as this position
   DCHECK(highest_root);
-  return FirstEditableVisiblePositionAfterPositionInRoot(pos.DeepEquivalent(),
-                                                         *highest_root);
+  return CreateVisiblePosition(FirstEditablePositionAfterPositionInRoot(
+      pos.DeepEquivalent(), *highest_root));
 }
 
 template <typename Strategy>
@@ -1193,8 +1193,8 @@
   // That must mean that |pos| is not editable. Return the last position
   // before |pos| that is in the same editable region as this position
   DCHECK(highest_root);
-  return LastEditableVisiblePositionBeforePositionInRoot(pos.DeepEquivalent(),
-                                                         *highest_root);
+  return CreateVisiblePosition(LastEditablePositionBeforePositionInRoot(
+      pos.DeepEquivalent(), *highest_root));
 }
 
 template <typename Strategy>
diff --git a/third_party/blink/renderer/core/events/message_event.cc b/third_party/blink/renderer/core/events/message_event.cc
index 1d32bb8d..7f8f440 100644
--- a/third_party/blink/renderer/core/events/message_event.cc
+++ b/third_party/blink/renderer/core/events/message_event.cc
@@ -78,7 +78,7 @@
   if (initializer.hasSource() && IsValidSource(initializer.source()))
     source_ = initializer.source();
   if (initializer.hasPorts())
-    ports_ = new MessagePortArray(initializer.ports());
+    ports_ = MakeGarbageCollected<MessagePortArray>(initializer.ports());
   if (initializer.hasUserActivation())
     user_activation_ = initializer.userActivation();
   DCHECK(IsValidSource(source_.Get()));
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index 409e5d0..114f9e4 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -354,10 +354,9 @@
                            thread_startup_data, DevToolsAgent::From(document),
                            parent_execution_context_task_runners_);
   // TODO(nhiroki): Support module workers (https://crbug.com/680046).
-  // Shared worker is origin-bound, so use kSharableCrossOrigin.
-  GetWorkerThread()->EvaluateClassicScript(
-      script_response_url, kSharableCrossOrigin, source_code,
-      nullptr /* cached_meta_data */, v8_inspector::V8StackTraceId());
+  GetWorkerThread()->EvaluateClassicScript(script_response_url, source_code,
+                                           nullptr /* cached_meta_data */,
+                                           v8_inspector::V8StackTraceId());
   client_->WorkerScriptLoaded();
 }
 
diff --git a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
index e0ab571..890e29a 100644
--- a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
@@ -343,7 +343,7 @@
    public:
     bool Initialize(const HTTPHeaderMap& header_fields) {
       const ParsedContentDisposition disposition(
-          header_fields.Get(HTTPNames::Content_Disposition));
+          header_fields.Get(http_names::kContentDisposition));
       const String disposition_type = disposition.Type();
       filename_ = disposition.Filename();
       name_ = disposition.ParameterValueForName("name");
@@ -354,7 +354,7 @@
       if (!filename_.IsNull()) {
         blob_data_ = BlobData::Create();
         const AtomicString& content_type =
-            header_fields.Get(HTTPNames::Content_Type);
+            header_fields.Get(http_names::kContentType);
         blob_data_->SetContentType(content_type.IsNull() ? "text/plain"
                                                          : content_type);
       } else {
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc
index f9a9072..24cc9f61 100644
--- a/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -106,7 +106,7 @@
 
 bool HasNonEmptyLocationHeader(const FetchHeaderList* headers) {
   String value;
-  if (!headers->Get(HTTPNames::Location, value))
+  if (!headers->Get(http_names::kLocation, value))
     return false;
   return !value.IsEmpty();
 }
@@ -839,8 +839,8 @@
                                AtomicString(header.second));
   }
 
-  if (fetch_request_data_->Method() != HTTPNames::GET &&
-      fetch_request_data_->Method() != HTTPNames::HEAD) {
+  if (fetch_request_data_->Method() != http_names::kGET &&
+      fetch_request_data_->Method() != http_names::kHEAD) {
     if (fetch_request_data_->Buffer()) {
       request.SetHTTPBody(
           fetch_request_data_->Buffer()->DrainAsFormData(exception_state));
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data.cc b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
index 7db662c8..636cd3d 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
@@ -124,7 +124,7 @@
 FetchRequestData::~FetchRequestData() {}
 
 FetchRequestData::FetchRequestData()
-    : method_(HTTPNames::GET),
+    : method_(http_names::kGET),
       header_list_(FetchHeaderList::Create()),
       context_(mojom::RequestContextType::UNSPECIFIED),
       same_origin_data_url_flag_(false),
diff --git a/third_party/blink/renderer/core/fetch/multipart_parser_test.cc b/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
index afdf013..e3085fc 100644
--- a/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
+++ b/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
@@ -83,18 +83,18 @@
     EXPECT_TRUE(client->GetPart(0).data_fully_received);
     EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
     EXPECT_EQ("application/xhtml+xml",
-              client->GetPart(1).header_fields.Get(HTTPNames::Content_Type));
+              client->GetPart(1).header_fields.Get(http_names::kContentType));
     EXPECT_EQ("1", toString(client->GetPart(1).data));
     EXPECT_TRUE(client->GetPart(1).data_fully_received);
     EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
     EXPECT_EQ("text/html",
-              client->GetPart(2).header_fields.Get(HTTPNames::Content_Type));
+              client->GetPart(2).header_fields.Get(http_names::kContentType));
     EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
               toString(client->GetPart(2).data));
     EXPECT_TRUE(client->GetPart(2).data_fully_received);
     EXPECT_EQ(1u, client->GetPart(3).header_fields.size());
     EXPECT_EQ("text/plain; charset=iso-8859-1",
-              client->GetPart(3).header_fields.Get(HTTPNames::Content_Type));
+              client->GetPart(3).header_fields.Get(http_names::kContentType));
     EXPECT_EQ("333", toString(client->GetPart(3).data));
     EXPECT_TRUE(client->GetPart(3).data_fully_received);
   }
@@ -126,18 +126,18 @@
     EXPECT_TRUE(client->GetPart(0).data_fully_received);
     EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
     EXPECT_EQ("application/xhtml+xml",
-              client->GetPart(1).header_fields.Get(HTTPNames::Content_Type));
+              client->GetPart(1).header_fields.Get(http_names::kContentType));
     EXPECT_EQ("1", toString(client->GetPart(1).data));
     EXPECT_TRUE(client->GetPart(1).data_fully_received);
     EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
     EXPECT_EQ("text/html",
-              client->GetPart(2).header_fields.Get(HTTPNames::Content_Type));
+              client->GetPart(2).header_fields.Get(http_names::kContentType));
     EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
               toString(client->GetPart(2).data));
     EXPECT_TRUE(client->GetPart(2).data_fully_received);
     EXPECT_EQ(1u, client->GetPart(3).header_fields.size());
     EXPECT_EQ("text/plain; charset=iso-8859-1",
-              client->GetPart(3).header_fields.Get(HTTPNames::Content_Type));
+              client->GetPart(3).header_fields.Get(http_names::kContentType));
     switch (end) {
       case 15u:
         EXPECT_EQ("333\r\n--boundar", toString(client->GetPart(3).data));
@@ -165,7 +165,7 @@
   EXPECT_EQ(1u, client->NumberOfParts());
   EXPECT_EQ(1u, client->GetPart(0).header_fields.size());
   EXPECT_EQ("application/xhtml+xml",
-            client->GetPart(0).header_fields.Get(HTTPNames::Content_Type));
+            client->GetPart(0).header_fields.Get(http_names::kContentType));
   EXPECT_EQ("1", toString(client->GetPart(0).data));
   EXPECT_FALSE(client->GetPart(0).data_fully_received);
 }
@@ -220,19 +220,19 @@
         EXPECT_EQ(3u, client->NumberOfParts()) << " start=" << start;
         EXPECT_EQ(1u, client->GetPart(0).header_fields.size());
         EXPECT_EQ("application/xhtml+xml", client->GetPart(0).header_fields.Get(
-                                               HTTPNames::Content_Type));
+                                               http_names::kContentType));
         EXPECT_EQ("1", toString(client->GetPart(0).data));
         EXPECT_TRUE(client->GetPart(0).data_fully_received);
         EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
         EXPECT_EQ("text/html", client->GetPart(1).header_fields.Get(
-                                   HTTPNames::Content_Type));
+                                   http_names::kContentType));
         EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
                   toString(client->GetPart(1).data));
         EXPECT_TRUE(client->GetPart(1).data_fully_received);
         EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
         EXPECT_EQ(
             "text/plain; charset=iso-8859-1",
-            client->GetPart(2).header_fields.Get(HTTPNames::Content_Type));
+            client->GetPart(2).header_fields.Get(http_names::kContentType));
         EXPECT_EQ("333", toString(client->GetPart(2).data));
         EXPECT_TRUE(client->GetPart(2).data_fully_received);
         break;
@@ -243,19 +243,19 @@
         EXPECT_TRUE(client->GetPart(0).data_fully_received);
         EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
         EXPECT_EQ("application/xhtml+xml", client->GetPart(1).header_fields.Get(
-                                               HTTPNames::Content_Type));
+                                               http_names::kContentType));
         EXPECT_EQ("1", toString(client->GetPart(1).data));
         EXPECT_TRUE(client->GetPart(1).data_fully_received);
         EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
         EXPECT_EQ("text/html", client->GetPart(2).header_fields.Get(
-                                   HTTPNames::Content_Type));
+                                   http_names::kContentType));
         EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
                   toString(client->GetPart(2).data));
         EXPECT_TRUE(client->GetPart(2).data_fully_received);
         EXPECT_EQ(1u, client->GetPart(3).header_fields.size());
         EXPECT_EQ(
             "text/plain; charset=iso-8859-1",
-            client->GetPart(3).header_fields.Get(HTTPNames::Content_Type));
+            client->GetPart(3).header_fields.Get(http_names::kContentType));
         EXPECT_EQ("333", toString(client->GetPart(3).data));
         EXPECT_TRUE(client->GetPart(3).data_fully_received);
         break;
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc
index 36a7d99..0a25316 100644
--- a/third_party/blink/renderer/core/fetch/request.cc
+++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -504,8 +504,8 @@
   v8::Local<v8::Value> init_body =
       init.hasBody() ? init.body().V8Value() : v8::Local<v8::Value>();
   if ((!init_body.IsEmpty() && !init_body->IsNull()) || temporary_body) {
-    if (request->Method() == HTTPNames::GET ||
-        request->Method() == HTTPNames::HEAD) {
+    if (request->Method() == http_names::kGET ||
+        request->Method() == http_names::kHEAD) {
       exception_state.ThrowTypeError(
           "Request with GET/HEAD method cannot have body.");
       return nullptr;
@@ -529,8 +529,8 @@
     temporary_body =
         ExtractBody(script_state, exception_state, init_body, content_type);
     if (!content_type.IsEmpty() &&
-        !r->getHeaders()->has(HTTPNames::Content_Type, exception_state)) {
-      r->getHeaders()->append(HTTPNames::Content_Type, content_type,
+        !r->getHeaders()->has(http_names::kContentType, exception_state)) {
+      r->getHeaders()->append(http_names::kContentType, content_type,
                               exception_state);
     }
     if (exception_state.HadException())
@@ -910,7 +910,7 @@
 
 String Request::ContentType() const {
   String result;
-  request_->HeaderList()->Get(HTTPNames::Content_Type, result);
+  request_->HeaderList()->Get(http_names::kContentType, result);
   return result;
 }
 
diff --git a/third_party/blink/renderer/core/fetch/response.cc b/third_party/blink/renderer/core/fetch/response.cc
index bccdd82..8c6e7f6 100644
--- a/third_party/blink/renderer/core/fetch/response.cc
+++ b/third_party/blink/renderer/core/fetch/response.cc
@@ -498,7 +498,7 @@
 
 String Response::ContentType() const {
   String result;
-  response_->HeaderList()->Get(HTTPNames::Content_Type, result);
+  response_->HeaderList()->Get(http_names::kContentType, result);
   return result;
 }
 
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 664bfe3..5cbfa0b 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -312,7 +312,7 @@
   if (parent_origin->CanAccess(SecurityOrigin::Create(response.Url()).get()))
     return true;
 
-  String header = response.HttpHeaderField(HTTPNames::Allow_CSP_From);
+  String header = response.HttpHeaderField(http_names::kAllowCSPFrom);
   header = header.StripWhiteSpace();
   if (header == "*")
     return true;
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
index 37bf3d3..92596ce 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -936,23 +936,23 @@
                   response, secure_origin.get()),
               test.inherits);
 
-    response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From, AtomicString("*"));
+    response.SetHTTPHeaderField(http_names::kAllowCSPFrom, AtomicString("*"));
     EXPECT_TRUE(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
         response, secure_origin.get()));
 
-    response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From,
+    response.SetHTTPHeaderField(http_names::kAllowCSPFrom,
                                 AtomicString("* not a valid header"));
     EXPECT_EQ(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
                   response, secure_origin.get()),
               test.inherits);
 
-    response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From,
+    response.SetHTTPHeaderField(http_names::kAllowCSPFrom,
                                 AtomicString("http://example.test"));
     EXPECT_EQ(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
                   response, secure_origin.get()),
               test.inherits);
 
-    response.SetHTTPHeaderField(HTTPNames::Allow_CSP_From,
+    response.SetHTTPHeaderField(http_names::kAllowCSPFrom,
                                 AtomicString("https://example.test"));
     EXPECT_TRUE(ContentSecurityPolicy::ShouldEnforceEmbeddersPolicy(
         response, secure_origin.get()));
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
index ad62893..8ca35ae 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h"
 
 #include "base/location.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
@@ -73,66 +75,47 @@
 
 void RecordIdleTaskStatusHistogram(
     CanvasAsyncBlobCreator::IdleTaskStatus status) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram,
-                                  to_blob_idle_task_status,
-                                  ("Blink.Canvas.ToBlob.IdleTaskStatus",
-                                   CanvasAsyncBlobCreator::kIdleTaskCount));
-  to_blob_idle_task_status.Count(status);
+  UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.ToBlob.IdleTaskStatus", status);
 }
 
-// This enum is used in histogram and any more types should be appended at the
-// end of the list.
-enum ElapsedTimeHistogramType {
-  kInitiateEncodingDelay,
-  kCompleteEncodingDelay,
-  kToBlobDuration,
-  kNumberOfElapsedTimeHistogramTypes
-};
+void RecordInitiateEncodingTimeHistogram(ImageEncodingMimeType mime_type,
+                                         TimeDelta elapsed_time) {
+  if (mime_type == kMimeTypePng) {
+    UmaHistogramMicrosecondsTimes(
+        "Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", elapsed_time);
+  } else if (mime_type == kMimeTypeJpeg) {
+    UmaHistogramMicrosecondsTimes(
+        "Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", elapsed_time);
+  }
+}
 
-void RecordElapsedTimeHistogram(ElapsedTimeHistogramType type,
-                                ImageEncodingMimeType mime_type,
-                                TimeDelta elapsed_time) {
-  if (type == kInitiateEncodingDelay) {
-    if (mime_type == kMimeTypePng) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_png_initiate_encoding_counter,
-          ("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50));
-      to_blob_png_initiate_encoding_counter.CountMicroseconds(elapsed_time);
-    } else if (mime_type == kMimeTypeJpeg) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_jpeg_initiate_encoding_counter,
-          ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50));
-      to_blob_jpeg_initiate_encoding_counter.CountMicroseconds(elapsed_time);
-    }
-  } else if (type == kCompleteEncodingDelay) {
-    if (mime_type == kMimeTypePng) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_png_idle_encode_counter,
-          ("Blink.Canvas.ToBlob.CompleteEncodingDelay.PNG", 0, 10000000, 50));
-      to_blob_png_idle_encode_counter.CountMicroseconds(elapsed_time);
-    } else if (mime_type == kMimeTypeJpeg) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_jpeg_idle_encode_counter,
-          ("Blink.Canvas.ToBlob.CompleteEncodingDelay.JPEG", 0, 10000000, 50));
-      to_blob_jpeg_idle_encode_counter.CountMicroseconds(elapsed_time);
-    }
-  } else if (type == kToBlobDuration) {
-    if (mime_type == kMimeTypePng) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_png_counter,
-          ("Blink.Canvas.ToBlobDuration.PNG", 0, 10000000, 50));
-      to_blob_png_counter.CountMicroseconds(elapsed_time);
-    } else if (mime_type == kMimeTypeJpeg) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_jpeg_counter,
-          ("Blink.Canvas.ToBlobDuration.JPEG", 0, 10000000, 50));
-      to_blob_jpeg_counter.CountMicroseconds(elapsed_time);
-    } else if (mime_type == kMimeTypeWebp) {
-      DEFINE_THREAD_SAFE_STATIC_LOCAL(
-          CustomCountHistogram, to_blob_webp_counter,
-          ("Blink.Canvas.ToBlobDuration.WEBP", 0, 10000000, 50));
-      to_blob_webp_counter.CountMicroseconds(elapsed_time);
-    }
+void RecordCompleteEncodingTimeHistogram(ImageEncodingMimeType mime_type,
+                                         TimeDelta elapsed_time) {
+  if (mime_type == kMimeTypePng) {
+    UmaHistogramMicrosecondsTimes(
+        "Blink.Canvas.ToBlob.CompleteEncodingDelay.PNG", elapsed_time);
+  } else if (mime_type == kMimeTypeJpeg) {
+    UmaHistogramMicrosecondsTimes(
+        "Blink.Canvas.ToBlob.CompleteEncodingDelay.JPEG", elapsed_time);
+  }
+}
+
+void RecordScaledDurationHistogram(ImageEncodingMimeType mime_type,
+                                   TimeDelta elapsed_time,
+                                   int width,
+                                   int height) {
+  float sqrt_pixels = std::sqrt(width * height);
+  int scaled_time =
+      elapsed_time.InMicrosecondsF() / (sqrt_pixels == 0 ? 1 : sqrt_pixels);
+  if (mime_type == kMimeTypePng) {
+    UMA_HISTOGRAM_COUNTS_100000("Blink.Canvas.ToBlob.ScaledDuration.PNG",
+                                scaled_time);
+  } else if (mime_type == kMimeTypeJpeg) {
+    UMA_HISTOGRAM_COUNTS_100000("Blink.Canvas.ToBlob.ScaledDuration.JPEG",
+                                scaled_time);
+  } else if (mime_type == kMimeTypeWebp) {
+    UMA_HISTOGRAM_COUNTS_100000("Blink.Canvas.ToBlob.ScaledDuration.WEBP",
+                                scaled_time);
   }
 }
 
@@ -371,9 +354,8 @@
   if (idle_task_status_ == kIdleTaskSwitchedToImmediateTask) {
     return;
   }
-  RecordElapsedTimeHistogram(
-      kInitiateEncodingDelay, mime_type_,
-      WTF::CurrentTimeTicks() - schedule_idle_task_start_time_);
+  RecordInitiateEncodingTimeHistogram(
+      mime_type_, WTF::CurrentTimeTicks() - schedule_idle_task_start_time_);
 
   DCHECK(idle_task_status_ == kIdleTaskNotStarted);
   idle_task_status_ = kIdleTaskStarted;
@@ -413,7 +395,7 @@
   idle_task_status_ = kIdleTaskCompleted;
   TimeDelta elapsed_time =
       WTF::CurrentTimeTicks() - schedule_idle_task_start_time_;
-  RecordElapsedTimeHistogram(kCompleteEncodingDelay, mime_type_, elapsed_time);
+  RecordCompleteEncodingTimeHistogram(mime_type_, elapsed_time);
   if (IsCreateBlobDeadlineNearOrPassed(deadline)) {
     context_->GetTaskRunner(TaskType::kCanvasBlobSerialization)
         ->PostTask(FROM_HERE,
@@ -451,8 +433,6 @@
 
 void CanvasAsyncBlobCreator::CreateBlobAndReturnResult() {
   RecordIdleTaskStatusHistogram(idle_task_status_);
-  RecordElapsedTimeHistogram(kToBlobDuration, mime_type_,
-                             WTF::CurrentTimeTicks() - start_time_);
 
   Blob* result_blob = Blob::Create(encoded_image_.data(), encoded_image_.size(),
                                    ImageEncodingMimeTypeName(mime_type_));
@@ -466,6 +446,10 @@
   } else {
     script_promise_resolver_->Resolve(result_blob);
   }
+
+  RecordScaledDurationHistogram(mime_type_,
+                                WTF::CurrentTimeTicks() - start_time_,
+                                image_->width(), image_->height());
   // Avoid unwanted retention, see dispose().
   Dispose();
 }
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
index 0373a08..8e9fa6c 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
@@ -36,18 +36,16 @@
 class CORE_EXPORT CanvasAsyncBlobCreator
     : public GarbageCollectedFinalized<CanvasAsyncBlobCreator> {
  public:
-
   // This enum is used to back an UMA histogram, and should therefore be treated
-  // as append-only.
+  // as append-only. Idle tasks are not implemented for some image types.
   enum IdleTaskStatus {
-    kIdleTaskNotStarted,
-    kIdleTaskStarted,
-    kIdleTaskCompleted,
-    kIdleTaskFailed,
-    kIdleTaskSwitchedToImmediateTask,
-    kIdleTaskNotSupported,  // Idle tasks are not implemented for some image
-                            // types
-    kIdleTaskCount,         // Should not be seen in production
+    kIdleTaskNotStarted = 0,
+    kIdleTaskStarted = 1,
+    kIdleTaskCompleted = 2,
+    kIdleTaskFailed = 3,
+    kIdleTaskSwitchedToImmediateTask = 4,
+    kIdleTaskNotSupported = 5,
+    kMaxValue = kIdleTaskNotSupported,
   };
   enum ToBlobFunctionType {
     kHTMLCanvasToBlobCallback,
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc b/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc
index 17f2895..48b65d6 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc
@@ -66,7 +66,7 @@
                                          Element* element,
                                          CustomElementReaction* reaction) {
   if (!queue)
-    queue = new ElementQueue();
+    queue = MakeGarbageCollected<ElementQueue>();
   queue->push_back(element);
 
   CustomElementReactionQueue* reactions = map_.at(element);
diff --git a/third_party/blink/renderer/core/html/forms/date_time_field_element.cc b/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
index de003201..c0922ab 100644
--- a/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
+++ b/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
@@ -196,10 +196,10 @@
 void DateTimeFieldElement::SetDisabled() {
   // Set HTML attribute disabled to change apperance.
   SetBooleanAttribute(kDisabledAttr, true);
-  SetNeedsStyleRecalc(
-      kSubtreeStyleChange,
-      StyleChangeReasonForTracing::CreateWithExtraData(
-          style_change_reason::kPseudoClass, StyleChangeExtraData::g_disabled));
+  SetNeedsStyleRecalc(kSubtreeStyleChange,
+                      StyleChangeReasonForTracing::CreateWithExtraData(
+                          style_change_reason::kPseudoClass,
+                          style_change_extra_data::g_disabled));
 }
 
 bool DateTimeFieldElement::SupportsFocus() const {
diff --git a/third_party/blink/renderer/core/html/forms/html_legend_element.cc b/third_party/blink/renderer/core/html/forms/html_legend_element.cc
index 98f698c..a17111c22 100644
--- a/third_party/blink/renderer/core/html/forms/html_legend_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_legend_element.cc
@@ -25,10 +25,7 @@
 #include "third_party/blink/renderer/core/html/forms/html_legend_element.h"
 
 #include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
 #include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
-#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
 
 namespace blink {
@@ -40,43 +37,6 @@
 
 DEFINE_NODE_FACTORY(HTMLLegendElement)
 
-HTMLFormControlElement* HTMLLegendElement::AssociatedControl() {
-  // Check if there's a fieldset belonging to this legend.
-  HTMLFieldSetElement* fieldset =
-      Traversal<HTMLFieldSetElement>::FirstAncestor(*this);
-  if (!fieldset)
-    return nullptr;
-
-  // Find first form element inside the fieldset that is not a legend element.
-  // FIXME: Should we consider tabindex?
-  if (auto* control =
-          Traversal<HTMLFormControlElement>::Next(*fieldset, fieldset)) {
-    UseCounter::Count(GetDocument(),
-                      WebFeature::kLegendDelegateFocusOrAccessKey);
-    return control;
-  }
-  return nullptr;
-}
-
-void HTMLLegendElement::focus(const FocusParams& params) {
-  GetDocument().UpdateStyleAndLayoutTreeForNode(this);
-  if (IsFocusable()) {
-    Element::focus(params);
-    return;
-  }
-
-  // To match other browsers' behavior, never restore previous selection.
-  if (HTMLFormControlElement* control = AssociatedControl()) {
-    control->focus(FocusParams(SelectionBehaviorOnFocus::kReset, params.type,
-                               params.source_capabilities, params.options));
-  }
-}
-
-void HTMLLegendElement::AccessKeyAction(bool send_mouse_events) {
-  if (HTMLFormControlElement* control = AssociatedControl())
-    control->AccessKeyAction(send_mouse_events);
-}
-
 HTMLFormElement* HTMLLegendElement::form() const {
   // According to the specification, If the legend has a fieldset element as
   // its parent, then the form attribute must return the same value as the
diff --git a/third_party/blink/renderer/core/html/forms/html_legend_element.h b/third_party/blink/renderer/core/html/forms/html_legend_element.h
index c69a718..802daeb 100644
--- a/third_party/blink/renderer/core/html/forms/html_legend_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_legend_element.h
@@ -28,8 +28,6 @@
 
 namespace blink {
 
-class HTMLFormControlElement;
-
 class HTMLLegendElement final : public HTMLElement {
   DEFINE_WRAPPERTYPEINFO();
 
@@ -40,12 +38,6 @@
 
  private:
   explicit HTMLLegendElement(Document&);
-
-  // Control in the legend's fieldset that gets focus and access key.
-  HTMLFormControlElement* AssociatedControl();
-
-  void AccessKeyAction(bool send_mouse_events) override;
-  void focus(const FocusParams&) override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/imports/html_import_loader.cc b/third_party/blink/renderer/core/html/imports/html_import_loader.cc
index 92e15b0..7f72b8d 100644
--- a/third_party/blink/renderer/core/html/imports/html_import_loader.cc
+++ b/third_party/blink/renderer/core/html/imports/html_import_loader.cc
@@ -69,7 +69,7 @@
   // Resource may already have been loaded with the import loader
   // being added as a client later & now being notified. Fail early.
   if (resource->LoadFailedOrCanceled() || response.HttpStatusCode() >= 400 ||
-      !response.HttpHeaderField(HTTPNames::Content_Disposition).IsNull()) {
+      !response.HttpHeaderField(http_names::kContentDisposition).IsNull()) {
     SetState(kStateError);
     return;
   }
diff --git a/third_party/blink/renderer/core/html/parser/xss_auditor.cc b/third_party/blink/renderer/core/html/parser/xss_auditor.cc
index 2abfec8..c052b22 100644
--- a/third_party/blink/renderer/core/html/parser/xss_auditor.cc
+++ b/third_party/blink/renderer/core/html/parser/xss_auditor.cc
@@ -402,7 +402,7 @@
           document->GetFrame()->Loader().GetDocumentLoader()) {
     const AtomicString& header_value =
         document_loader->GetResponse().HttpHeaderField(
-            HTTPNames::X_XSS_Protection);
+            http_names::kXXSSProtection);
     String error_details;
     unsigned error_position = 0;
     String report_url;
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
index 7ce52ef..524221f 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
@@ -132,7 +132,7 @@
   SetNeedsStyleRecalc(
       kLocalStyleChange,
       StyleChangeReasonForTracing::CreateWithExtraData(
-          style_change_reason::kPseudoClass, StyleChangeExtraData::g_past));
+          style_change_reason::kPseudoClass, style_change_extra_data::g_past));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/input/event_handler.h b/third_party/blink/renderer/core/input/event_handler.h
index 57d7422..e5a0c96 100644
--- a/third_party/blink/renderer/core/input/event_handler.h
+++ b/third_party/blink/renderer/core/input/event_handler.h
@@ -78,6 +78,7 @@
 class WebMouseEvent;
 class WebMouseWheelEvent;
 
+// Handles events for Pointers (Mouse/Touch), HitTests, DragAndDrop, etc.
 class CORE_EXPORT EventHandler final
     : public GarbageCollectedFinalized<EventHandler> {
  public:
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index f92bf22..4729cba 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -835,7 +835,7 @@
       // use ResourceRequest::referrer_. See https://crbug.com/850813. This
       // seems to require storing the referrer info that is currently stored
       // inside state_'s kExtraRequestHeaders, somewhere else.
-      if (header_name.LowerASCII() == HTTPNames::Referer.LowerASCII())
+      if (header_name.LowerASCII() == http_names::kReferer.LowerASCII())
         request.SetHTTPReferrer(Referrer(value, kReferrerPolicyAlways));
       else
         request.SetHTTPHeaderField(header_name, AtomicString(value));
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index 7426bd9..6f98b1f 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -318,7 +318,8 @@
     return;
 
   // FIXME: Use the actual rule type rather than STYLE_RULE?
-  CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList();
+  CSSRuleSourceDataList* source_data =
+      MakeGarbageCollected<CSSRuleSourceDataList>();
 
   StyleSheetHandler handler(comment_text, document_, source_data);
   CSSParser::ParseDeclarationListForInspector(
@@ -345,7 +346,8 @@
   DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee"));
   StyleSheetContents* style_sheet =
       StyleSheetContents::Create(ParserContextForDocument(document));
-  CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList();
+  CSSRuleSourceDataList* source_data =
+      MakeGarbageCollected<CSSRuleSourceDataList>();
   String text = rule_text + " div { " + bogus_property_name + ": none; }";
   StyleSheetHandler handler(text, document, source_data);
   CSSParser::ParseSheetForInspector(ParserContextForDocument(document),
@@ -382,7 +384,8 @@
 bool VerifyKeyframeKeyText(Document* document, const String& key_text) {
   StyleSheetContents* style_sheet =
       StyleSheetContents::Create(ParserContextForDocument(document));
-  CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList();
+  CSSRuleSourceDataList* source_data =
+      MakeGarbageCollected<CSSRuleSourceDataList>();
   String text = "@keyframes boguzAnim { " + key_text +
                 " { -webkit-boguz-propertee : none; } }";
   StyleSheetHandler handler(text, document, source_data);
@@ -412,7 +415,8 @@
   DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee"));
   StyleSheetContents* style_sheet =
       StyleSheetContents::Create(ParserContextForDocument(document));
-  CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList();
+  CSSRuleSourceDataList* source_data =
+      MakeGarbageCollected<CSSRuleSourceDataList>();
   String text = selector_text + " { " + bogus_property_name + ": none; }";
   StyleSheetHandler handler(text, document, source_data);
   CSSParser::ParseSheetForInspector(ParserContextForDocument(document),
@@ -441,7 +445,8 @@
   DEFINE_STATIC_LOCAL(String, bogus_property_name, ("-webkit-boguz-propertee"));
   StyleSheetContents* style_sheet =
       StyleSheetContents::Create(ParserContextForDocument(document));
-  CSSRuleSourceDataList* source_data = new CSSRuleSourceDataList();
+  CSSRuleSourceDataList* source_data =
+      MakeGarbageCollected<CSSRuleSourceDataList>();
   String text = "@media " + media_text + " { div { " + bogus_property_name +
                 ": none; } }";
   StyleSheetHandler handler(text, document, source_data);
@@ -1410,7 +1415,8 @@
 
 void InspectorStyleSheet::InnerSetText(const String& text,
                                        bool mark_as_locally_modified) {
-  CSSRuleSourceDataList* rule_tree = new CSSRuleSourceDataList();
+  CSSRuleSourceDataList* rule_tree =
+      MakeGarbageCollected<CSSRuleSourceDataList>();
   StyleSheetContents* style_sheet = StyleSheetContents::Create(
       page_style_sheet_->Contents()->ParserContext());
   StyleSheetHandler handler(text, page_style_sheet_->OwnerDocument(),
@@ -1430,7 +1436,7 @@
   parsed_flat_rules_.clear();
   CollectFlatRules(source_data_sheet, &parsed_flat_rules_);
 
-  source_data_ = new CSSRuleSourceDataList();
+  source_data_ = MakeGarbageCollected<CSSRuleSourceDataList>();
   FlattenSourceData(*rule_tree, source_data_.Get());
   text_ = text;
 
@@ -1948,7 +1954,7 @@
     rule_source_data->rule_body_range.end = 0;
   } else {
     CSSRuleSourceDataList* rule_source_data_result =
-        new CSSRuleSourceDataList();
+        MakeGarbageCollected<CSSRuleSourceDataList>();
     StyleSheetHandler handler(text, &element_->GetDocument(),
                               rule_source_data_result);
     CSSParser::ParseDeclarationListForInspector(
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index dec3e998..d638111 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1747,7 +1747,8 @@
 std::ostream& operator<<(std::ostream& out, const LayoutObject& object) {
   StringBuilder string_builder;
   object.DumpLayoutObject(string_builder, false, 0);
-  return out << string_builder.ToString().Utf8().data();
+  return out << static_cast<const void*>(&object) << ":"
+             << string_builder.ToString().Utf8().data();
 }
 
 std::ostream& operator<<(std::ostream& out, const LayoutObject* object) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 7d17154..f45d5c1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -1912,12 +1912,16 @@
     writing_mode = Style().GetWritingMode();
   } else {
     const ComputedStyle& child_style = child.Style();
+    writing_mode = child_style.GetWritingMode();
+    bool is_shrink_to_fit =
+        !IsParallelWritingMode(ConstraintSpace().GetWritingMode(),
+                               writing_mode) &&
+        child_style.LogicalWidth().IsAuto();
     LayoutUnit child_clearance_offset =
         exclusion_space_.ClearanceOffset(child_style.Clear());
     clearance_offset = std::max(clearance_offset, child_clearance_offset);
-    space_builder.SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style));
+    space_builder.SetIsShrinkToFit(is_shrink_to_fit);
     space_builder.SetTextDirection(child_style.Direction());
-    writing_mode = child_style.GetWritingMode();
 
     // PositionListMarker() requires a first line baseline.
     if (container_builder_.UnpositionedListMarker()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 67252bb..a9b2f78a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -779,7 +779,7 @@
   const ComputedStyle& style = Style();
   NGConstraintSpace constraint_space =
       space_builder.SetIsNewFormattingContext(true)
-          .SetIsShrinkToFit(true)
+          .SetIsShrinkToFit(Style().LogicalWidth().IsAuto())
           .SetAvailableSize(parent_constraint_space.AvailableSize())
           .SetPercentageResolutionSize(
               parent_constraint_space.PercentageResolutionSize())
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index 548cdf19..4f33b3f7 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -201,7 +201,7 @@
       CalculateChildPercentageSize(ConstraintSpace(), Node(), available_size);
   builder.SetPercentageResolutionSize(percentage_size);
   builder.SetIsNewFormattingContext(true);
-  builder.SetIsShrinkToFit(true);
+  builder.SetIsShrinkToFit(legend.Style().LogicalWidth().IsAuto());
   builder.SetTextDirection(legend.Style().Direction());
   return builder.ToConstraintSpace(legend.Style().GetWritingMode());
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
index 9b91c8ab..818ac0b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
@@ -87,7 +87,7 @@
       .SetAvailableSize(float_available_size)
       .SetReplacedPercentageResolutionSize(float_replaced_percentage_size)
       .SetIsNewFormattingContext(true)
-      .SetIsShrinkToFit(true)
+      .SetIsShrinkToFit(style.LogicalWidth().IsAuto())
       .SetTextDirection(style.Direction())
       .ToConstraintSpace(style.GetWritingMode());
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc
index f43794d..cbd38d8 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_space_utils.cc
@@ -12,17 +12,6 @@
 
 namespace blink {
 
-bool ShouldShrinkToFit(const ComputedStyle& parent_style,
-                       const ComputedStyle& style) {
-  // Whether the child and the containing block are parallel to each other.
-  // Example: vertical-rl and vertical-lr
-  bool is_in_parallel_flow = IsParallelWritingMode(
-      parent_style.GetWritingMode(), style.GetWritingMode());
-
-  return style.Display() == EDisplay::kInlineBlock || style.IsFloating() ||
-         !is_in_parallel_flow;
-}
-
 bool AdjustToClearance(LayoutUnit clearance_offset, NGBfcOffset* offset) {
   DCHECK(offset);
   if (clearance_offset > offset->block_offset) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_space_utils.h b/third_party/blink/renderer/core/layout/ng/ng_space_utils.h
index 17774f6..3330a48 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_space_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_space_utils.h
@@ -13,15 +13,8 @@
 
 namespace blink {
 
-class ComputedStyle;
 struct NGBfcOffset;
 
-// Whether child's constraint space should shrink to its intrinsic width.
-// This is needed for buttons, select, input, floats and orthogonal children.
-// See LayoutBox::sizesLogicalWidthToFitContent for the rationale behind this.
-bool ShouldShrinkToFit(const ComputedStyle& parent_style,
-                       const ComputedStyle& style);
-
 // Adjusts {@code offset} to the clearance line.
 CORE_EXPORT bool AdjustToClearance(LayoutUnit clearance_offset,
                                    NGBfcOffset* offset);
diff --git a/third_party/blink/renderer/core/loader/allowed_by_nosniff.cc b/third_party/blink/renderer/core/loader/allowed_by_nosniff.cc
index 996deb625..c30ff61 100644
--- a/third_party/blink/renderer/core/loader/allowed_by_nosniff.cc
+++ b/third_party/blink/renderer/core/loader/allowed_by_nosniff.cc
@@ -140,7 +140,7 @@
 
   // Allowed by nosniff?
   if (!(ParseContentTypeOptionsHeader(response.HttpHeaderField(
-            HTTPNames::X_Content_Type_Options)) != kContentTypeOptionsNosniff ||
+            http_names::kXContentTypeOptions)) != kContentTypeOptionsNosniff ||
         MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type))) {
     execution_context->AddConsoleMessage(ConsoleMessage::Create(
         kSecurityMessageSource, kErrorMessageLevel,
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 510e197..fd155bb1 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -312,7 +312,7 @@
     LinkLoader::MediaPreloadPolicy media_policy) {
   DCHECK_GE(state_, kCommitted);
   LinkLoader::LoadLinksFromHeader(
-      GetResponse().HttpHeaderField(HTTPNames::Link), GetResponse().Url(),
+      GetResponse().HttpHeaderField(http_names::kLink), GetResponse().Url(),
       *frame_, frame_->GetDocument(), NetworkHintsInterfaceImpl(),
       LinkLoader::kOnlyLoadResources, media_policy, viewport);
 }
@@ -368,7 +368,7 @@
   request_.SetURL(new_url);
   SetReplacesCurrentHistoryItem(type != WebFrameLoadType::kStandard);
   if (same_document_navigation_source == kSameDocumentNavigationHistoryApi) {
-    request_.SetHTTPMethod(HTTPNames::GET);
+    request_.SetHTTPMethod(http_names::kGET);
     request_.SetHTTPBody(nullptr);
   }
   ClearRedirectChain();
@@ -594,7 +594,7 @@
   }
 
   if (IsContentDispositionAttachment(
-          response_.HttpHeaderField(HTTPNames::Content_Disposition))) {
+          response_.HttpHeaderField(http_names::kContentDisposition))) {
     // The server wants us to download instead of replacing the page contents.
     // Downloading is handled by the embedder, but we still get the initial
     // response so that we can ignore it and clean up properly.
@@ -786,7 +786,7 @@
   if (request_.WasDiscarded())
     frame_->GetDocument()->SetWasDiscarded(true);
   frame_->GetDocument()->MaybeHandleHttpRefresh(
-      response_.HttpHeaderField(HTTPNames::Refresh),
+      response_.HttpHeaderField(http_names::kRefresh),
       Document::kHttpRefreshFromHeader);
 }
 
@@ -999,12 +999,12 @@
   fetcher_->SetAutoLoadImages(settings->GetLoadsImagesAutomatically());
 
   const AtomicString& dns_prefetch_control =
-      response_.HttpHeaderField(HTTPNames::X_DNS_Prefetch_Control);
+      response_.HttpHeaderField(http_names::kXDNSPrefetchControl);
   if (!dns_prefetch_control.IsEmpty())
     document->ParseDNSPrefetchControlHeader(dns_prefetch_control);
 
   String header_content_language =
-      response_.HttpHeaderField(HTTPNames::Content_Language);
+      response_.HttpHeaderField(http_names::kContentLanguage);
   if (!header_content_language.IsEmpty()) {
     size_t comma_index = header_content_language.find(',');
     // kNotFound == -1 == don't truncate
@@ -1016,7 +1016,7 @@
   }
 
   String referrer_policy_header =
-      response_.HttpHeaderField(HTTPNames::Referrer_Policy);
+      response_.HttpHeaderField(http_names::kReferrerPolicy);
   if (!referrer_policy_header.IsNull()) {
     UseCounter::Count(*document, WebFeature::kReferrerPolicyHeader);
     document->ParseAndSetReferrerPolicy(referrer_policy_header);
@@ -1212,7 +1212,7 @@
           "ForceTouchEventFeatureDetectionForInspector");
     }
     OriginTrialContext::AddTokensFromHeader(
-        document, response_.HttpHeaderField(HTTPNames::Origin_Trial));
+        document, response_.HttpHeaderField(http_names::kOriginTrial));
   }
   bool stale_while_revalidate_enabled =
       OriginTrials::StaleWhileRevalidateEnabled(document);
@@ -1238,7 +1238,7 @@
   // be initialized and replicated to the browser process after commit messages
   // are sent in didCommitNavigation().
   document->ApplyFeaturePolicyFromHeader(
-      response_.HttpHeaderField(HTTPNames::Feature_Policy));
+      response_.HttpHeaderField(http_names::kFeaturePolicy));
 
   GetFrameLoader().DispatchDidClearDocumentOfWindowObject();
 }
diff --git a/third_party/blink/renderer/core/loader/form_submission.cc b/third_party/blink/renderer/core/loader/form_submission.cc
index 01f87e81..5e5756e 100644
--- a/third_party/blink/renderer/core/loader/form_submission.cc
+++ b/third_party/blink/renderer/core/loader/form_submission.cc
@@ -285,7 +285,7 @@
     frame_request.SetFrameName(target_);
 
   if (method_ == FormSubmission::kPostMethod) {
-    frame_request.GetResourceRequest().SetHTTPMethod(HTTPNames::POST);
+    frame_request.GetResourceRequest().SetHTTPMethod(http_names::kPOST);
     frame_request.GetResourceRequest().SetHTTPBody(form_data_);
 
     // construct some user headers if necessary
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 5a74886..b4f6afb 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -422,10 +422,10 @@
 
   // Reload should reflect the current data saver setting.
   if (IsReloadLoadType(MasterDocumentLoader()->LoadType()))
-    request.ClearHTTPHeaderField(HTTPNames::Save_Data);
+    request.ClearHTTPHeaderField(http_names::kSaveData);
 
   if (save_data_enabled_)
-    request.SetHTTPHeaderField(HTTPNames::Save_Data, "on");
+    request.SetHTTPHeaderField(http_names::kSaveData, "on");
 
   if (GetLocalFrameClient()->GetPreviewsStateForFrame() &
       WebURLRequest::kNoScriptOn) {
@@ -466,8 +466,8 @@
   DCHECK(GetFrame());
   if (type == ResourceType::kMainResource) {
     const auto cache_mode = DetermineCacheMode(
-        request.HttpMethod() == HTTPNames::POST ? RequestMethod::kIsPost
-                                                : RequestMethod::kIsNotPost,
+        request.HttpMethod() == http_names::kPOST ? RequestMethod::kIsPost
+                                                  : RequestMethod::kIsNotPost,
         request.IsConditional() ? RequestType::kIsConditional
                                 : RequestType::kIsNotConditional,
         MainResourceType::kIsMainResource, MasterDocumentLoader()->LoadType());
@@ -634,7 +634,7 @@
   }
 
   LinkLoader::LoadLinksFromHeader(
-      response.HttpHeaderField(HTTPNames::Link), response.Url(), *GetFrame(),
+      response.HttpHeaderField(http_names::kLink), response.Url(), *GetFrame(),
       document_, NetworkHintsInterfaceImpl(), resource_loading_policy,
       LinkLoader::kLoadAll, nullptr);
 
@@ -1347,12 +1347,12 @@
 
   document_loader_->GetClientHintsPreferences()
       .UpdateFromAcceptClientHintsLifetimeHeader(
-          response.HttpHeaderField(HTTPNames::Accept_CH_Lifetime),
+          response.HttpHeaderField(http_names::kAcceptCHLifetime),
           response.Url(), &hints_context);
 
   document_loader_->GetClientHintsPreferences()
       .UpdateFromAcceptClientHintsHeader(
-          response.HttpHeaderField(HTTPNames::Accept_CH), response.Url(),
+          response.HttpHeaderField(http_names::kAcceptCH), response.Url(),
           &hints_context);
 
   // Notify content settings client of persistent client hints.
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 ceda90f2..304434f8 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
@@ -356,14 +356,14 @@
 
     EXPECT_EQ(
         should_prefer ? String("1") : String(),
-        resource_request.HttpHeaderField(HTTPNames::Upgrade_Insecure_Requests));
+        resource_request.HttpHeaderField(http_names::kUpgradeInsecureRequests));
 
     // Calling modifyRequestForCSP more than once shouldn't affect the
     // header.
     if (should_prefer) {
       fetch_context->ModifyRequestForCSP(resource_request);
       EXPECT_EQ("1", resource_request.HttpHeaderField(
-                         HTTPNames::Upgrade_Insecure_Requests));
+                         http_names::kUpgradeInsecureRequests));
     }
   }
 
@@ -395,7 +395,7 @@
     fetch_context->ModifyRequestForCSP(resource_request);
 
     EXPECT_EQ(expected_required_csp,
-              resource_request.HttpHeaderField(HTTPNames::Sec_Required_CSP));
+              resource_request.HttpHeaderField(http_names::kSecRequiredCSP));
   }
 
   void SetFrameOwnerBasedOnFrameType(
@@ -848,7 +848,7 @@
 
   // Post
   ResourceRequest post_request("http://www.example.com");
-  post_request.SetHTTPMethod(HTTPNames::POST);
+  post_request.SetHTTPMethod(http_names::kPOST);
   EXPECT_EQ(mojom::FetchCacheMode::kValidateCache,
             fetch_context->ResourceRequestCachePolicy(
                 post_request, ResourceType::kMainResource,
@@ -871,7 +871,7 @@
   // Conditional request
   document->Loader()->SetLoadType(WebFrameLoadType::kStandard);
   ResourceRequest conditional("http://www.example.com");
-  conditional.SetHTTPHeaderField(HTTPNames::If_Modified_Since, "foo");
+  conditional.SetHTTPHeaderField(http_names::kIfModifiedSince, "foo");
   EXPECT_EQ(
       mojom::FetchCacheMode::kValidateCache,
       fetch_context->ResourceRequestCachePolicy(
@@ -955,7 +955,7 @@
   // Conditional request
   document->Loader()->SetLoadType(WebFrameLoadType::kStandard);
   ResourceRequest conditional("http://www.example.com/mock");
-  conditional.SetHTTPHeaderField(HTTPNames::If_Modified_Since, "foo");
+  conditional.SetHTTPHeaderField(http_names::kIfModifiedSince, "foo");
   EXPECT_EQ(mojom::FetchCacheMode::kValidateCache,
             fetch_context->ResourceRequestCachePolicy(
                 conditional, ResourceType::kMock, FetchParameters::kNoDefer));
@@ -1214,8 +1214,9 @@
 
   fetch_context->AddAdditionalRequestHeaders(request, kFetchSubresource);
 
-  EXPECT_EQ(origin, request.HttpHeaderField(HTTPNames::Origin));
-  EXPECT_EQ(String(origin + "/"), request.HttpHeaderField(HTTPNames::Referer));
+  EXPECT_EQ(origin, request.HttpHeaderField(http_names::kOrigin));
+  EXPECT_EQ(String(origin + "/"),
+            request.HttpHeaderField(http_names::kReferer));
   EXPECT_EQ(String(), request.HttpHeaderField("Save-Data"));
 }
 
@@ -1253,7 +1254,7 @@
   fetch_context->PrepareRequest(request,
                                 FetchContext::RedirectType::kNotForRedirect);
 
-  EXPECT_EQ("hi", request.HttpHeaderField(HTTPNames::User_Agent));
+  EXPECT_EQ("hi", request.HttpHeaderField(http_names::kUserAgent));
 }
 
 TEST_F(FrameFetchContextTest, DispatchWillSendRequestWhenDetached) {
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 8a919b3..1e9e045 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -683,7 +683,7 @@
     return WebFrameLoadType::kReplaceCurrentItem;
 
   if (resource_request.Url() == document_loader_->UrlForHistory()) {
-    if (resource_request.HttpMethod() == HTTPNames::POST)
+    if (resource_request.HttpMethod() == http_names::kPOST)
       return WebFrameLoadType::kStandard;
     if (!origin_document)
       return WebFrameLoadType::kReload;
@@ -1419,7 +1419,7 @@
   // We don't do this if we are submitting a form with method other than "GET",
   // explicitly reloading, currently displaying a frameset, or if the URL does
   // not have a fragment.
-  return DeprecatedEqualIgnoringCase(http_method, HTTPNames::GET) &&
+  return DeprecatedEqualIgnoringCase(http_method, http_names::kGET) &&
          !IsReloadLoadType(load_type) &&
          load_type != WebFrameLoadType::kBackForward &&
          url.HasFragmentIdentifier() &&
@@ -1666,7 +1666,7 @@
   if (!RequiredCSP().IsEmpty()) {
     DCHECK(
         ContentSecurityPolicy::IsValidCSPAttr(RequiredCSP().GetString(), ""));
-    resource_request.SetHTTPHeaderField(HTTPNames::Sec_Required_CSP,
+    resource_request.SetHTTPHeaderField(http_names::kSecRequiredCSP,
                                         RequiredCSP());
   }
 
@@ -1676,12 +1676,12 @@
   if (resource_request.GetFrameType() !=
       network::mojom::RequestContextFrameType::kNone) {
     // Early return if the request has already been upgraded.
-    if (!resource_request.HttpHeaderField(HTTPNames::Upgrade_Insecure_Requests)
+    if (!resource_request.HttpHeaderField(http_names::kUpgradeInsecureRequests)
              .IsNull()) {
       return;
     }
 
-    resource_request.SetHTTPHeaderField(HTTPNames::Upgrade_Insecure_Requests,
+    resource_request.SetHTTPHeaderField(http_names::kUpgradeInsecureRequests,
                                         "1");
   }
 
diff --git a/third_party/blink/renderer/core/loader/history_item.cc b/third_party/blink/renderer/core/loader/history_item.cc
index 79521ab..13f2c97 100644
--- a/third_party/blink/renderer/core/loader/history_item.cc
+++ b/third_party/blink/renderer/core/loader/history_item.cc
@@ -170,7 +170,7 @@
   request.SetHTTPReferrer(referrer_);
   request.SetCacheMode(cache_mode);
   if (form_data_) {
-    request.SetHTTPMethod(HTTPNames::POST);
+    request.SetHTTPMethod(http_names::kPOST);
     request.SetHTTPBody(form_data_);
     request.SetHTTPContentType(form_content_type_);
     request.SetHTTPOriginToMatchReferrerIfNeeded();
diff --git a/third_party/blink/renderer/core/loader/http_equiv.cc b/third_party/blink/renderer/core/loader/http_equiv.cc
index f78e8ca..798c6c7f 100644
--- a/third_party/blink/renderer/core/loader/http_equiv.cc
+++ b/third_party/blink/renderer/core/loader/http_equiv.cc
@@ -108,9 +108,9 @@
         kSecurityMessageSource, kErrorMessageLevel,
         "X-Frame-Options may only be set via an HTTP header sent along with a "
         "document. It may not be set inside <meta>."));
-  } else if (EqualIgnoringASCIICase(equiv, HTTPNames::Accept_CH)) {
+  } else if (EqualIgnoringASCIICase(equiv, http_names::kAcceptCH)) {
     ProcessHttpEquivAcceptCH(document, content);
-  } else if (EqualIgnoringASCIICase(equiv, HTTPNames::Accept_CH_Lifetime)) {
+  } else if (EqualIgnoringASCIICase(equiv, http_names::kAcceptCHLifetime)) {
     ProcessHttpEquivAcceptCHLifetime(document, content);
   } else if (EqualIgnoringASCIICase(equiv, "content-security-policy") ||
              EqualIgnoringASCIICase(equiv,
@@ -119,7 +119,7 @@
       ProcessHttpEquivContentSecurityPolicy(document, equiv, content);
     else
       document.GetContentSecurityPolicy()->ReportMetaOutsideHead(content);
-  } else if (EqualIgnoringASCIICase(equiv, HTTPNames::Origin_Trial)) {
+  } else if (EqualIgnoringASCIICase(equiv, http_names::kOriginTrial)) {
     if (in_document_head_element)
       OriginTrialContext::FromOrCreate(&document)->AddToken(content);
   }
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index 4dad4301..52aac06 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -489,7 +489,7 @@
     bool page_is_being_dismissed =
         document.PageDismissalEventBeingDispatched() != Document::kNoDismissal;
     if (page_is_being_dismissed) {
-      resource_request.SetHTTPHeaderField(HTTPNames::Cache_Control,
+      resource_request.SetHTTPHeaderField(http_names::kCacheControl,
                                           "max-age=0");
       resource_request.SetKeepalive(true);
       resource_request.SetRequestContext(mojom::RequestContextType::PING);
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
index 092915a99..6fa7b584 100644
--- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -82,7 +82,7 @@
     // Step 13.5. "Set worker global scope's referrer policy to the result of
     // parsing the `Referrer-Policy` header of response." [spec text]
     const String referrer_policy_header =
-        resource->GetResponse().HttpHeaderField(HTTPNames::Referrer_Policy);
+        resource->GetResponse().HttpHeaderField(http_names::kReferrerPolicy);
     if (!referrer_policy_header.IsNull()) {
       ReferrerPolicy referrer_policy = kReferrerPolicyDefault;
       SecurityPolicy::ReferrerPolicyFromHeaderValue(
diff --git a/third_party/blink/renderer/core/loader/ping_loader.cc b/third_party/blink/renderer/core/loader/ping_loader.cc
index 44f1c271..ea0cace 100644
--- a/third_party/blink/renderer/core/loader/ping_loader.cc
+++ b/third_party/blink/renderer/core/loader/ping_loader.cc
@@ -185,7 +185,7 @@
   }
 
   ResourceRequest request(url);
-  request.SetHTTPMethod(HTTPNames::POST);
+  request.SetHTTPMethod(http_names::kPOST);
   request.SetKeepalive(true);
   request.SetRequestContext(mojom::RequestContextType::BEACON);
   beacon.Serialize(request);
@@ -214,18 +214,18 @@
     return;
 
   ResourceRequest request(ping_url);
-  request.SetHTTPMethod(HTTPNames::POST);
+  request.SetHTTPMethod(http_names::kPOST);
   request.SetHTTPContentType("text/ping");
   request.SetHTTPBody(EncodedFormData::Create("PING"));
-  request.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=0");
-  request.SetHTTPHeaderField(HTTPNames::Ping_To,
+  request.SetHTTPHeaderField(http_names::kCacheControl, "max-age=0");
+  request.SetHTTPHeaderField(http_names::kPingTo,
                              AtomicString(destination_url.GetString()));
   scoped_refptr<const SecurityOrigin> ping_origin =
       SecurityOrigin::Create(ping_url);
   if (ProtocolIs(frame->GetDocument()->Url().GetString(), "http") ||
       frame->GetDocument()->GetSecurityOrigin()->CanAccess(ping_origin.get())) {
     request.SetHTTPHeaderField(
-        HTTPNames::Ping_From,
+        http_names::kPingFrom,
         AtomicString(frame->GetDocument()->Url().GetString()));
   }
 
@@ -247,7 +247,7 @@
                                      scoped_refptr<EncodedFormData> report,
                                      ViolationReportType type) {
   ResourceRequest request(report_url);
-  request.SetHTTPMethod(HTTPNames::POST);
+  request.SetHTTPMethod(http_names::kPOST);
   switch (type) {
     case kContentSecurityPolicyViolationReport:
       request.SetHTTPContentType("application/csp-report");
diff --git a/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc b/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
index 6b838b0..f1529322 100644
--- a/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
@@ -95,7 +95,7 @@
 ReferrerPolicy CSSStyleSheetResource::GetReferrerPolicy() const {
   ReferrerPolicy referrer_policy = kReferrerPolicyDefault;
   String referrer_policy_header =
-      GetResponse().HttpHeaderField(HTTPNames::Referrer_Policy);
+      GetResponse().HttpHeaderField(http_names::kReferrerPolicy);
   if (!referrer_policy_header.IsNull()) {
     SecurityPolicy::ReferrerPolicyFromHeaderValue(
         referrer_policy_header, kDoNotSupportReferrerPolicyLegacyKeywords,
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
index 66fe55ab..15bc2b81 100644
--- a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
@@ -41,7 +41,7 @@
   KURL url("http://127.0.0.1:8000/font.woff");
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::ETag, "1234567890");
+  response.SetHTTPHeaderField(http_names::kETag, "1234567890");
   Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
       url, WrappedResourceResponse(response), "");
 
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
index 782a748..0c2485a9 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -293,7 +293,7 @@
 
 scoped_refptr<Image> ImageResourceContent::CreateImage(bool is_multipart) {
   String content_dpr_value =
-      info_->GetResponse().HttpHeaderField(HTTPNames::Content_DPR);
+      info_->GetResponse().HttpHeaderField(http_names::kContentDPR);
   size_t comma = content_dpr_value.ReverseFind(',');
   if (comma != kNotFound && comma < content_dpr_value.length() - 1) {
     content_dpr_value = content_dpr_value.Substring(comma + 1);
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
index 78bb9a0c..df780224 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
@@ -1412,7 +1412,7 @@
   KURL test_url(kTestURL);
   ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
   ResourceRequest resource_request(test_url);
-  resource_request.SetHTTPMethod(HTTPNames::POST);
+  resource_request.SetHTTPMethod(http_names::kPOST);
   FetchParameters params(resource_request);
   params.SetAllowImagePlaceholder();
   ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
diff --git a/third_party/blink/renderer/core/loader/threadable_loader.cc b/third_party/blink/renderer/core/loader/threadable_loader.cc
index 1a42723..75f79df4 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -156,9 +156,9 @@
 
   std::unique_ptr<ResourceRequest> preflight_request =
       std::make_unique<ResourceRequest>(request_url);
-  preflight_request->SetHTTPMethod(HTTPNames::OPTIONS);
-  preflight_request->SetHTTPHeaderField(
-      HTTPNames::Access_Control_Request_Method, request.HttpMethod());
+  preflight_request->SetHTTPMethod(http_names::kOPTIONS);
+  preflight_request->SetHTTPHeaderField(http_names::kAccessControlRequestMethod,
+                                        request.HttpMethod());
   preflight_request->SetPriority(request.Priority());
   preflight_request->SetRequestContext(request.GetRequestContext());
   preflight_request->SetFetchCredentialsMode(
@@ -169,14 +169,14 @@
 
   if (request.IsExternalRequest()) {
     preflight_request->SetHTTPHeaderField(
-        HTTPNames::Access_Control_Request_External, "true");
+        http_names::kAccessControlRequestExternal, "true");
   }
 
   const AtomicString request_headers =
       CreateAccessControlRequestHeadersHeader(request.HttpHeaderFields());
   if (request_headers != g_null_atom) {
     preflight_request->SetHTTPHeaderField(
-        HTTPNames::Access_Control_Request_Headers, request_headers);
+        http_names::kAccessControlRequestHeaders, request_headers);
   }
 
   if (origin)
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 76b7913e..1bf58050 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -319,7 +319,7 @@
     return;
 
   if (save_data_enabled_)
-    request.SetHTTPHeaderField(HTTPNames::Save_Data, "on");
+    request.SetHTTPHeaderField(http_names::kSaveData, "on");
 }
 
 void WorkerFetchContext::DispatchWillSendRequest(
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc
index 31fb702..2b167c9c 100644
--- a/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/third_party/blink/renderer/core/messaging/message_port.cc
@@ -246,7 +246,7 @@
   // https://html.spec.whatwg.org/multipage/comms.html#message-ports
   // |ports| should be an empty array, not null even when there is no ports.
   wtf_size_t count = SafeCast<wtf_size_t>(channels.size());
-  MessagePortArray* port_array = new MessagePortArray(count);
+  MessagePortArray* port_array = MakeGarbageCollected<MessagePortArray>(count);
   for (wtf_size_t i = 0; i < count; ++i) {
     MessagePort* port = MessagePort::Create(context);
     port->Entangle(std::move(channels[i]));
diff --git a/third_party/blink/renderer/core/paint/block_painter_test.cc b/third_party/blink/renderer/core/paint/block_painter_test.cc
index 4c2b60b..5c1143f 100644
--- a/third_party/blink/renderer/core/paint/block_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/block_painter_test.cc
@@ -4,7 +4,8 @@
 
 #include "third_party/blink/renderer/core/paint/block_painter.h"
 
-#include <gtest/gtest.h>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
@@ -13,6 +14,8 @@
 #include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
 
+using testing::ElementsAre;
+
 namespace blink {
 
 using BlockPainterTest = PaintControllerPaintTest;
@@ -33,59 +36,66 @@
     </div>
   )HTML");
 
-  auto& container = *GetLayoutObjectByElementId("container");
+  auto& container = ToLayoutBlock(*GetLayoutObjectByElementId("container"));
   auto& child = *GetLayoutObjectByElementId("child");
 
   // The scroll hit test should be after the container background but before the
   // scrolled contents.
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(container, kBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(child, kBackgroundType));
-  const auto& paint_chunks =
-      RootPaintController().GetPaintArtifact().PaintChunks();
-  EXPECT_EQ(4u, paint_chunks.size());
-  const auto& root_chunk = RootPaintController().PaintChunks()[0];
-  EXPECT_EQ(GetLayoutView().Layer(), &root_chunk.id.client);
-  const auto& container_chunk = RootPaintController().PaintChunks()[1];
-  EXPECT_EQ(ToLayoutBoxModelObject(container).Layer(),
-            &container_chunk.id.client);
-  // The container's scroll hit test.
-  const auto& scroll_hit_test_chunk = RootPaintController().PaintChunks()[2];
-  EXPECT_EQ(&container, &scroll_hit_test_chunk.id.client);
-  EXPECT_EQ(kScrollHitTestType, scroll_hit_test_chunk.id.type);
-  // The scrolled contents.
-  const auto& contents_chunk = RootPaintController().PaintChunks()[3];
-  EXPECT_EQ(&container, &contents_chunk.id.client);
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&container, kBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&child, kBackgroundType)));
+
+  const auto& paint_chunks = RootPaintController().PaintChunks();
+  EXPECT_THAT(
+      paint_chunks,
+      ElementsAre(
+          IsPaintChunk(
+              0, 1,
+              PaintChunk::Id(*GetLayoutView().Layer(),
+                             DisplayItem::kLayerChunkBackground),
+              GetLayoutView().FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(1, 2,
+                       PaintChunk::Id(*container.Layer(),
+                                      kNonScrollingBackgroundChunkType),
+                       container.FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(2, 3, PaintChunk::Id(container, kScrollHitTestType),
+                       container.FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(
+              3, 4,
+              PaintChunk::Id(container, kScrollingContentsBackgroundChunkType),
+              container.FirstFragment().ContentsProperties())));
 
   // The document should not scroll so there should be no scroll offset
   // transform.
-  auto* root_transform = root_chunk.properties.Transform();
+  const auto* root_transform = paint_chunks[0].properties.Transform();
   EXPECT_EQ(nullptr, root_transform->ScrollNode());
 
   // The container's background chunk should not scroll and therefore should use
   // the root transform. Its local transform is actually a paint offset
   // transform.
-  auto* container_transform = container_chunk.properties.Transform()->Parent();
-  EXPECT_EQ(root_transform, container_transform);
+  const auto* container_transform = paint_chunks[1].properties.Transform();
+  EXPECT_EQ(root_transform, container_transform->Parent());
   EXPECT_EQ(nullptr, container_transform->ScrollNode());
 
   // The scroll hit test should not be scrolled and should not be clipped.
   // Its local transform is actually a paint offset transform.
-  auto* scroll_hit_test_transform =
-      scroll_hit_test_chunk.properties.Transform()->Parent();
+  const auto& scroll_hit_test_chunk = paint_chunks[2];
+  const auto* scroll_hit_test_transform =
+      scroll_hit_test_chunk.properties.Transform();
   EXPECT_EQ(nullptr, scroll_hit_test_transform->ScrollNode());
-  EXPECT_EQ(root_transform, scroll_hit_test_transform);
-  auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
+  EXPECT_EQ(root_transform, scroll_hit_test_transform->Parent());
+  const auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
   EXPECT_EQ(FloatRect(0, 0, 800, 600), scroll_hit_test_clip->ClipRect().Rect());
 
   // The scrolled contents should be scrolled and clipped.
-  auto* contents_transform = contents_chunk.properties.Transform();
-  auto* contents_scroll = contents_transform->ScrollNode();
+  const auto& contents_chunk = RootPaintController().PaintChunks()[3];
+  const auto* contents_transform = contents_chunk.properties.Transform();
+  const auto* contents_scroll = contents_transform->ScrollNode();
   EXPECT_EQ(IntSize(200, 300), contents_scroll->ContentsSize());
   EXPECT_EQ(IntRect(0, 0, 200, 200), contents_scroll->ContainerRect());
-  auto* contents_clip = contents_chunk.properties.Clip();
+  const auto* contents_clip = contents_chunk.properties.Clip();
   EXPECT_EQ(FloatRect(0, 0, 200, 200), contents_clip->ClipRect().Rect());
 
   // The scroll hit test display item maintains a reference to a scroll offset
@@ -108,42 +118,50 @@
     <div id='child'></div>
   )HTML");
 
-  auto& html = *GetDocument().documentElement()->GetLayoutObject();
+  auto& html =
+      ToLayoutBlock(*GetDocument().documentElement()->GetLayoutObject());
   auto& child = *GetLayoutObjectByElementId("child");
 
   // The scroll hit test should be after the document background but before the
   // scrolled contents.
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(GetLayoutView(), kScrollHitTestType),
-                      TestDisplayItem(child, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&GetLayoutView(), kScrollHitTestType),
+                          IsSameId(&child, kBackgroundType)));
 
-  const auto& paint_chunks =
-      RootPaintController().GetPaintArtifact().PaintChunks();
-  EXPECT_EQ(3u, paint_chunks.size());
-  const auto& root_chunk = RootPaintController().PaintChunks()[0];
-  EXPECT_EQ(GetLayoutView().Layer(), &root_chunk.id.client);
-  const auto& scroll_hit_test_chunk = RootPaintController().PaintChunks()[1];
-  EXPECT_EQ(&GetLayoutView(), &scroll_hit_test_chunk.id.client);
-  EXPECT_EQ(kScrollHitTestType, scroll_hit_test_chunk.id.type);
-  // The scrolled contents.
-  const auto& contents_chunk = RootPaintController().PaintChunks()[2];
-  EXPECT_EQ(ToLayoutBoxModelObject(html).Layer(), &contents_chunk.id.client);
+  const auto& paint_chunks = RootPaintController().PaintChunks();
+  EXPECT_THAT(
+      paint_chunks,
+      ElementsAre(
+          IsPaintChunk(
+              0, 1,
+              PaintChunk::Id(*GetLayoutView().Layer(),
+                             DisplayItem::kLayerChunkBackground),
+              GetLayoutView().FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(
+              1, 2, PaintChunk::Id(GetLayoutView(), kScrollHitTestType),
+              GetLayoutView().FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(2, 3,
+                       PaintChunk::Id(*html.Layer(),
+                                      kNonScrollingContentsBackgroundChunkType),
+                       html.FirstFragment().ContentsProperties())));
 
   // The scroll hit test should not be scrolled and should not be clipped.
-  auto* scroll_hit_test_transform =
+  const auto& scroll_hit_test_chunk = RootPaintController().PaintChunks()[1];
+  const auto* scroll_hit_test_transform =
       scroll_hit_test_chunk.properties.Transform();
   EXPECT_EQ(nullptr, scroll_hit_test_transform->ScrollNode());
-  auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
+  const auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
   EXPECT_EQ(FloatRect(LayoutRect::InfiniteIntRect()),
             scroll_hit_test_clip->ClipRect().Rect());
 
   // The scrolled contents should be scrolled and clipped.
-  auto* contents_transform = contents_chunk.properties.Transform();
-  auto* contents_scroll = contents_transform->ScrollNode();
+  const auto& contents_chunk = RootPaintController().PaintChunks()[2];
+  const auto* contents_transform = contents_chunk.properties.Transform();
+  const auto* contents_scroll = contents_transform->ScrollNode();
   EXPECT_EQ(IntSize(800, 2000), contents_scroll->ContentsSize());
   EXPECT_EQ(IntRect(0, 0, 800, 600), contents_scroll->ContainerRect());
-  auto* contents_clip = contents_chunk.properties.Clip();
+  const auto* contents_clip = contents_chunk.properties.Clip();
   EXPECT_EQ(FloatRect(0, 0, 800, 600), contents_clip->ClipRect().Rect());
 
   // The scroll hit test display item maintains a reference to a scroll offset
@@ -185,9 +203,9 @@
   // Initially there should be no hit test display items because there is no
   // touch action.
   const auto& scrolling_client = ViewScrollingBackgroundClient();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 1,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
 
   // Add a touch action to parent and ensure that hit test display items are
   // created for both the parent and the visible child.
@@ -196,19 +214,18 @@
   GetDocument().View()->UpdateAllLifecyclePhases();
   auto* parent = GetLayoutObjectByElementId("parent");
   auto* childVisible = GetLayoutObjectByElementId("childVisible");
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*parent, DisplayItem::kHitTest),
-      TestDisplayItem(*childVisible, DisplayItem::kHitTest));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(parent, DisplayItem::kHitTest),
+                          IsSameId(childVisible, DisplayItem::kHitTest)));
 
   // Remove the touch action from parent and ensure no hit test display items
   // are left.
   parent_element->removeAttribute(html_names::kClassAttr);
   GetDocument().View()->UpdateAllLifecyclePhases();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 1,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
 }
 
 TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintCaching) {
@@ -231,31 +248,32 @@
   )HTML");
 
   const auto& scrolling_client = ViewScrollingBackgroundClient();
-  auto* touchaction_element = GetElementById("touchaction");
-  auto* touchaction = touchaction_element->GetLayoutObject();
+  const auto* touchaction = GetLayoutObjectByElementId("touchaction");
   auto* sibling_element = GetElementById("sibling");
-  auto* sibling = sibling_element->GetLayoutObject();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*touchaction, DisplayItem::kHitTest),
-      TestDisplayItem(*sibling, kBackgroundType));
+  const auto* sibling = sibling_element->GetLayoutObject();
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(touchaction, DisplayItem::kHitTest),
+                          IsSameId(sibling, kBackgroundType)));
 
-  {
-    const auto& paint_chunks =
-        RootPaintController().GetPaintArtifact().PaintChunks();
-    EXPECT_EQ(paint_chunks.size(), 2u);
-    auto& background_chunk = paint_chunks[0];
-    EXPECT_EQ(nullptr, background_chunk.GetHitTestData());
-    auto& hit_test_chunk = paint_chunks[1];
-    DCHECK(hit_test_chunk.GetHitTestData());
-    EXPECT_EQ(1u, hit_test_chunk.GetHitTestData()->touch_action_rects.size());
-    auto& touch_action_rect =
-        hit_test_chunk.GetHitTestData()->touch_action_rects[0];
-    EXPECT_EQ(LayoutRect(0, 0, 100, 100), touch_action_rect.rect);
-    EXPECT_EQ(TouchAction::kTouchActionNone,
-              touch_action_rect.whitelisted_touch_action);
-  }
+  PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType);
+  auto root_chunk_properties =
+      GetLayoutView().FirstFragment().ContentsProperties();
+
+  PaintChunk::Id hit_test_chunk_id(*touchaction->EnclosingLayer(),
+                                   kNonScrollingBackgroundChunkType);
+  auto hit_test_chunk_properties = touchaction->EnclosingLayer()
+                                       ->GetLayoutObject()
+                                       .FirstFragment()
+                                       .ContentsProperties();
+  HitTestData hit_test_data;
+  hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 100));
+
+  EXPECT_THAT(
+      RootPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+                  IsPaintChunk(1, 3, hit_test_chunk_id,
+                               hit_test_chunk_properties, hit_test_data)));
 
   sibling_element->setAttribute(html_names::kStyleAttr, "background: green;");
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
@@ -264,21 +282,11 @@
   EXPECT_EQ(2, NumCachedNewItems());
   CommitAndFinishCycle();
 
-  {
-    const auto& paint_chunks =
-        RootPaintController().GetPaintArtifact().PaintChunks();
-    EXPECT_EQ(paint_chunks.size(), 2u);
-    auto& background_chunk = paint_chunks[0];
-    EXPECT_EQ(nullptr, background_chunk.GetHitTestData());
-    auto& hit_test_chunk = paint_chunks[1];
-    DCHECK(hit_test_chunk.GetHitTestData());
-    EXPECT_EQ(1u, hit_test_chunk.GetHitTestData()->touch_action_rects.size());
-    auto& touch_action_rect =
-        hit_test_chunk.GetHitTestData()->touch_action_rects[0];
-    EXPECT_EQ(LayoutRect(0, 0, 100, 100), touch_action_rect.rect);
-    EXPECT_EQ(TouchAction::kTouchActionNone,
-              touch_action_rect.whitelisted_touch_action);
-  }
+  EXPECT_THAT(
+      RootPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+                  IsPaintChunk(1, 3, hit_test_chunk_id,
+                               hit_test_chunk_properties, hit_test_data)));
 }
 
 TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectScrollingContents) {
@@ -317,15 +325,15 @@
                                         ->Layer()
                                         ->GraphicsLayerBacking()
                                         ->GetPaintController();
-  EXPECT_DISPLAY_LIST(
-      scroller_paint_controller.GetDisplayItemList(), 3,
-      TestDisplayItem(scroller->GetScrollableArea()
-                          ->GetScrollingBackgroundDisplayItemClient(),
-                      kBackgroundType),
-      TestDisplayItem(*scroller, DisplayItem::kHitTest),
-      TestDisplayItem(*child, DisplayItem::kHitTest));
-  EXPECT_DISPLAY_LIST(non_scroller_paint_controller.GetDisplayItemList(), 1,
-                      TestDisplayItem(root_client, kDocumentBackgroundType));
+  EXPECT_THAT(
+      scroller_paint_controller.GetDisplayItemList(),
+      ElementsAre(IsSameId(&scroller->GetScrollableArea()
+                                ->GetScrollingBackgroundDisplayItemClient(),
+                           kBackgroundType),
+                  IsSameId(scroller, DisplayItem::kHitTest),
+                  IsSameId(child, DisplayItem::kHitTest)));
+  EXPECT_THAT(non_scroller_paint_controller.GetDisplayItemList(),
+              ElementsAre(IsSameId(&root_client, kDocumentBackgroundType)));
 
   {
     const auto& paint_chunks =
@@ -373,52 +381,48 @@
   const auto& scrolling_client = ViewScrollingBackgroundClient();
   auto* touchaction_element = GetElementById("touchaction");
   auto* touchaction = touchaction_element->GetLayoutObject();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 1,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
 
-  {
-    const auto& paint_chunks =
-        RootPaintController().GetPaintArtifact().PaintChunks();
-    EXPECT_EQ(paint_chunks.size(), 1u);
-    EXPECT_EQ(nullptr, paint_chunks[0].GetHitTestData());
-  }
+  PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType);
+  auto root_chunk_properties =
+      GetLayoutView().FirstFragment().ContentsProperties();
+
+  EXPECT_THAT(
+      RootPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties)));
 
   touchaction_element->setAttribute(html_names::kStyleAttr,
                                     "touch-action: none;");
   GetDocument().View()->UpdateAllLifecyclePhases();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*touchaction, DisplayItem::kHitTest));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(touchaction, DisplayItem::kHitTest)));
 
-  {
-    const auto& paint_chunks =
-        RootPaintController().GetPaintArtifact().PaintChunks();
-    EXPECT_EQ(paint_chunks.size(), 2u);
-    auto& background_chunk = paint_chunks[0];
-    EXPECT_EQ(nullptr, background_chunk.GetHitTestData());
-    auto& hit_test_chunk = paint_chunks[1];
-    DCHECK(hit_test_chunk.GetHitTestData());
-    EXPECT_EQ(1u, hit_test_chunk.GetHitTestData()->touch_action_rects.size());
-    auto& touch_action_rect =
-        hit_test_chunk.GetHitTestData()->touch_action_rects[0];
-    EXPECT_EQ(LayoutRect(0, 0, 100, 100), touch_action_rect.rect);
-    EXPECT_EQ(TouchAction::kTouchActionNone,
-              touch_action_rect.whitelisted_touch_action);
-  }
+  PaintChunk::Id hit_test_chunk_id(*touchaction->EnclosingLayer(),
+                                   kNonScrollingBackgroundChunkType);
+  auto hit_test_chunk_properties = touchaction->EnclosingLayer()
+                                       ->GetLayoutObject()
+                                       .FirstFragment()
+                                       .ContentsProperties();
+  HitTestData hit_test_data;
+  hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 100));
+
+  EXPECT_THAT(
+      RootPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+                  IsPaintChunk(1, 2, hit_test_chunk_id,
+                               hit_test_chunk_properties, hit_test_data)));
 
   touchaction_element->removeAttribute(html_names::kStyleAttr);
   GetDocument().View()->UpdateAllLifecyclePhases();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 1,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType));
-  {
-    const auto& paint_chunks =
-        RootPaintController().GetPaintArtifact().PaintChunks();
-    EXPECT_EQ(paint_chunks.size(), 1u);
-    EXPECT_EQ(nullptr, paint_chunks[0].GetHitTestData());
-  }
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
+  EXPECT_THAT(
+      RootPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties)));
 }
 
 namespace {
@@ -450,9 +454,9 @@
   // Initially there should be no hit test display items because there are no
   // event handlers.
   const auto& scrolling_client = ViewScrollingBackgroundClient();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 1,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
 
   // Add an event listener to parent and ensure that hit test display items are
   // created for both the parent and child.
@@ -462,19 +466,18 @@
   GetDocument().View()->UpdateAllLifecyclePhases();
   auto* parent = GetLayoutObjectByElementId("parent");
   auto* child = GetLayoutObjectByElementId("child");
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*parent, DisplayItem::kHitTest),
-      TestDisplayItem(*child, DisplayItem::kHitTest));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(parent, DisplayItem::kHitTest),
+                          IsSameId(child, DisplayItem::kHitTest)));
 
   // Remove the event handler from parent and ensure no hit test display items
   // are left.
   parent_element->RemoveAllEventListeners();
   GetDocument().View()->UpdateAllLifecyclePhases();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 1,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
 }
 
 TEST_F(BlockPainterTestWithPaintTouchAction,
@@ -494,21 +497,19 @@
   const auto& scrolling_client = ViewScrollingBackgroundClient();
   auto* parent = GetLayoutObjectByElementId("parent");
   auto* child = GetLayoutObjectByElementId("child");
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*parent, DisplayItem::kHitTest),
-      TestDisplayItem(*child, DisplayItem::kHitTest));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(parent, DisplayItem::kHitTest),
+                          IsSameId(child, DisplayItem::kHitTest)));
 
   auto* child_element = GetElementById("parent");
   child_element->setAttribute("style", "background: blue;");
   GetDocument().View()->UpdateAllLifecyclePhases();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 4,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*parent, kBackgroundType),
-      TestDisplayItem(*parent, DisplayItem::kHitTest),
-      TestDisplayItem(*child, DisplayItem::kHitTest));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(parent, kBackgroundType),
+                          IsSameId(parent, DisplayItem::kHitTest),
+                          IsSameId(child, DisplayItem::kHitTest)));
 }
 
 TEST_F(BlockPainterTestWithPaintTouchAction, ScrolledHitTestChunkProperties) {
@@ -534,27 +535,44 @@
   )HTML");
 
   const auto& scrolling_client = ViewScrollingBackgroundClient();
-  auto* scroller = GetLayoutObjectByElementId("scroller");
-  auto* child = GetLayoutObjectByElementId("child");
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(scrolling_client, kDocumentBackgroundType),
-      TestDisplayItem(*scroller, DisplayItem::kHitTest),
-      TestDisplayItem(*child, DisplayItem::kHitTest));
+  const auto* scroller = ToLayoutBlock(GetLayoutObjectByElementId("scroller"));
+  const auto* child = GetLayoutObjectByElementId("child");
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+                          IsSameId(scroller, DisplayItem::kHitTest),
+                          IsSameId(child, DisplayItem::kHitTest)));
 
-  const auto& paint_chunks =
-      RootPaintController().GetPaintArtifact().PaintChunks();
-  EXPECT_EQ(3u, paint_chunks.size());
+  HitTestData scroller_hit_test_data;
+  scroller_hit_test_data.touch_action_rects.emplace_back(
+      LayoutRect(0, 0, 100, 100));
+  HitTestData scrolled_hit_test_data;
+  scrolled_hit_test_data.touch_action_rects.emplace_back(
+      LayoutRect(0, 0, 200, 50));
 
-  const auto& scroller_paint_chunk = RootPaintController().PaintChunks()[1];
-  EXPECT_EQ(ToLayoutBoxModelObject(scroller)->Layer(),
-            &scroller_paint_chunk.id.client);
+  const auto& paint_chunks = RootPaintController().PaintChunks();
+  EXPECT_THAT(
+      paint_chunks,
+      ElementsAre(
+          IsPaintChunk(
+              0, 1, PaintChunk::Id(scrolling_client, kDocumentBackgroundType),
+              GetLayoutView().FirstFragment().ContentsProperties()),
+          IsPaintChunk(1, 2,
+                       PaintChunk::Id(*scroller->Layer(),
+                                      kNonScrollingBackgroundChunkType),
+                       scroller->FirstFragment().LocalBorderBoxProperties(),
+                       scroller_hit_test_data),
+          IsPaintChunk(
+              2, 3,
+              PaintChunk::Id(*scroller, kScrollingContentsBackgroundChunkType),
+              scroller->FirstFragment().ContentsProperties(),
+              scrolled_hit_test_data)));
+
+  const auto& scroller_paint_chunk = paint_chunks[1];
   EXPECT_EQ(FloatRect(0, 0, 100, 100), scroller_paint_chunk.bounds);
   // The hit test rect for the scroller itself should not be scrolled.
   EXPECT_FALSE(scroller_paint_chunk.properties.Transform()->ScrollNode());
 
-  const auto& scrolled_paint_chunk = RootPaintController().PaintChunks()[2];
-  EXPECT_EQ(scroller, &scrolled_paint_chunk.id.client);
+  const auto& scrolled_paint_chunk = paint_chunks[2];
   EXPECT_EQ(FloatRect(0, 0, 200, 50), scrolled_paint_chunk.bounds);
   // The hit test rect for the scrolled contents should be scrolled.
   EXPECT_TRUE(scrolled_paint_chunk.properties.Transform()->ScrollNode());
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc
index 5d683de..8bbcb7b 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc
@@ -19,6 +19,8 @@
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
+using testing::ElementsAre;
+
 namespace blink {
 
 class NGTextFragmentPainterTest : public PaintControllerPaintTest,
@@ -54,10 +56,10 @@
   EXPECT_EQ(1u, line_box_fragment.Children().size());
   const NGPaintFragment& text_fragment = *line_box_fragment.FirstChild();
 
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(ViewScrollingBackgroundClient(),
-                                      DisplayItem::kDocumentBackground),
-                      TestDisplayItem(text_fragment, kForegroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   DisplayItem::kDocumentBackground),
+                          IsSameId(&text_fragment, kForegroundType)));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
index b2cc0f5..0abe628 100644
--- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
@@ -15,6 +15,8 @@
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 
+using testing::ElementsAre;
+
 namespace blink {
 
 INSTANTIATE_PAINT_TEST_CASE_P(PaintControllerPaintTest);
@@ -30,20 +32,21 @@
   Element& div = *ToElement(GetDocument().body()->firstChild());
   InlineTextBox& text_inline_box =
       *ToLayoutText(div.firstChild()->GetLayoutObject())->FirstTextBox();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-      TestDisplayItem(text_inline_box, kForegroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType),
+                          IsSameId(&text_inline_box, kForegroundType)));
 
   div.focus();
   GetDocument().View()->UpdateAllLifecyclePhases();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-      TestDisplayItem(text_inline_box, kForegroundType),
-      TestDisplayItem(CaretDisplayItemClientForTesting(),
-                      DisplayItem::kCaret));  // New!
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(
+          IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+          IsSameId(&text_inline_box, kForegroundType),
+          // New!
+          IsSameId(&CaretDisplayItemClientForTesting(), DisplayItem::kCaret)));
 }
 
 TEST_P(PaintControllerPaintTest, InlineRelayout) {
@@ -56,10 +59,10 @@
   LayoutText& text = *ToLayoutText(div_block.FirstChild());
   InlineTextBox& first_text_box = *text.FirstTextBox();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-      TestDisplayItem(first_text_box, kForegroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType),
+                          IsSameId(&first_text_box, kForegroundType)));
 
   div.setAttribute(html_names::kStyleAttr, "width: 10px; height: 200px");
   GetDocument().View()->UpdateAllLifecyclePhases();
@@ -69,11 +72,11 @@
   InlineTextBox& second_text_box =
       *new_text.FirstTextBox()->NextForSameLayoutObject();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-      TestDisplayItem(new_first_text_box, kForegroundType),
-      TestDisplayItem(second_text_box, kForegroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType),
+                          IsSameId(&new_first_text_box, kForegroundType),
+                          IsSameId(&second_text_box, kForegroundType)));
 }
 
 TEST_P(PaintControllerPaintTest, ChunkIdClientCacheFlag) {
@@ -89,11 +92,11 @@
   LayoutObject& sub_div = *div.FirstChild();
   LayoutObject& sub_div2 = *sub_div.NextSibling();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-      TestDisplayItem(sub_div, kBackgroundType),
-      TestDisplayItem(sub_div2, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType),
+                          IsSameId(&sub_div, kBackgroundType),
+                          IsSameId(&sub_div2, kBackgroundType)));
 
   // Verify that the background does not scroll.
   const PaintChunk& background_chunk = RootPaintController().PaintChunks()[0];
@@ -131,10 +134,10 @@
   LayoutBlock& div = *ToLayoutBlock(GetLayoutObjectByElementId("div"));
   LayoutObject& sub_div = *div.FirstChild();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(ViewScrollingBackgroundClient(), kDocumentBackgroundType),
-      TestDisplayItem(sub_div, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType),
+                          IsSameId(&sub_div, kBackgroundType)));
 }
 
 TEST_P(PaintControllerPaintTestForSPv2, FrameScrollingContents) {
@@ -155,10 +158,10 @@
 
   // TODO(crbug.com/792577): Cull rect for frame scrolling contents is too
   // small?
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(GetLayoutView(), kScrollHitTestType),
-                      TestDisplayItem(div1, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&GetLayoutView(), kScrollHitTestType),
+                          IsSameId(&div1, kBackgroundType)));
 
   GetDocument().View()->LayoutViewport()->SetScrollOffset(
       ScrollOffset(5000, 5000), kProgrammaticScroll);
@@ -166,9 +169,9 @@
 
   // TODO(crbug.com/792577): Cull rect for frame scrolling contents is too
   // small?
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(GetLayoutView(), kScrollHitTestType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&GetLayoutView(), kScrollHitTestType)));
 }
 
 TEST_P(PaintControllerPaintTestForSPv2, BlockScrollingNonLayeredContents) {
@@ -195,23 +198,23 @@
   auto& div4 = *GetLayoutObjectByElementId("div4");
 
   // Initial cull rect: (0,0 4200x4200)
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(div1, kBackgroundType),
-                      TestDisplayItem(div2, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&div1, kBackgroundType),
+                          IsSameId(&div2, kBackgroundType)));
 
   container.GetScrollableArea()->SetScrollOffset(ScrollOffset(5000, 5000),
                                                  kProgrammaticScroll);
   GetDocument().View()->UpdateAllLifecyclePhases();
 
   // Cull rect after scroll: (1000,1000 8100x8100)
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 5,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(div2, kBackgroundType),
-                      TestDisplayItem(div3, kBackgroundType),
-                      TestDisplayItem(div4, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&div2, kBackgroundType),
+                          IsSameId(&div3, kBackgroundType),
+                          IsSameId(&div4, kBackgroundType)));
 }
 
 TEST_P(PaintControllerPaintTestForSPv2, ScrollHitTestOrder) {
@@ -236,12 +239,12 @@
   // The container's items should all be after the document's scroll hit test
   // to ensure the container is hit before the document. Similarly, the child's
   // items should all be after the container's scroll hit test.
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 5,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(GetLayoutView(), kScrollHitTestType),
-                      TestDisplayItem(container, kBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(child, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&GetLayoutView(), kScrollHitTestType),
+                          IsSameId(&container, kBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&child, kBackgroundType)));
 }
 
 TEST_P(PaintControllerPaintTestForSPv2, NonStackingScrollHitTestOrder) {
@@ -276,13 +279,13 @@
   // testing should hit positive descendants, the container, and then negative
   // descendants so the ScrollHitTest item should be immediately after the
   // background.
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(neg_z_child, kBackgroundType),
-                      TestDisplayItem(container, kBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(child, kBackgroundType),
-                      TestDisplayItem(pos_z_child, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&neg_z_child, kBackgroundType),
+                          IsSameId(&container, kBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&child, kBackgroundType),
+                          IsSameId(&pos_z_child, kBackgroundType)));
 }
 
 TEST_P(PaintControllerPaintTestForSPv2, StackingScrollHitTestOrder) {
@@ -315,13 +318,13 @@
   // Both positive and negative z-index descendants are painted after the
   // background. The scroll hit test should be after the background but before
   // the z-index descendants to ensure hit test order is correct.
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(container, kBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(neg_z_child, kBackgroundType),
-                      TestDisplayItem(child, kBackgroundType),
-                      TestDisplayItem(pos_z_child, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&container, kBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&neg_z_child, kBackgroundType),
+                          IsSameId(&child, kBackgroundType),
+                          IsSameId(&pos_z_child, kBackgroundType)));
 }
 
 TEST_P(PaintControllerPaintTestForSPv2,
@@ -353,12 +356,12 @@
 
   // Even though container does not paint a background, the scroll hit test item
   // should still be between the negative z-index child and the regular child.
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 5,
-                      TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
-                      TestDisplayItem(neg_z_child, kBackgroundType),
-                      TestDisplayItem(container, kScrollHitTestType),
-                      TestDisplayItem(child, kBackgroundType),
-                      TestDisplayItem(pos_z_child, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+                          IsSameId(&neg_z_child, kBackgroundType),
+                          IsSameId(&container, kScrollHitTestType),
+                          IsSameId(&child, kBackgroundType),
+                          IsSameId(&pos_z_child, kBackgroundType)));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
index a3a732c2..efe02959 100644
--- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
+++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
@@ -129,6 +129,18 @@
       : PaintControllerPaintTestBase(local_frame_client) {}
 };
 
+// Shorter names for frequently used display item types in core/ tests.
+const DisplayItem::Type kNonScrollingBackgroundChunkType =
+    DisplayItem::PaintPhaseToDrawingType(PaintPhase::kSelfBlockBackgroundOnly);
+const DisplayItem::Type kScrollingBackgroundChunkType =
+    DisplayItem::PaintPhaseToClipType(PaintPhase::kSelfBlockBackgroundOnly);
+const DisplayItem::Type kNonScrollingContentsBackgroundChunkType =
+    DisplayItem::PaintPhaseToDrawingType(
+        PaintPhase::kDescendantBlockBackgroundsOnly);
+const DisplayItem::Type kScrollingContentsBackgroundChunkType =
+    DisplayItem::PaintPhaseToClipType(
+        PaintPhase::kDescendantBlockBackgroundsOnly);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_CONTROLLER_PAINT_TEST_H_
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
index 3e46a1b..74b35e49 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -86,15 +86,15 @@
           ? *GetLayoutView().Layer()
           : view_display_item_client;
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 7,
-      TestDisplayItem(view_display_item_client, kDocumentBackgroundType),
-      TestDisplayItem(container1, kBackgroundType),
-      TestDisplayItem(content1, kBackgroundType),
-      TestDisplayItem(filler1, kBackgroundType),
-      TestDisplayItem(container2, kBackgroundType),
-      TestDisplayItem(content2, kBackgroundType),
-      TestDisplayItem(filler2, kBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&view_display_item_client, kDocumentBackgroundType),
+                  IsSameId(&container1, kBackgroundType),
+                  IsSameId(&content1, kBackgroundType),
+                  IsSameId(&filler1, kBackgroundType),
+                  IsSameId(&container2, kBackgroundType),
+                  IsSameId(&content2, kBackgroundType),
+                  IsSameId(&filler2, kBackgroundType)));
 
   auto* container1_layer = ToLayoutBoxModelObject(container1).Layer();
   auto* filler1_layer = ToLayoutBoxModelObject(filler1).Layer();
@@ -119,37 +119,30 @@
   auto check_chunks = [&]() {
     // Check that new paint chunks were forced for |container1| and
     // |container2|.
-    const auto& paint_chunks =
-        RootPaintController().GetPaintArtifact().PaintChunks();
-    EXPECT_EQ(paint_chunks.size(), 7u);
-    EXPECT_EQ(
-        paint_chunks[0],
-        PaintChunk(0, 1, PaintChunk::Id(view_chunk_client, view_chunk_type),
-                   view_chunk_state));
-    EXPECT_EQ(paint_chunks[1], PaintChunk(1, 2,
-                                          PaintChunk::Id(*container1_layer,
-                                                         chunk_background_type),
-                                          other_chunk_state));
-    EXPECT_EQ(paint_chunks[2], PaintChunk(2, 3,
-                                          PaintChunk::Id(*container1_layer,
-                                                         chunk_foreground_type),
-                                          other_chunk_state));
-    EXPECT_EQ(
-        paint_chunks[3],
-        PaintChunk(3, 4, PaintChunk::Id(*filler1_layer, filler_chunk_type),
-                   other_chunk_state));
-    EXPECT_EQ(paint_chunks[4], PaintChunk(4, 5,
-                                          PaintChunk::Id(*container2_layer,
-                                                         chunk_background_type),
-                                          other_chunk_state));
-    EXPECT_EQ(paint_chunks[5], PaintChunk(5, 6,
-                                          PaintChunk::Id(*container2_layer,
-                                                         chunk_foreground_type),
-                                          other_chunk_state));
-    EXPECT_EQ(
-        paint_chunks[6],
-        PaintChunk(6, 7, PaintChunk::Id(*filler2_layer, filler_chunk_type),
-                   other_chunk_state));
+    EXPECT_THAT(
+        RootPaintController().PaintChunks(),
+        ElementsAre(
+            IsPaintChunk(0, 1,
+                         PaintChunk::Id(view_chunk_client, view_chunk_type),
+                         view_chunk_state),
+            IsPaintChunk(
+                1, 2, PaintChunk::Id(*container1_layer, chunk_background_type),
+                other_chunk_state),
+            IsPaintChunk(
+                2, 3, PaintChunk::Id(*container1_layer, chunk_foreground_type),
+                other_chunk_state),
+            IsPaintChunk(3, 4,
+                         PaintChunk::Id(*filler1_layer, filler_chunk_type),
+                         other_chunk_state),
+            IsPaintChunk(
+                4, 5, PaintChunk::Id(*container2_layer, chunk_background_type),
+                other_chunk_state),
+            IsPaintChunk(
+                5, 6, PaintChunk::Id(*container2_layer, chunk_foreground_type),
+                other_chunk_state),
+            IsPaintChunk(6, 7,
+                         PaintChunk::Id(*filler2_layer, filler_chunk_type),
+                         other_chunk_state)));
   };
 
   check_chunks();
@@ -164,15 +157,15 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 7,
-      TestDisplayItem(view_display_item_client, kDocumentBackgroundType),
-      TestDisplayItem(container1, kBackgroundType),
-      TestDisplayItem(content1, kBackgroundType),
-      TestDisplayItem(filler1, kBackgroundType),
-      TestDisplayItem(container2, kBackgroundType),
-      TestDisplayItem(content2, kBackgroundType),
-      TestDisplayItem(filler2, kBackgroundType));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&view_display_item_client, kDocumentBackgroundType),
+                  IsSameId(&container1, kBackgroundType),
+                  IsSameId(&content1, kBackgroundType),
+                  IsSameId(&filler1, kBackgroundType),
+                  IsSameId(&container2, kBackgroundType),
+                  IsSameId(&content2, kBackgroundType),
+                  IsSameId(&filler2, kBackgroundType)));
 
   // We should still have the paint chunks forced by the cached subsequences.
   check_chunks();
@@ -231,15 +224,15 @@
   // Container2 is partly (including its stacking chidren) in the interest rect;
   // Content2b is out of the interest rect and output nothing;
   // Container3 is partly in the interest rect.
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 7,
-      TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
-      TestDisplayItem(container1, kBackgroundType),
-      TestDisplayItem(content1, kBackgroundType),
-      TestDisplayItem(container2, kBackgroundType),
-      TestDisplayItem(content2a, kBackgroundType),
-      TestDisplayItem(container3, kBackgroundType),
-      TestDisplayItem(content3, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&background_display_item_client,
+                                   kDocumentBackgroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2a, kBackgroundType),
+                          IsSameId(&container3, kBackgroundType),
+                          IsSameId(&content3, kBackgroundType)));
 
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   IntRect new_interest_rect(0, 100, 300, 1000);
@@ -255,14 +248,14 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 6,
-      TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
-      TestDisplayItem(container1, kBackgroundType),
-      TestDisplayItem(content1, kBackgroundType),
-      TestDisplayItem(container2, kBackgroundType),
-      TestDisplayItem(content2a, kBackgroundType),
-      TestDisplayItem(content2b, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&background_display_item_client,
+                                   kDocumentBackgroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2a, kBackgroundType),
+                          IsSameId(&content2b, kBackgroundType)));
 }
 
 TEST_P(PaintLayerPainterTest,
@@ -318,13 +311,13 @@
       *GetDocument().getElementById("content2")->GetLayoutObject();
 
   const auto& background_display_item_client = ViewScrollingBackgroundClient();
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 5,
-      TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
-      TestDisplayItem(container1, kBackgroundType),
-      TestDisplayItem(content1, kBackgroundType),
-      TestDisplayItem(container2, kBackgroundType),
-      TestDisplayItem(content2, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&background_display_item_client,
+                                   kDocumentBackgroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType)));
 
   ToHTMLElement(content1.GetNode())
       ->setAttribute(html_names::kStyleAttr,
@@ -336,13 +329,13 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 5,
-      TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
-      TestDisplayItem(container1, kBackgroundType),
-      TestDisplayItem(content1, kBackgroundType),
-      TestDisplayItem(container2, kBackgroundType),
-      TestDisplayItem(content2, kBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&background_display_item_client,
+                                   kDocumentBackgroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType)));
 }
 
 TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index c5c5713..dae3697 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2539,9 +2539,10 @@
 
 HeapVector<Member<PaintLayerScrollableArea>>&
 PaintLayerScrollableArea::PreventRelayoutScope::NeedsRelayoutList() {
-  DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
-                      needs_relayout_list,
-                      (new HeapVector<Member<PaintLayerScrollableArea>>));
+  DEFINE_STATIC_LOCAL(
+      Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
+      needs_relayout_list,
+      (MakeGarbageCollected<HeapVector<Member<PaintLayerScrollableArea>>>()));
   return *needs_relayout_list;
 }
 
@@ -2578,9 +2579,10 @@
 
 HeapVector<Member<PaintLayerScrollableArea>>&
 PaintLayerScrollableArea::DelayScrollOffsetClampScope::NeedsClampList() {
-  DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
-                      needs_clamp_list,
-                      (new HeapVector<Member<PaintLayerScrollableArea>>));
+  DEFINE_STATIC_LOCAL(
+      Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
+      needs_clamp_list,
+      (MakeGarbageCollected<HeapVector<Member<PaintLayerScrollableArea>>>()));
   return *needs_clamp_list;
 }
 
diff --git a/third_party/blink/renderer/core/paint/table_painter_test.cc b/third_party/blink/renderer/core/paint/table_painter_test.cc
index 698c0c8..200f2ac 100644
--- a/third_party/blink/renderer/core/paint/table_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/table_painter_test.cc
@@ -11,6 +11,8 @@
 // TableRowPainter and TableCellPainter. It's difficult to separate the tests
 // into individual files because of dependencies among the painter classes.
 
+using testing::ElementsAre;
+
 namespace blink {
 
 using TablePainterTest = PaintControllerPaintTest;
@@ -37,21 +39,21 @@
   IntRect interest_rect(0, 0, 200, 200);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row1, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row1, DisplayItem::kBoxDecorationBackground)));
 
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   interest_rect = IntRect(0, 300, 200, 1000);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row2, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row2, DisplayItem::kBoxDecorationBackground)));
 }
 
 TEST_P(TablePainterTest, BackgroundWithCellSpacing) {
@@ -82,35 +84,35 @@
   IntRect interest_rect(0, 200, 200, 150);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row1, DisplayItem::kBoxDecorationBackground),
-      TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row1, DisplayItem::kBoxDecorationBackground),
+                  IsSameId(&cell1, DisplayItem::kBoxDecorationBackground)));
 
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   // Intersects the spacing only.
   interest_rect = IntRect(0, 250, 100, 100);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 2,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row1, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row1, DisplayItem::kBoxDecorationBackground)));
 
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   // Intersects cell2 only.
   interest_rect = IntRect(0, 350, 200, 150);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row2, DisplayItem::kBoxDecorationBackground),
-      TestDisplayItem(cell2, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row2, DisplayItem::kBoxDecorationBackground),
+                  IsSameId(&cell2, DisplayItem::kBoxDecorationBackground)));
 }
 
 TEST_P(TablePainterTest, BackgroundInSelfPaintingRow) {
@@ -138,33 +140,33 @@
   IntRect interest_rect(200, 0, 200, 200);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
-      TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row, DisplayItem::kBoxDecorationBackground),
+                  IsSameId(&cell1, DisplayItem::kBoxDecorationBackground)));
 
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   // Intersects the spacing only.
   interest_rect = IntRect(300, 0, 100, 100);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 1,
-                      TestDisplayItem(ViewScrollingBackgroundClient(),
-                                      DisplayItem::kDocumentBackground));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   DisplayItem::kDocumentBackground)));
 
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   // Intersects cell2 only.
   interest_rect = IntRect(450, 0, 200, 200);
   Paint(&interest_rect);
 
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 3,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
-      TestDisplayItem(cell2, DisplayItem::kBoxDecorationBackground));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&row, DisplayItem::kBoxDecorationBackground),
+                  IsSameId(&cell2, DisplayItem::kBoxDecorationBackground)));
 }
 
 TEST_P(TablePainterTest, CollapsedBorderAndOverflow) {
@@ -189,14 +191,14 @@
   Paint(&interest_rect);
 
   // We should paint all display items of cell.
-  EXPECT_DISPLAY_LIST(
-      RootPaintController().GetDisplayItemList(), 4,
-      TestDisplayItem(ViewScrollingBackgroundClient(),
-                      DisplayItem::kDocumentBackground),
-      TestDisplayItem(cell, DisplayItem::kBoxDecorationBackground),
-      TestDisplayItem(*cell.Row(), DisplayItem::kTableCollapsedBorders),
-      TestDisplayItem(cell, DisplayItem::PaintPhaseToDrawingType(
-                                PaintPhase::kSelfOutlineOnly)));
+  EXPECT_THAT(
+      RootPaintController().GetDisplayItemList(),
+      ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                           DisplayItem::kDocumentBackground),
+                  IsSameId(&cell, DisplayItem::kBoxDecorationBackground),
+                  IsSameId(cell.Row(), DisplayItem::kTableCollapsedBorders),
+                  IsSameId(&cell, DisplayItem::PaintPhaseToDrawingType(
+                                      PaintPhase::kSelfOutlineOnly))));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/theme_painter.cc b/third_party/blink/renderer/core/paint/theme_painter.cc
index 19d69d08..bb8cdb19 100644
--- a/third_party/blink/renderer/core/paint/theme_painter.cc
+++ b/third_party/blink/renderer/core/paint/theme_painter.cc
@@ -68,6 +68,7 @@
 #define COUNT_APPEARANCE(doc, feature) \
   UseCounter::Count(doc, WebFeature::kCSSValueAppearance##feature##Rendered)
 
+// Returns true; Needs CSS painting and/or PaintBorderOnly().
 bool ThemePainter::Paint(const LayoutObject& o,
                          const PaintInfo& paint_info,
                          const IntRect& r) {
@@ -226,6 +227,7 @@
   return true;
 }
 
+// Returns true; Needs CSS border painting.
 bool ThemePainter::PaintBorderOnly(const Node* node,
                                    const ComputedStyle& style,
                                    const PaintInfo& paint_info,
@@ -261,21 +263,30 @@
     case kSearchFieldPart:
     case kListboxPart:
       return true;
-    case kCheckboxPart:
-    case kRadioPart:
-    case kPushButtonPart:
-    case kSquareButtonPart:
     case kButtonPart:
+    case kCheckboxPart:
+    case kInnerSpinButtonPart:
     case kMenulistPart:
-    case kMeterPart:
     case kProgressBarPart:
+    case kPushButtonPart:
+    case kRadioPart:
+    case kSearchFieldCancelButtonPart:
     case kSliderHorizontalPart:
-    case kSliderVerticalPart:
     case kSliderThumbHorizontalPart:
     case kSliderThumbVerticalPart:
-    case kSearchFieldCancelButtonPart:
+    case kSliderVerticalPart:
+    case kSquareButtonPart:
+      // Supported appearance values don't need CSS border painting.
+      return false;
     default:
-      break;
+      if (node) {
+        UseCounter::Count(
+            node->GetDocument(),
+            WebFeature::kCSSValueAppearanceNoImplementationSkipBorder);
+      }
+      // TODO(tkent): Should do CSS border painting for non-supported
+      // appearance values.
+      return false;
   }
 
   return false;
diff --git a/third_party/blink/renderer/core/paint/view_painter_test.cc b/third_party/blink/renderer/core/paint/view_painter_test.cc
index 39449477..160de65 100644
--- a/third_party/blink/renderer/core/paint/view_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/view_painter_test.cc
@@ -9,6 +9,8 @@
 #include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 
+using testing::ElementsAre;
+
 namespace blink {
 
 class ViewPainterTest : public PaintControllerPaintTest {
@@ -101,9 +103,9 @@
 
   SetBodyInnerHTML("<div style='height: 5000px'></div>");
 
-  EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 1,
-                      TestDisplayItem(ViewScrollingBackgroundClient(),
-                                      kDocumentBackgroundType));
+  EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+                                   kDocumentBackgroundType)));
 
   const auto& chunks = RootPaintController().GetPaintArtifact().PaintChunks();
   EXPECT_EQ(1u, chunks.size());
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 1339f36..9f36326 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -853,7 +853,7 @@
                               bool hot_spot_specified,
                               const IntPoint& hot_spot) {
   if (!CursorDataInternal())
-    SetCursorDataInternal(new CursorList);
+    SetCursorDataInternal(MakeGarbageCollected<CursorList>());
   MutableCursorDataInternal()->push_back(
       CursorData(image, hot_spot_specified, hot_spot));
 }
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc
index f42b5c2..c84fd52 100644
--- a/third_party/blink/renderer/core/timing/performance.cc
+++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -312,7 +312,7 @@
 
   const AtomicString& timing_allow_origin_string =
       original_timing_allow_origin.IsEmpty()
-          ? response.HttpHeaderField(HTTPNames::Timing_Allow_Origin)
+          ? response.HttpHeaderField(http_names::kTimingAllowOrigin)
           : original_timing_allow_origin;
   if (timing_allow_origin_string.IsEmpty() ||
       EqualIgnoringASCIICase(timing_allow_origin_string, "null"))
diff --git a/third_party/blink/renderer/core/timing/performance_server_timing.cc b/third_party/blink/renderer/core/timing/performance_server_timing.cc
index 9bc079fc..63b1dba 100644
--- a/third_party/blink/renderer/core/timing/performance_server_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_server_timing.cc
@@ -31,7 +31,7 @@
   WebVector<WebServerTimingInfo> result;
   const ResourceResponse& response = info.FinalResponse();
   std::unique_ptr<ServerTimingHeaderVector> headers = ParseServerTimingHeader(
-      response.HttpHeaderField(HTTPNames::Server_Timing));
+      response.HttpHeaderField(http_names::kServerTiming));
   result.reserve(headers->size());
   for (const auto& header : *headers) {
     result.emplace_back(header->Name(), header->Duration(),
diff --git a/third_party/blink/renderer/core/timing/performance_test.cc b/third_party/blink/renderer/core/timing/performance_test.cc
index 8ac8b6b8..bb442b2 100644
--- a/third_party/blink/renderer/core/timing/performance_test.cc
+++ b/third_party/blink/renderer/core/timing/performance_test.cc
@@ -171,7 +171,7 @@
                                     GetExecutionContext()));
 
   // When cross-origin redirect opts in.
-  redirect_chain.back().SetHTTPHeaderField(HTTPNames::Timing_Allow_Origin,
+  redirect_chain.back().SetHTTPHeaderField(http_names::kTimingAllowOrigin,
                                            origin_domain);
   EXPECT_TRUE(AllowsTimingRedirect(redirect_chain, final_response,
                                    *security_origin.get(),
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
index 4200376..6e60ab9 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -55,10 +55,8 @@
       CreateBackingThreadStartupData(ToIsolate(GetExecutionContext())));
 
   if (options.type() == "classic") {
-    // Dedicated worker is origin-bound, so use kSharableCrossOrigin.
     GetWorkerThread()->EvaluateClassicScript(
-        script_url, kSharableCrossOrigin, source_code,
-        nullptr /* cached_meta_data */, stack_id);
+        script_url, source_code, nullptr /* cached_meta_data */, stack_id);
   } else if (options.type() == "module") {
     network::mojom::FetchCredentialsMode credentials_mode;
     bool result =
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
index a833d26c..0fa29ff 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -22,7 +22,6 @@
 #include "third_party/blink/renderer/core/workers/worker_thread.h"
 #include "third_party/blink/renderer/core/workers/worker_thread_test_helper.h"
 #include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
 
@@ -144,9 +143,9 @@
         WorkerBackingThreadStartupData(
             WorkerBackingThreadStartupData::HeapLimitMode::kDefault,
             WorkerBackingThreadStartupData::AtomicsWaitMode::kAllow));
-    GetWorkerThread()->EvaluateClassicScript(
-        script_url, kOpaqueResource, source, nullptr /* cached_meta_data */,
-        v8_inspector::V8StackTraceId());
+    GetWorkerThread()->EvaluateClassicScript(script_url, source,
+                                             nullptr /* cached_meta_data */,
+                                             v8_inspector::V8StackTraceId());
   }
 
   DedicatedWorkerThreadForTest* GetDedicatedWorkerThread() {
diff --git a/third_party/blink/renderer/core/workers/installed_scripts_manager.cc b/third_party/blink/renderer/core/workers/installed_scripts_manager.cc
index 4ce377db..6e9e5b9d 100644
--- a/third_party/blink/renderer/core/workers/installed_scripts_manager.cc
+++ b/third_party/blink/renderer/core/workers/installed_scripts_manager.cc
@@ -27,13 +27,13 @@
 }
 
 String InstalledScriptsManager::ScriptData::GetReferrerPolicy() {
-  return headers_.Get(HTTPNames::Referrer_Policy);
+  return headers_.Get(http_names::kReferrerPolicy);
 }
 
 std::unique_ptr<Vector<String>>
 InstalledScriptsManager::ScriptData::CreateOriginTrialTokens() {
   return OriginTrialContext::ParseHeaderValue(
-      headers_.Get(HTTPNames::Origin_Trial));
+      headers_.Get(http_names::kOriginTrial));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
index 6ae503c..ad4b117 100644
--- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -81,8 +81,9 @@
 
   MessagePort* port = MessagePort::Create(*this);
   port->Entangle(std::move(channel));
-  MessageEvent* event = MessageEvent::Create(new MessagePortArray(1, port),
-                                             String(), String(), port);
+  MessageEvent* event =
+      MessageEvent::Create(MakeGarbageCollected<MessagePortArray>(1, port),
+                           String(), String(), port);
   event->initEvent(EventTypeNames::connect, false, false);
   DispatchEvent(*event);
 }
diff --git a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
index db995d23..6636d27f 100644
--- a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
+++ b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
@@ -68,7 +68,7 @@
   execution_context_ = &execution_context;
 
   ResourceRequest request(url);
-  request.SetHTTPMethod(HTTPNames::GET);
+  request.SetHTTPMethod(http_names::kGET);
   request.SetExternalRequestStateFromRequestorAddressSpace(
       creation_address_space);
   request.SetRequestContext(request_context);
@@ -102,7 +102,7 @@
   forbid_cross_origin_redirects_ = true;
 
   ResourceRequest request(url);
-  request.SetHTTPMethod(HTTPNames::GET);
+  request.SetHTTPMethod(http_names::kGET);
   request.SetExternalRequestStateFromRequestorAddressSpace(
       creation_address_space);
   request.SetRequestContext(request_context);
@@ -165,10 +165,10 @@
   response_encoding_ = response.TextEncodingName();
   app_cache_id_ = response.AppCacheID();
 
-  referrer_policy_ = response.HttpHeaderField(HTTPNames::Referrer_Policy);
+  referrer_policy_ = response.HttpHeaderField(http_names::kReferrerPolicy);
   ProcessContentSecurityPolicy(response);
   origin_trial_tokens_ = OriginTrialContext::ParseHeaderValue(
-      response.HttpHeaderField(HTTPNames::Origin_Trial));
+      response.HttpHeaderField(http_names::kOriginTrial));
 
   if (network_utils::IsReservedIPAddress(response.RemoteIPAddress())) {
     response_address_space_ =
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index b1f7a56..3f1c2f68 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -324,22 +324,20 @@
 
 void WorkerGlobalScope::EvaluateClassicScriptPausable(
     const KURL& script_url,
-    AccessControlStatus access_control_status,
     String source_code,
     std::unique_ptr<Vector<char>> cached_meta_data,
     const v8_inspector::V8StackTraceId& stack_id) {
   if (IsContextPaused()) {
-    AddPausedCall(WTF::Bind(
-        &WorkerGlobalScope::EvaluateClassicScriptPausable,
-        WrapWeakPersistent(this), script_url, access_control_status,
-        source_code, WTF::Passed(std::move(cached_meta_data)), stack_id));
+    AddPausedCall(WTF::Bind(&WorkerGlobalScope::EvaluateClassicScriptPausable,
+                            WrapWeakPersistent(this), script_url, source_code,
+                            WTF::Passed(std::move(cached_meta_data)),
+                            stack_id));
     return;
   }
   ThreadDebugger* debugger = ThreadDebugger::From(GetThread()->GetIsolate());
   if (debugger)
     debugger->ExternalAsyncTaskStarted(stack_id);
-  EvaluateClassicScript(script_url, access_control_status, source_code,
-                        std::move(cached_meta_data));
+  EvaluateClassicScript(script_url, source_code, std::move(cached_meta_data));
   if (debugger)
     debugger->ExternalAsyncTaskFinished(stack_id);
 }
@@ -384,7 +382,6 @@
 
 void WorkerGlobalScope::EvaluateClassicScript(
     const KURL& script_url,
-    AccessControlStatus access_control_status,
     String source_code,
     std::unique_ptr<Vector<char>> cached_meta_data) {
   DCHECK(IsContextThread());
@@ -395,8 +392,9 @@
   ReportingProxy().WillEvaluateClassicScript(
       source_code.length(),
       cached_meta_data.get() ? cached_meta_data->size() : 0);
+  // Cross-origin workers are disallowed, so use kSharableCrossOrigin.
   bool success = ScriptController()->Evaluate(
-      ScriptSourceCode(source_code, handler, script_url), access_control_status,
+      ScriptSourceCode(source_code, handler, script_url), kSharableCrossOrigin,
       nullptr /* error_event */, v8_cache_options_);
   ReportingProxy().DidEvaluateClassicScript(success);
 }
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h
index aa5bee47..940cf9f1 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -141,7 +141,6 @@
   // so that WorkerGlobalScope can be paused.
   void EvaluateClassicScriptPausable(
       const KURL& script_url,
-      AccessControlStatus access_control_status,
       String source_code,
       std::unique_ptr<Vector<char>> cached_meta_data,
       const v8_inspector::V8StackTraceId& stack_id);
@@ -184,7 +183,6 @@
   // Evaluates the given top-level classic script.
   virtual void EvaluateClassicScript(
       const KURL& script_url,
-      AccessControlStatus access_control_status,
       String source_code,
       std::unique_ptr<Vector<char>> cached_meta_data);
 
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
index d29be4a..5585696 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -165,7 +165,6 @@
 
 void WorkerThread::EvaluateClassicScript(
     const KURL& script_url,
-    AccessControlStatus access_control_status,
     const String& source_code,
     std::unique_ptr<Vector<char>> cached_meta_data,
     const v8_inspector::V8StackTraceId& stack_id) {
@@ -173,8 +172,7 @@
   PostCrossThreadTask(
       *GetTaskRunner(TaskType::kInternalWorker), FROM_HERE,
       CrossThreadBind(&WorkerThread::EvaluateClassicScriptOnWorkerThread,
-                      CrossThreadUnretained(this), script_url,
-                      access_control_status, source_code,
+                      CrossThreadUnretained(this), script_url, source_code,
                       WTF::Passed(std::move(cached_meta_data)), stack_id));
 }
 
@@ -503,13 +501,11 @@
 
 void WorkerThread::EvaluateClassicScriptOnWorkerThread(
     const KURL& script_url,
-    AccessControlStatus access_control_status,
     String source_code,
     std::unique_ptr<Vector<char>> cached_meta_data,
     const v8_inspector::V8StackTraceId& stack_id) {
   To<WorkerGlobalScope>(GlobalScope())
-      ->EvaluateClassicScriptPausable(script_url, access_control_status,
-                                      std::move(source_code),
+      ->EvaluateClassicScriptPausable(script_url, std::move(source_code),
                                       std::move(cached_meta_data), stack_id);
 }
 
diff --git a/third_party/blink/renderer/core/workers/worker_thread.h b/third_party/blink/renderer/core/workers/worker_thread.h
index bd1b085..648714a9 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.h
+++ b/third_party/blink/renderer/core/workers/worker_thread.h
@@ -42,7 +42,6 @@
 #include "third_party/blink/renderer/core/inspector/devtools_agent.h"
 #include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
 #include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h"
-#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
 #include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
 #include "third_party/blink/renderer/platform/web_task_runner.h"
@@ -107,7 +106,6 @@
   // Posts a task to evaluate a top-level classic script on the worker thread.
   // Called on the main thread after Start().
   void EvaluateClassicScript(const KURL& script_url,
-                             AccessControlStatus access_control_status,
                              const String& source_code,
                              std::unique_ptr<Vector<char>> cached_meta_data,
                              const v8_inspector::V8StackTraceId& stack_id);
@@ -286,7 +284,6 @@
 
   void EvaluateClassicScriptOnWorkerThread(
       const KURL& script_url,
-      AccessControlStatus access_control_status,
       String source_code,
       std::unique_ptr<Vector<char>> cached_meta_data,
       const v8_inspector::V8StackTraceId& stack_id);
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
index 041e38ea..9d9111d 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
+++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -27,7 +27,6 @@
 #include "third_party/blink/renderer/core/workers/worker_thread.h"
 #include "third_party/blink/renderer/platform/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
 #include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
 #include "third_party/blink/renderer/platform/waitable_event.h"
 #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"
@@ -103,8 +102,7 @@
     Start(std::move(creation_params),
           WorkerBackingThreadStartupData::CreateDefault(), nullptr,
           parent_execution_context_task_runners);
-    EvaluateClassicScript(script_url, kOpaqueResource, source,
-                          nullptr /* cached_meta_data */,
+    EvaluateClassicScript(script_url, source, nullptr /* cached_meta_data */,
                           v8_inspector::V8StackTraceId());
   }
 
diff --git a/third_party/blink/renderer/core/xml/xpath_grammar.y b/third_party/blink/renderer/core/xml/xpath_grammar.y
index 02f81a9..fcd33e5 100644
--- a/third_party/blink/renderer/core/xml/xpath_grammar.y
+++ b/third_party/blink/renderer/core/xml/xpath_grammar.y
@@ -272,7 +272,7 @@
 PredicateList:
     Predicate
     {
-      $$ = new blink::HeapVector<blink::Member<blink::xpath::Predicate>>;
+      $$ = blink::MakeGarbageCollected<blink::HeapVector<blink::Member<blink::xpath::Predicate>>>();
       $$->push_back(new blink::xpath::Predicate($1));
     }
     |
@@ -356,7 +356,7 @@
 ArgumentList:
     Argument
     {
-      $$ = new blink::HeapVector<blink::Member<blink::xpath::Expression>>;
+      $$ = blink::MakeGarbageCollected<blink::HeapVector<blink::Member<blink::xpath::Expression>>>();
       $$->push_back($1);
     }
     |
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index 7662f645..a075c1b 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -809,7 +809,7 @@
 }
 
 bool XMLHttpRequest::AreMethodAndURLValidForSend() {
-  return method_ != HTTPNames::GET && method_ != HTTPNames::HEAD &&
+  return method_ != http_names::kGET && method_ != http_names::kHEAD &&
          url_.ProtocolIsInHTTPFamily();
 }
 
@@ -868,7 +868,7 @@
     if (!HasContentTypeRequestHeader()) {
       const String& blob_type = FetchUtils::NormalizeHeaderValue(body->type());
       if (!blob_type.IsEmpty() && ParsedContentType(blob_type).IsValid()) {
-        SetRequestHeaderInternal(HTTPNames::Content_Type,
+        SetRequestHeaderInternal(http_names::kContentType,
                                  AtomicString(blob_type));
       }
     }
@@ -906,7 +906,7 @@
       AtomicString content_type =
           AtomicString("multipart/form-data; boundary=") +
           FetchUtils::NormalizeHeaderValue(http_body->Boundary().data());
-      SetRequestHeaderInternal(HTTPNames::Content_Type, content_type);
+      SetRequestHeaderInternal(http_names::kContentType, content_type);
     }
   }
 
@@ -993,7 +993,7 @@
 void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
                                    ExceptionState& exception_state) {
   // Only GET request is supported for blob URL.
-  if (url_.ProtocolIs("blob") && method_ != HTTPNames::GET) {
+  if (url_.ProtocolIs("blob") && method_ != http_names::kGET) {
     HandleNetworkError();
 
     if (!async_) {
@@ -1063,8 +1063,8 @@
                      request_headers_, with_credentials_);
 
   if (http_body) {
-    DCHECK_NE(method_, HTTPNames::GET);
-    DCHECK_NE(method_, HTTPNames::HEAD);
+    DCHECK_NE(method_, http_names::kGET);
+    DCHECK_NE(method_, http_names::kHEAD);
     request.SetHTTPBody(std::move(http_body));
   }
 
@@ -1436,7 +1436,7 @@
 }
 
 bool XMLHttpRequest::HasContentTypeRequestHeader() const {
-  return request_headers_.Find(HTTPNames::Content_Type) !=
+  return request_headers_.Find(http_names::kContentType) !=
          request_headers_.end();
 }
 
@@ -1517,9 +1517,10 @@
   if (!overridden_type.IsEmpty())
     return overridden_type;
 
-  if (response_.IsHTTP())
+  if (response_.IsHTTP()) {
     return ExtractMIMETypeFromMediaType(
-        response_.HttpHeaderField(HTTPNames::Content_Type));
+        response_.HttpHeaderField(http_names::kContentType));
+  }
 
   return response_.MimeType();
 }
@@ -1545,14 +1546,14 @@
     const String& charset) {
   // http://xhr.spec.whatwg.org/#the-send()-method step 4's concilliation of
   // "charset=" in any author-provided Content-Type: request header.
-  String content_type = request_headers_.Get(HTTPNames::Content_Type);
+  String content_type = request_headers_.Get(http_names::kContentType);
   if (content_type.IsNull()) {
-    SetRequestHeaderInternal(HTTPNames::Content_Type, default_content_type);
+    SetRequestHeaderInternal(http_names::kContentType, default_content_type);
     return;
   }
   String original_content_type = content_type;
   ReplaceCharsetInMediaType(content_type, charset);
-  request_headers_.Set(HTTPNames::Content_Type, AtomicString(content_type));
+  request_headers_.Set(http_names::kContentType, AtomicString(content_type));
 
   if (original_content_type != content_type) {
     UseCounter::Count(GetExecutionContext(), WebFeature::kReplaceCharsetInXHR);
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index b9be0d1a..a75c00d 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -273,14 +273,10 @@
     "indexeddb/idb_test_helper.cc",
     "indexeddb/idb_transaction_test.cc",
     "indexeddb/idb_value_wrapping_test.cc",
-    "indexeddb/mock_web_idb_callbacks.cc",
-    "indexeddb/mock_web_idb_callbacks.h",
     "indexeddb/mock_web_idb_database.cc",
     "indexeddb/mock_web_idb_database.h",
     "indexeddb/mock_web_idb_factory.cc",
     "indexeddb/mock_web_idb_factory.h",
-    "indexeddb/web_idb_cursor_impl_unittest.cc",
-    "indexeddb/web_idb_database_impl_unittest.cc",
     "manifest/image_resource_type_converters_test.cc",
     "media_controls/elements/media_control_animated_arrow_container_element_test.cc",
     "media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc",
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index 8197c4b..ab76403 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -593,7 +593,7 @@
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   const ScriptPromise promise = resolver->Promise();
-  if (request->method() != HTTPNames::GET && !options.ignoreMethod()) {
+  if (request->method() != http_names::kGET && !options.ignoreMethod()) {
     resolver->Resolve();
     return promise;
   }
@@ -650,7 +650,7 @@
   if (request) {
     request->PopulateWebServiceWorkerRequest(web_request.emplace());
 
-    if (request->method() != HTTPNames::GET && !options.ignoreMethod()) {
+    if (request->method() != http_names::kGET && !options.ignoreMethod()) {
       resolver->Resolve(HeapVector<Member<Response>>());
       return promise;
     }
@@ -714,7 +714,7 @@
                                        "Add/AddAll does not support schemes "
                                        "other than \"http\" or \"https\""));
     }
-    if (requests[i]->method() != HTTPNames::GET) {
+    if (requests[i]->method() != http_names::kGET) {
       return ScriptPromise::Reject(
           script_state,
           V8ThrowException::CreateTypeError(
@@ -737,7 +737,7 @@
                                 const CacheQueryOptions& options) {
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   const ScriptPromise promise = resolver->Promise();
-  if (request->method() != HTTPNames::GET && !options.ignoreMethod()) {
+  if (request->method() != http_names::kGET && !options.ignoreMethod()) {
     resolver->Resolve(false);
     return promise;
   }
@@ -818,7 +818,7 @@
                                 "' is unsupported");
       return promise;
     }
-    if (requests[i]->method() != HTTPNames::GET) {
+    if (requests[i]->method() != http_names::kGET) {
       barrier_callback->OnError("Request method '" + requests[i]->method() +
                                 "' is unsupported");
       return promise;
@@ -900,7 +900,7 @@
   if (request) {
     request->PopulateWebServiceWorkerRequest(web_request.emplace());
 
-    if (request->method() != HTTPNames::GET && !options.ignoreMethod()) {
+    if (request->method() != http_names::kGET && !options.ignoreMethod()) {
       resolver->Resolve(HeapVector<Member<Response>>());
       return promise;
     }
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
index e5076b5..f640f42 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
@@ -170,7 +170,7 @@
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   const ScriptPromise promise = resolver->Promise();
 
-  if (request->method() != HTTPNames::GET && !options.ignoreMethod()) {
+  if (request->method() != http_names::kGET && !options.ignoreMethod()) {
     resolver->Resolve();
     return promise;
   }
diff --git a/third_party/blink/renderer/modules/eventsource/event_source.cc b/third_party/blink/renderer/modules/eventsource/event_source.cc
index 90eff457..dd7bb979 100644
--- a/third_party/blink/renderer/modules/eventsource/event_source.cc
+++ b/third_party/blink/renderer/modules/eventsource/event_source.cc
@@ -123,9 +123,9 @@
 
   ExecutionContext& execution_context = *this->GetExecutionContext();
   ResourceRequest request(current_url_);
-  request.SetHTTPMethod(HTTPNames::GET);
-  request.SetHTTPHeaderField(HTTPNames::Accept, "text/event-stream");
-  request.SetHTTPHeaderField(HTTPNames::Cache_Control, "no-cache");
+  request.SetHTTPMethod(http_names::kGET);
+  request.SetHTTPHeaderField(http_names::kAccept, "text/event-stream");
+  request.SetHTTPHeaderField(http_names::kCacheControl, "no-cache");
   request.SetRequestContext(mojom::RequestContextType::EVENT_SOURCE);
   request.SetFetchRequestMode(network::mojom::FetchRequestMode::kCORS);
   request.SetFetchCredentialsMode(
@@ -143,7 +143,7 @@
     // setHTTPHeaderField's arguments.
     CString last_event_id_utf8 = parser_->LastEventId().Utf8();
     request.SetHTTPHeaderField(
-        HTTPNames::Last_Event_ID,
+        http_names::kLastEventID,
         AtomicString(reinterpret_cast<const LChar*>(last_event_id_utf8.data()),
                      last_event_id_utf8.length()));
   }
diff --git a/third_party/blink/renderer/modules/exported/BUILD.gn b/third_party/blink/renderer/modules/exported/BUILD.gn
index bfc6251..f79e1d1 100644
--- a/third_party/blink/renderer/modules/exported/BUILD.gn
+++ b/third_party/blink/renderer/modules/exported/BUILD.gn
@@ -5,7 +5,6 @@
 
 blink_modules_sources("exported") {
   sources = [
-    "indexed_db_key_builder.cc",
     "web_apply_constraints_request.cc",
     "web_ax_context.cc",
     "web_ax_object.cc",
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
index ed97e38..e93ddfa4 100644
--- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
+++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -466,10 +466,9 @@
     // > "classic": Fetch a classic worker script given job’s serialized script
     // > url, job’s client, "serviceworker", and the to-be-created environment
     // > settings object for this service worker.
-    // Service worker is origin-bound, so use kSharableCrossOrigin.
     worker_thread_->EvaluateClassicScript(
-        worker_start_data_.script_url, kSharableCrossOrigin, source_code,
-        std::move(cached_meta_data), v8_inspector::V8StackTraceId());
+        worker_start_data_.script_url, source_code, std::move(cached_meta_data),
+        v8_inspector::V8StackTraceId());
   } else {
     // > "module": Fetch a module worker script graph given job’s serialized
     // > script url, job’s client, "serviceworker", "omit", and the
diff --git a/third_party/blink/renderer/modules/exported/web_idb_key.cc b/third_party/blink/renderer/modules/exported/web_idb_key.cc
index 4b26410..600bfce 100644
--- a/third_party/blink/renderer/modules/exported/web_idb_key.cc
+++ b/third_party/blink/renderer/modules/exported/web_idb_key.cc
@@ -68,23 +68,6 @@
   return private_->Number();
 }
 
-size_t WebIDBKeyView::SizeEstimate() const {
-  // TODO(cmp): Ensure |private_| can never be null.
-  //
-  // SizeEstimate() can be called when |private_| is null.  That happens if and
-  // only if the |WebIDBKey| instance is created using WebIDBKey::CreateNull().
-  //
-  // Eventually, WebIDBKey::CreateNull() will change so that case will lead to
-  // a non-null |private_|.  At that time, this null check can change to a
-  // DCHECK that |private_| is not null and the special null case handling can
-  // be removed.
-  if (this->IsNull()) {
-    return IDBKey::kIDBKeyOverheadSize;
-  }
-
-  return private_->SizeEstimate();
-}
-
 WebIDBKey WebIDBKey::CreateArray(WebVector<WebIDBKey> array) {
   IDBKey::KeyArray keys;
   keys.ReserveCapacity(SafeCast<wtf_size_t>(array.size()));
@@ -129,11 +112,4 @@
   return *this;
 }
 
-WebIDBKey::WebIDBKey(const WebIDBKey& rkey)
-    : private_(IDBKey::Clone(rkey.private_)) {}
-WebIDBKey& WebIDBKey::operator=(const WebIDBKey& rkey) {
-  private_ = IDBKey::Clone(rkey.private_);
-  return *this;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/directory_reader.cc b/third_party/blink/renderer/modules/filesystem/directory_reader.cc
index e234149..e3bf350 100644
--- a/third_party/blink/renderer/modules/filesystem/directory_reader.cc
+++ b/third_party/blink/renderer/modules/filesystem/directory_reader.cc
@@ -118,7 +118,8 @@
   }
 
   if (!has_more_entries_ || !entries_.IsEmpty()) {
-    EntryHeapVector* entries = new EntryHeapVector(std::move(entries_));
+    EntryHeapVector* entries =
+        MakeGarbageCollected<EntryHeapVector>(std::move(entries_));
     DOMFileSystem::ScheduleCallback(
         Filesystem()->GetExecutionContext(),
         WTF::Bind(
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
index 06bde352..b08b1f6 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
+++ b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
@@ -223,7 +223,7 @@
       success_callback_(success_callback),
       directory_reader_(directory_reader),
       base_path_(base_path),
-      entries_(new HeapVector<Member<Entry>>()) {
+      entries_(MakeGarbageCollected<HeapVector<Member<Entry>>>()) {
   DCHECK(directory_reader_);
 }
 
@@ -240,7 +240,8 @@
 
 void EntriesCallbacks::DidReadDirectoryEntries(bool has_more) {
   directory_reader_->SetHasMoreEntries(has_more);
-  EntryHeapVector* entries = new EntryHeapVector(std::move(*entries_));
+  EntryHeapVector* entries =
+      MakeGarbageCollected<EntryHeapVector>(std::move(*entries_));
 
   if (!success_callback_)
     return;
diff --git a/third_party/blink/renderer/modules/indexeddb/BUILD.gn b/third_party/blink/renderer/modules/indexeddb/BUILD.gn
index 8f00ce4..b16dcc0 100644
--- a/third_party/blink/renderer/modules/indexeddb/BUILD.gn
+++ b/third_party/blink/renderer/modules/indexeddb/BUILD.gn
@@ -58,34 +58,13 @@
     "idb_version_change_event.cc",
     "idb_version_change_event.h",
     "indexed_db.h",
-    "indexed_db_callbacks_impl.cc",
-    "indexed_db_callbacks_impl.h",
     "indexed_db_client.cc",
     "indexed_db_client.h",
-    "indexed_db_database_callbacks_impl.cc",
-    "indexed_db_database_callbacks_impl.h",
-    "indexed_db_dispatcher.cc",
-    "indexed_db_dispatcher.h",
-    "indexed_db_mojom_traits.cc",
-    "indexed_db_mojom_traits.h",
     "inspector_indexed_db_agent.cc",
     "inspector_indexed_db_agent.h",
     "web_idb_callbacks_impl.cc",
     "web_idb_callbacks_impl.h",
-    "web_idb_cursor.h",
-    "web_idb_cursor_impl.cc",
-    "web_idb_cursor_impl.h",
-    "web_idb_database.h",
     "web_idb_database_callbacks_impl.cc",
     "web_idb_database_callbacks_impl.h",
-    "web_idb_database_impl.cc",
-    "web_idb_database_impl.h",
-    "web_idb_factory.h",
-    "web_idb_factory_impl.cc",
-    "web_idb_factory_impl.h",
-  ]
-
-  public_deps = [
-    "//third_party/blink/public/mojom:mojom_modules_blink",
   ]
 }
diff --git a/third_party/blink/renderer/modules/indexeddb/OWNERS b/third_party/blink/renderer/modules/indexeddb/OWNERS
index 4d50d63..a740487 100644
--- a/third_party/blink/renderer/modules/indexeddb/OWNERS
+++ b/third_party/blink/renderer/modules/indexeddb/OWNERS
@@ -1,9 +1,4 @@
 file://content/browser/indexed_db/OWNERS
 
-per-file *_mojom_traits*.*=set noparent
-per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
-
 # TEAM: storage-dev@chromium.org
 # COMPONENT: Blink>Storage>IndexedDB
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
index d161436..0a815c7 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
@@ -27,6 +27,7 @@
 
 #include <limits>
 #include <memory>
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
 #include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
@@ -37,7 +38,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_object_store.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor.h b/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
index 821aaf2..64cec7cd 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
@@ -29,12 +29,12 @@
 #include <memory>
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/compiler.h"
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h b/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
index 5914effa..91223d4 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
@@ -28,9 +28,9 @@
 
 #include <memory>
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database.cc b/third_party/blink/renderer/modules/indexeddb/idb_database.cc
index ab6dc279..db3a230 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_database.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -208,7 +208,7 @@
       IDBTransaction* transaction = nullptr;
       auto it = transactions.find(map_entry.first);
       if (it != transactions.end()) {
-        const std::pair<int64_t, WebVector<int64_t>>& obs_txn = it->second;
+        const std::pair<int64_t, std::vector<int64_t>>& obs_txn = it->second;
         HashSet<String> stores;
         for (int64_t store_id : obs_txn.second) {
           stores.insert(metadata_.object_stores.at(store_id)->name);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database.h b/third_party/blink/renderer/modules/indexeddb/idb_database.h
index c85d9183..90c1175 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_database.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_database.h
@@ -29,6 +29,7 @@
 #include <memory>
 
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/string_or_string_sequence.h"
@@ -42,7 +43,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_object_store_parameters.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
index 85b5354..1e123b7a 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -31,10 +31,9 @@
 #include <memory>
 #include <utility>
 
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_name_and_version.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -54,8 +53,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db_client.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/histogram.h"
@@ -189,13 +186,8 @@
 }
 
 WebIDBFactory* IDBFactory::GetFactory() {
-  if (!web_idb_factory_) {
-    mojom::blink::IDBFactoryPtrInfo web_idb_factory_host_info;
-    Platform::Current()->GetInterfaceProvider()->GetInterface(
-        mojo::MakeRequest(&web_idb_factory_host_info));
-    web_idb_factory_ = std::make_unique<WebIDBFactoryImpl>(
-        std::move(web_idb_factory_host_info));
-  }
+  if (!web_idb_factory_)
+    web_idb_factory_ = Platform::Current()->CreateIdbFactory();
   return web_idb_factory_.get();
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.h b/third_party/blink/renderer/modules/indexeddb/idb_factory.h
index 3ff9b1c..3d7e36d 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.h
@@ -29,9 +29,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_FACTORY_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_FACTORY_H_
 
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_index.h b/third_party/blink/renderer/modules/indexeddb/idb_index.h
index e78ec6ff..99a4824 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_index.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_index.h
@@ -27,13 +27,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_INDEX_H_
 
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key.cc b/third_party/blink/renderer/modules/indexeddb/idb_key.cc
index 530e07b..8ed421c 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_key.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_key.cc
@@ -34,40 +34,6 @@
 
 namespace blink {
 
-namespace {
-
-size_t CalculateIDBKeyArraySize(const IDBKey::KeyArray& keys) {
-  size_t size(0);
-  for (const auto& key : keys)
-    size += key.get()->SizeEstimate();
-  return size;
-}
-
-}  // namespace
-
-IDBKey::IDBKey() : type_(kInvalidType), size_estimate_(kIDBKeyOverheadSize) {}
-
-IDBKey::IDBKey(Type type, double number)
-    : type_(type),
-      number_(number),
-      size_estimate_(kIDBKeyOverheadSize + sizeof(number_)) {}
-
-IDBKey::IDBKey(const class String& value)
-    : type_(kStringType),
-      string_(value),
-      size_estimate_(kIDBKeyOverheadSize + (string_.length() * sizeof(UChar))) {
-}
-
-IDBKey::IDBKey(scoped_refptr<SharedBuffer> value)
-    : type_(kBinaryType),
-      binary_(std::move(value)),
-      size_estimate_(kIDBKeyOverheadSize + binary_.get()->size()) {}
-
-IDBKey::IDBKey(KeyArray key_array)
-    : type_(kArrayType),
-      array_(std::move(key_array)),
-      size_estimate_(kIDBKeyOverheadSize + CalculateIDBKeyArraySize(array_)) {}
-
 IDBKey::~IDBKey() = default;
 
 bool IDBKey::IsValid() const {
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key.h b/third_party/blink/renderer/modules/indexeddb/idb_key.h
index a57d257..3082acad 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_key.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_key.h
@@ -78,50 +78,8 @@
     return base::WrapUnique(new IDBKey(std::move(array)));
   }
 
-  // TODO(cmp): This |Clone| function is necessary for WebIDBKey's ctor
-  //            functions.  It needs to be available in this header file so
-  //            web_idb_key.cc can use it.  When the IDB Blink variant typemap
-  //            moves to the renderer/modules/indexeddb/ types and off of the
-  //            WebIDB* types, this |Clone| function should be removed.
-  static std::unique_ptr<IDBKey> Clone(const std::unique_ptr<IDBKey>& rkey_in) {
-    IDBKey* rkey = rkey_in.get();
-    if (!rkey_in.get())
-      return nullptr;
-
-    switch (rkey->GetType()) {
-      case kInvalidType:
-        return IDBKey::CreateInvalid();
-      case kArrayType: {
-        IDBKey::KeyArray lkey_array;
-        const auto& rkey_array = rkey->Array();
-        for (const auto& rkey_item : rkey_array)
-          lkey_array.push_back(IDBKey::Clone(rkey_item));
-        return IDBKey::CreateArray(std::move(lkey_array));
-      }
-      case kBinaryType:
-        return IDBKey::CreateBinary(rkey->Binary());
-      case kStringType:
-        return IDBKey::CreateString(rkey->GetString());
-      case kDateType:
-        return IDBKey::CreateDate(rkey->Date());
-      case kNumberType:
-        return IDBKey::CreateNumber(rkey->Number());
-
-      case kTypeEnumMax:
-        break;  // Not used, NOTREACHED.
-    }
-    NOTREACHED();
-    return nullptr;
-  }
-
   ~IDBKey();
 
-  // Very rough estimate of minimum key size overhead.
-  //
-  // TODO(cmp): When the reference to this in web_idb_key.cc goes away, move
-  //            this variable back to idb_key.cc's anonymous namespace.
-  static const size_t kIDBKeyOverheadSize = 16;
-
   // In order of the least to the highest precedent in terms of sort order.
   // These values are written to logs. New enum values can be added, but
   // existing enums must never be renumbered or deleted and reused.
@@ -166,7 +124,6 @@
   int Compare(const IDBKey* other) const;
   bool IsLessThan(const IDBKey* other) const;
   bool IsEqual(const IDBKey* other) const;
-  size_t SizeEstimate() const { return size_estimate_; }
 
   // Returns a new key array with invalid keys and duplicates removed.
   //
@@ -183,22 +140,20 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(IDBKey);
 
-  IDBKey();
-  IDBKey(Type type, double number);
-  explicit IDBKey(const class String& value);
-  explicit IDBKey(scoped_refptr<SharedBuffer> value);
-  explicit IDBKey(KeyArray key_array);
+  IDBKey() : type_(kInvalidType) {}
+  IDBKey(Type type, double number) : type_(type), number_(number) {}
+  explicit IDBKey(const class String& value)
+      : type_(kStringType), string_(value) {}
+  explicit IDBKey(scoped_refptr<SharedBuffer> value)
+      : type_(kBinaryType), binary_(std::move(value)) {}
+  explicit IDBKey(KeyArray key_array)
+      : type_(kArrayType), array_(std::move(key_array)) {}
 
   Type type_;
   KeyArray array_;
   scoped_refptr<SharedBuffer> binary_;
   const class String string_;
   const double number_ = 0;
-
-  // Initialized in IDBKey constructors based on key type and value size (see
-  // idb_key.cc).  Returned via SizeEstimate() and used in IndexedDB code to
-  // verify that a given key is small enough to pass over IPC.
-  size_t size_estimate_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
index 51f4277d..722fa6d6 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -30,6 +30,7 @@
 #include "base/feature_list.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/numerics/safe_conversions.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
 #include "third_party/blink/public/platform/web_blob_info.h"
@@ -48,7 +49,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/histogram.h"
@@ -558,8 +558,8 @@
     key_type_histogram.Count(static_cast<int>(key->GetType()));
   }
 
-  Vector<WebIDBIndexKeys> index_keys;
-  index_keys.ReserveInitialCapacity(Metadata().indexes.size());
+  WebVector<WebIDBIndexKeys> index_keys;
+  index_keys.reserve(Metadata().indexes.size());
   for (const auto& it : Metadata().indexes) {
     if (clone.IsEmpty())
       value_wrapper.Clone(script_state, &clone);
@@ -754,8 +754,8 @@
       const IDBKey* primary_key = cursor->IdbPrimaryKey();
       ScriptValue value = cursor->value(script_state_);
 
-      Vector<WebIDBIndexKeys> index_keys;
-      index_keys.ReserveInitialCapacity(1);
+      WebVector<WebIDBIndexKeys> index_keys;
+      index_keys.reserve(1);
       index_keys.emplace_back(
           IndexMetadata().id,
           GenerateIndexKeysForValue(script_state_->GetIsolate(),
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.h b/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
index 747ece3..4174356a 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
@@ -28,6 +28,8 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_index.h"
@@ -37,8 +39,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
index 31a8c98..36d9ecb 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
@@ -27,8 +27,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_OPEN_DB_REQUEST_H_
 
 #include <memory>
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.h b/third_party/blink/renderer/modules/indexeddb/idb_request.h
index 2e737d33..5e1980d8 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request.h
@@ -34,6 +34,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/public/platform/web_blob_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
@@ -48,7 +49,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
index bb8753c..cfbe57f 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
@@ -9,12 +9,12 @@
 
 #include "base/callback.h"
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request_loader.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_transaction.h b/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
index 32c30c51..bfb15df 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
@@ -29,6 +29,7 @@
 #include <memory>
 
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/dom/dom_string_list.h"
@@ -37,7 +38,6 @@
 #include "third_party/blink/renderer/modules/event_target_modules.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/deque.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db.typemap b/third_party/blink/renderer/modules/indexeddb/indexed_db.typemap
deleted file mode 100644
index e4f018a..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db.typemap
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//third_party/blink/public/mojom/indexeddb/indexeddb.mojom"
-public_headers = [
-  "//third_party/blink/public/common/indexeddb/web_idb_types.h",
-  "//third_party/blink/public/platform/modules/indexeddb/web_idb_key.h",
-  "//third_party/blink/public/platform/modules/indexeddb/web_idb_key_path.h",
-  "//third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h",
-  "//third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h",
-  "//third_party/blink/public/platform/modules/indexeddb/web_idb_name_and_version.h",
-  "//third_party/blink/renderer/modules/indexeddb/idb_key_range.h",
-]
-traits_headers = [
-  "//mojo/public/cpp/base/string16_mojom_traits.h",
-  "//mojo/public/cpp/bindings/array_traits_web_vector.h",
-  "//mojo/public/cpp/bindings/array_traits_wtf_vector.h",
-  "//third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h",
-  "//third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.h",
-  "//third_party/blink/renderer/platform/mojo/string16_mojom_traits.h",
-]
-deps = [
-  "//mojo/public/cpp/bindings",
-  "//third_party/blink/renderer/platform/wtf",
-]
-type_mappings = [
-  "blink.mojom.IDBCursorDirection=::blink::WebIDBCursorDirection",
-  "blink.mojom.IDBDataLoss=::blink::WebIDBDataLoss",
-  "blink.mojom.IDBDatabaseMetadata=::blink::WebIDBMetadata",
-  "blink.mojom.IDBIndexKeys=::blink::WebIDBIndexKeys",
-  "blink.mojom.IDBIndexMetadata=::blink::WebIDBMetadata::Index",
-  "blink.mojom.IDBKey=::blink::WebIDBKey[move_only]",
-  "blink.mojom.IDBKeyPath=::blink::WebIDBKeyPath",
-  "blink.mojom.IDBKeyRange=::blink::WebIDBKeyRange",
-  "blink.mojom.IDBObjectStoreMetadata=::blink::WebIDBMetadata::ObjectStore",
-  "blink.mojom.IDBOperationType=::blink::WebIDBOperationType",
-  "blink.mojom.IDBPutMode=::blink::WebIDBPutMode",
-  "blink.mojom.IDBTaskType=::blink::WebIDBTaskType",
-  "blink.mojom.IDBTransactionMode=::blink::WebIDBTransactionMode",
-]
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc
deleted file mode 100644
index 1ccdcbfe..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
-
-#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_name_and_version.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h"
-
-using blink::IndexedDBDatabaseMetadata;
-using blink::WebBlobInfo;
-using blink::WebData;
-using blink::WebIDBCallbacks;
-using blink::WebIDBDatabase;
-using blink::WebIDBMetadata;
-using blink::WebIDBNameAndVersion;
-using blink::WebIDBValue;
-using blink::WebString;
-using blink::WebVector;
-using blink::mojom::blink::IDBDatabaseAssociatedPtrInfo;
-
-namespace blink {
-
-namespace {
-
-WebIDBValue ConvertReturnValue(const mojom::blink::IDBReturnValuePtr& value) {
-  if (!value)
-    return WebIDBValue(WebData(), WebVector<WebBlobInfo>());
-
-  WebIDBValue web_value = IndexedDBCallbacksImpl::ConvertValue(value->value);
-  web_value.SetInjectedPrimaryKey(value->primary_key, value->key_path);
-  return web_value;
-}
-
-WebIDBNameAndVersion ConvertNameVersion(
-    const mojom::blink::IDBNameAndVersionPtr& name_and_version) {
-  return WebIDBNameAndVersion(name_and_version->name,
-                              name_and_version->version);
-}
-
-}  // namespace
-
-// static
-WebIDBValue IndexedDBCallbacksImpl::ConvertValue(
-    const mojom::blink::IDBValuePtr& value) {
-  if (!value || value->bits.length() == 0)
-    return WebIDBValue(WebData(), WebVector<WebBlobInfo>());
-
-  WebVector<WebBlobInfo> local_blob_info;
-  local_blob_info.reserve(value->blob_or_file_info.size());
-  for (const auto& info : value->blob_or_file_info) {
-    if (info->file) {
-      local_blob_info.emplace_back(
-          WebString(info->uuid), FilePathToWebString(info->file->path),
-          WebString(info->file->name), WebString(info->mime_type),
-          info->file->last_modified.ToDoubleT(), info->size,
-          info->blob.PassHandle());
-    } else {
-      local_blob_info.emplace_back(WebString(info->uuid),
-                                   WebString(info->mime_type), info->size,
-                                   info->blob.PassHandle());
-    }
-  }
-
-  return WebIDBValue(WebData(value->bits.Latin1().data(), value->bits.length()),
-                     std::move(local_blob_info));
-}
-
-IndexedDBCallbacksImpl::IndexedDBCallbacksImpl(
-    std::unique_ptr<WebIDBCallbacks> callbacks,
-    int64_t transaction_id,
-    const base::WeakPtr<WebIDBCursorImpl>& cursor)
-    : callbacks_(std::move(callbacks)),
-      cursor_(cursor),
-      transaction_id_(transaction_id) {}
-
-IndexedDBCallbacksImpl::~IndexedDBCallbacksImpl() = default;
-
-void IndexedDBCallbacksImpl::Error(int32_t code, const WTF::String& message) {
-  callbacks_->OnError(WebIDBDatabaseError(code, WebString(message)));
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessNamesAndVersionsList(
-    Vector<mojom::blink::IDBNameAndVersionPtr> names_and_versions) {
-  WebVector<WebIDBNameAndVersion> web_names_and_versions;
-  web_names_and_versions.reserve(names_and_versions.size());
-  for (const mojom::blink::IDBNameAndVersionPtr& name_version :
-       names_and_versions)
-    web_names_and_versions.emplace_back(ConvertNameVersion(name_version));
-  callbacks_->OnSuccess(web_names_and_versions);
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessStringList(const Vector<String>& value) {
-  WebVector<WebString> web_value(value.size());
-  std::transform(value.begin(), value.end(), web_value.begin(),
-                 [](const WTF::String& s) { return WebString(s); });
-  callbacks_->OnSuccess(web_value);
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::Blocked(int64_t existing_version) {
-  callbacks_->OnBlocked(existing_version);
-  // Not resetting |callbacks_|.  In this instance we will have to forward at
-  // least one other call in the set OnUpgradeNeeded() / OnSuccess() /
-  // OnError().
-}
-
-void IndexedDBCallbacksImpl::UpgradeNeeded(
-    IDBDatabaseAssociatedPtrInfo database_info,
-    int64_t old_version,
-    WebIDBDataLoss data_loss,
-    const String& data_loss_message,
-    const WebIDBMetadata& web_metadata) {
-  WebIDBDatabase* database = new WebIDBDatabaseImpl(std::move(database_info));
-  callbacks_->OnUpgradeNeeded(old_version, database, web_metadata, data_loss,
-                              WebString(data_loss_message));
-  // Not resetting |callbacks_|.  In this instance we will have to forward at
-  // least one other call in the set OnSuccess() / OnError().
-}
-
-void IndexedDBCallbacksImpl::SuccessDatabase(
-    IDBDatabaseAssociatedPtrInfo database_info,
-    const WebIDBMetadata& web_metadata) {
-  WebIDBDatabase* database = nullptr;
-  if (database_info.is_valid())
-    database = new WebIDBDatabaseImpl(std::move(database_info));
-
-  callbacks_->OnSuccess(database, web_metadata);
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessCursor(
-    mojom::blink::IDBCursorAssociatedPtrInfo cursor_info,
-    WebIDBKey key,
-    WebIDBKey primary_key,
-    mojom::blink::IDBValuePtr value) {
-  WebIDBCursorImpl* cursor =
-      new WebIDBCursorImpl(std::move(cursor_info), transaction_id_);
-  callbacks_->OnSuccess(cursor, std::move(key), std::move(primary_key),
-                        ConvertValue(value));
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessValue(
-    mojom::blink::IDBReturnValuePtr value) {
-  callbacks_->OnSuccess(ConvertReturnValue(value));
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessCursorContinue(
-    WebIDBKey key,
-    WebIDBKey primary_key,
-    mojom::blink::IDBValuePtr value) {
-  callbacks_->OnSuccess(std::move(key), std::move(primary_key),
-                        ConvertValue(value));
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessCursorPrefetch(
-    Vector<WebIDBKey> keys,
-    Vector<WebIDBKey> primary_keys,
-    Vector<mojom::blink::IDBValuePtr> values) {
-  Vector<WebIDBValue> web_values;
-  web_values.ReserveInitialCapacity(values.size());
-  for (const mojom::blink::IDBValuePtr& value : values)
-    web_values.emplace_back(ConvertValue(value));
-
-  if (cursor_) {
-    cursor_->SetPrefetchData(std::move(keys), std::move(primary_keys),
-                             std::move(web_values));
-    cursor_->CachedContinue(callbacks_.get());
-  }
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessArray(
-    Vector<mojom::blink::IDBReturnValuePtr> values) {
-  WebVector<WebIDBValue> web_values;
-  web_values.reserve(values.size());
-  for (const mojom::blink::IDBReturnValuePtr& value : values)
-    web_values.emplace_back(ConvertReturnValue(value));
-  callbacks_->OnSuccess(std::move(web_values));
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessKey(WebIDBKey key) {
-  callbacks_->OnSuccess(std::move(key));
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::SuccessInteger(int64_t value) {
-  callbacks_->OnSuccess(value);
-  callbacks_.reset();
-}
-
-void IndexedDBCallbacksImpl::Success() {
-  callbacks_->OnSuccess();
-  callbacks_.reset();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h
deleted file mode 100644
index dd49fd8..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_CALLBACKS_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_CALLBACKS_IMPL_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-
-using blink::IndexedDBKey;
-
-namespace blink {
-
-class WebIDBCallbacks;
-class WebIDBCursorImpl;
-class WebIDBValue;
-
-// Implements the child-process end of the pipe used to deliver callbacks.
-// |callback_runner_| is used to post tasks back to the thread which owns the
-// blink::WebIDBCallbacks.
-class IndexedDBCallbacksImpl : public mojom::blink::IDBCallbacks {
- public:
-  // |kNoTransaction| is used as the default transaction ID when instantiating
-  // an IndexedDBCallbacksImpl instance.  See web_idb_factory_impl.cc for those
-  // cases.
-  enum : int64_t { kNoTransaction = -1 };
-
-  static WebIDBValue ConvertValue(const mojom::blink::IDBValuePtr& value);
-
-  IndexedDBCallbacksImpl(std::unique_ptr<WebIDBCallbacks> callbacks,
-                         int64_t transaction_id,
-                         const base::WeakPtr<WebIDBCursorImpl>& cursor);
-  ~IndexedDBCallbacksImpl() override;
-
-  // mojom::blink::IDBCallbacks implementation:
-  void Error(int32_t code, const String& message) override;
-  void SuccessNamesAndVersionsList(
-      Vector<mojom::blink::IDBNameAndVersionPtr> names_and_versions) override;
-  void SuccessStringList(const Vector<String>& value) override;
-  void Blocked(int64_t existing_version) override;
-  void UpgradeNeeded(mojom::blink::IDBDatabaseAssociatedPtrInfo database_info,
-                     int64_t old_version,
-                     WebIDBDataLoss data_loss,
-                     const String& data_loss_message,
-                     const WebIDBMetadata& metadata) override;
-  void SuccessDatabase(mojom::blink::IDBDatabaseAssociatedPtrInfo database_info,
-                       const WebIDBMetadata& metadata) override;
-  void SuccessCursor(mojom::blink::IDBCursorAssociatedPtrInfo cursor,
-                     WebIDBKey key,
-                     WebIDBKey primary_key,
-                     mojom::blink::IDBValuePtr value) override;
-  void SuccessValue(mojom::blink::IDBReturnValuePtr value) override;
-  void SuccessCursorContinue(WebIDBKey key,
-                             WebIDBKey primary_key,
-                             mojom::blink::IDBValuePtr value) override;
-  void SuccessCursorPrefetch(Vector<WebIDBKey> keys,
-                             Vector<WebIDBKey> primary_keys,
-                             Vector<mojom::blink::IDBValuePtr> values) override;
-  void SuccessArray(Vector<mojom::blink::IDBReturnValuePtr> values) override;
-  void SuccessKey(WebIDBKey key) override;
-  void SuccessInteger(int64_t value) override;
-  void Success() override;
-
- private:
-  scoped_refptr<base::SingleThreadTaskRunner> callback_runner_;
-  std::unique_ptr<WebIDBCallbacks> callbacks_;
-  base::WeakPtr<WebIDBCursorImpl> cursor_;
-  int64_t transaction_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(IndexedDBCallbacksImpl);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_CALLBACKS_IMPL_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h
deleted file mode 100644
index 702ea69..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-
-namespace blink {
-class WebIDBDatabaseCallbacks;
-
-class IndexedDBDatabaseCallbacksImpl
-    : public mojom::blink::IDBDatabaseCallbacks {
- public:
-  explicit IndexedDBDatabaseCallbacksImpl(
-      std::unique_ptr<WebIDBDatabaseCallbacks> callbacks);
-  ~IndexedDBDatabaseCallbacksImpl() override;
-
-  // mojom::blink::IDBDatabaseCallbacks implementation
-  void ForcedClose() override;
-  void VersionChange(int64_t old_version, int64_t new_version) override;
-  void Abort(int64_t transaction_id,
-             int32_t code,
-             const WTF::String& message) override;
-  void Complete(int64_t transaction_id) override;
-  void Changes(mojom::blink::IDBObserverChangesPtr changes) override;
-
- private:
-  std::unique_ptr<WebIDBDatabaseCallbacks> callbacks_;
-
-  DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseCallbacksImpl);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc
deleted file mode 100644
index 84198c4..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h"
-
-#include <utility>
-
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_observation.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h"
-
-namespace blink {
-// static
-IndexedDBDispatcher* IndexedDBDispatcher::GetInstanceForCurrentThread() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<IndexedDBDispatcher>,
-                                  thread_specific_instance, ());
-  return thread_specific_instance;
-}
-
-IndexedDBDispatcher::IndexedDBDispatcher() = default;
-
-// static
-void IndexedDBDispatcher::RegisterCursor(WebIDBCursorImpl* cursor) {
-  IndexedDBDispatcher* this_ptr = GetInstanceForCurrentThread();
-  DCHECK(!this_ptr->cursors_.Contains(cursor));
-  this_ptr->cursors_.insert(cursor);
-}
-
-// static
-void IndexedDBDispatcher::UnregisterCursor(WebIDBCursorImpl* cursor) {
-  IndexedDBDispatcher* this_ptr = GetInstanceForCurrentThread();
-  DCHECK(this_ptr->cursors_.Contains(cursor));
-  this_ptr->cursors_.erase(cursor);
-}
-
-// static
-void IndexedDBDispatcher::ResetCursorPrefetchCaches(
-    int64_t transaction_id,
-    WebIDBCursorImpl* except_cursor) {
-  IndexedDBDispatcher* this_ptr = GetInstanceForCurrentThread();
-  for (WebIDBCursorImpl* cursor : this_ptr->cursors_) {
-    if (cursor != except_cursor && cursor->transaction_id() == transaction_id)
-      cursor->ResetPrefetchCache();
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h
deleted file mode 100644
index 906d706..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_DISPATCHER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_DISPATCHER_H_
-
-#include <stdint.h>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
-
-namespace blink {
-class WebIDBCursorImpl;
-
-// Handle the indexed db related communication for this context thread - the
-// main thread and each worker thread have their own copies.
-class MODULES_EXPORT IndexedDBDispatcher {
- public:
-  static void RegisterCursor(WebIDBCursorImpl* cursor);
-  static void UnregisterCursor(WebIDBCursorImpl* cursor);
-
-  // Reset cursor prefetch caches for all cursors except |except_cursor|.
-  // In most callers, |except_cursor| is passed as nullptr, causing all cursors
-  // to have their prefetch cache to be reset.  In 2 WebIDBCursorImpl callers,
-  // specifically from |Advance| and |CursorContinue|, these want to reset all
-  // cursor prefetch caches except the cursor the calls are running from.  They
-  // get that behavior by passing |this| to |ResetCursorPrefetchCaches| which
-  // skips calling |ResetPrefetchCache| on them.
-  static void ResetCursorPrefetchCaches(int64_t transaction_id,
-                                        WebIDBCursorImpl* except_cursor);
-
- private:
-  friend class WTF::ThreadSpecific<IndexedDBDispatcher>;
-
-  static IndexedDBDispatcher* GetInstanceForCurrentThread();
-
-  IndexedDBDispatcher();
-
-  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
-  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
-
-  WTF::HashSet<WebIDBCursorImpl*> cursors_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_DISPATCHER_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.cc
deleted file mode 100644
index c0dcd1a..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.cc
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.h"
-
-#include "base/stl_util.h"
-#include "mojo/public/cpp/bindings/array_traits_web_vector.h"
-#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_mojom_traits.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/platform/mojo/string16_mojom_traits.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-using blink::mojom::IDBCursorDirection;
-using blink::mojom::IDBDataLoss;
-using blink::mojom::IDBOperationType;
-
-namespace mojo {
-
-// static
-bool StructTraits<
-    blink::mojom::IDBDatabaseMetadataDataView,
-    blink::WebIDBMetadata>::Read(blink::mojom::IDBDatabaseMetadataDataView data,
-                                 blink::WebIDBMetadata* out) {
-  out->id = data.id();
-  String name;
-  if (!data.ReadName(&name))
-    return false;
-  out->name = name;
-  out->version = data.version();
-  out->max_object_store_id = data.max_object_store_id();
-  if (!data.ReadObjectStores(&out->object_stores))
-    return false;
-  return true;
-}
-
-// static
-bool StructTraits<blink::mojom::IDBIndexKeysDataView, blink::WebIDBIndexKeys>::
-    Read(blink::mojom::IDBIndexKeysDataView data, blink::WebIDBIndexKeys* out) {
-  out->first = data.index_id();
-  if (!data.ReadIndexKeys(&out->second))
-    return false;
-  return true;
-}
-
-// static
-bool StructTraits<blink::mojom::IDBIndexMetadataDataView,
-                  blink::WebIDBMetadata::Index>::
-    Read(blink::mojom::IDBIndexMetadataDataView data,
-         blink::WebIDBMetadata::Index* out) {
-  out->id = data.id();
-  String name;
-  if (!data.ReadName(&name))
-    return false;
-  out->name = name;
-  if (!data.ReadKeyPath(&out->key_path))
-    return false;
-  out->unique = data.unique();
-  out->multi_entry = data.multi_entry();
-  return true;
-}
-
-// static
-blink::mojom::IDBKeyDataDataView::Tag
-UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::GetTag(
-    const blink::WebIDBKey& key) {
-  switch (key.View().KeyType()) {
-    case blink::kWebIDBKeyTypeInvalid:
-      return blink::mojom::IDBKeyDataDataView::Tag::OTHER;
-    case blink::kWebIDBKeyTypeArray:
-      return blink::mojom::IDBKeyDataDataView::Tag::KEY_ARRAY;
-    case blink::kWebIDBKeyTypeBinary:
-      return blink::mojom::IDBKeyDataDataView::Tag::BINARY;
-    case blink::kWebIDBKeyTypeString:
-      return blink::mojom::IDBKeyDataDataView::Tag::STRING;
-    case blink::kWebIDBKeyTypeDate:
-      return blink::mojom::IDBKeyDataDataView::Tag::DATE;
-    case blink::kWebIDBKeyTypeNumber:
-      return blink::mojom::IDBKeyDataDataView::Tag::NUMBER;
-    case blink::kWebIDBKeyTypeNull:
-      return blink::mojom::IDBKeyDataDataView::Tag::OTHER;
-    case blink::kWebIDBKeyTypeMin:
-      break;
-  }
-  NOTREACHED();
-  return blink::mojom::IDBKeyDataDataView::Tag::OTHER;
-}
-
-// static
-bool UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::Read(
-    blink::mojom::IDBKeyDataDataView data,
-    blink::WebIDBKey* out) {
-  switch (data.tag()) {
-    case blink::mojom::IDBKeyDataDataView::Tag::KEY_ARRAY: {
-      Vector<blink::WebIDBKey> array;
-      if (!data.ReadKeyArray(&array))
-        return false;
-      blink::WebVector<blink::WebIDBKey> webvector_array;
-      for (const auto& item : array) {
-        webvector_array.emplace_back(
-            blink::WebIDBKeyBuilder::Build(item.View()));
-      }
-      *out = blink::WebIDBKey::CreateArray(std::move(webvector_array));
-      return true;
-    }
-    case blink::mojom::IDBKeyDataDataView::Tag::BINARY: {
-      Vector<uint8_t> binary_vector;
-      if (!data.ReadBinary(&binary_vector))
-        return false;
-      std::string binary_string = std::string(
-          binary_vector.data(), binary_vector.data() + binary_vector.size());
-      *out = blink::WebIDBKey::CreateBinary(
-          blink::WebData(binary_string.c_str(), binary_string.length()));
-      return true;
-    }
-    case blink::mojom::IDBKeyDataDataView::Tag::STRING: {
-      String string;
-      if (!data.ReadString(&string))
-        return false;
-      *out = blink::WebIDBKey::CreateString(blink::WebString(string));
-      return true;
-    }
-    case blink::mojom::IDBKeyDataDataView::Tag::DATE:
-      *out = blink::WebIDBKey::CreateDate(data.date());
-      return true;
-    case blink::mojom::IDBKeyDataDataView::Tag::NUMBER:
-      *out = blink::WebIDBKey::CreateNumber(data.number());
-      return true;
-    case blink::mojom::IDBKeyDataDataView::Tag::OTHER:
-      switch (data.other()) {
-        case blink::mojom::IDBDatalessKeyType::Invalid:
-          *out = blink::WebIDBKey::CreateInvalid();
-          return true;
-        case blink::mojom::IDBDatalessKeyType::Null:
-          *out = blink::WebIDBKey::CreateNull();
-          return true;
-      }
-  }
-
-  return false;
-}
-
-// static
-const blink::WebVector<blink::WebIDBKey>
-UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::key_array(
-    const blink::WebIDBKey& key) {
-  const auto& array_view = key.View().ArrayView();
-  const size_t array_size = array_view.size();
-  Vector<blink::WebIDBKey> result;
-  result.ReserveInitialCapacity(array_view.size());
-  for (size_t i = 0; i < array_size; ++i)
-    result.emplace_back(blink::WebIDBKeyBuilder::Build(array_view[i]));
-  return result;
-}
-
-// static
-const Vector<uint8_t>
-UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::binary(
-    const blink::WebIDBKey& key) {
-  const auto& data_view = key.View().Binary().Copy();
-  const size_t data_size = data_view.size();
-  Vector<uint8_t> result;
-  result.ReserveInitialCapacity(data_size);
-  for (const auto& item : data_view)
-    result.push_back(item);
-  return result;
-}
-
-// static
-const blink::WebIDBKey&
-StructTraits<blink::mojom::IDBKeyDataView, blink::WebIDBKey>::data(
-    const blink::WebIDBKey& key) {
-  return key;
-}
-
-// static
-bool StructTraits<blink::mojom::IDBKeyDataView, blink::WebIDBKey>::Read(
-    blink::mojom::IDBKeyDataView data,
-    blink::WebIDBKey* out) {
-  return data.ReadData(out);
-}
-
-// static
-blink::mojom::blink::IDBKeyPathDataPtr
-StructTraits<blink::mojom::IDBKeyPathDataView, blink::WebIDBKeyPath>::data(
-    const blink::WebIDBKeyPath& key_path) {
-  if (key_path.KeyPathType() == blink::kWebIDBKeyPathTypeNull)
-    return nullptr;
-
-  auto data = blink::mojom::blink::IDBKeyPathData::New();
-  switch (key_path.KeyPathType()) {
-    case blink::kWebIDBKeyPathTypeString: {
-      String key_path_string = key_path.String();
-      if (key_path_string.IsNull())
-        key_path_string = "";
-      data->set_string(key_path_string);
-      return data;
-    }
-    case blink::kWebIDBKeyPathTypeArray: {
-      const auto& array = key_path.Array();
-      const size_t array_size = array.size();
-      Vector<String> result;
-      result.ReserveInitialCapacity(array_size);
-      for (const auto& item : array)
-        result.push_back(item);
-      data->set_string_array(result);
-      return data;
-    }
-
-    case blink::kWebIDBKeyPathTypeNull:
-      break;  // Not used, NOTREACHED.
-  }
-  NOTREACHED();
-  return data;
-}
-
-// static
-bool StructTraits<blink::mojom::IDBKeyPathDataView, blink::WebIDBKeyPath>::Read(
-    blink::mojom::IDBKeyPathDataView data,
-    blink::WebIDBKeyPath* out) {
-  blink::mojom::IDBKeyPathDataDataView data_view;
-  data.GetDataDataView(&data_view);
-
-  if (data_view.is_null()) {
-    *out = blink::WebIDBKeyPath();
-    return true;
-  }
-
-  switch (data_view.tag()) {
-    case blink::mojom::IDBKeyPathDataDataView::Tag::STRING: {
-      String string;
-      if (!data_view.ReadString(&string))
-        return false;
-      *out = blink::WebIDBKeyPath(blink::WebString(string));
-      return true;
-    }
-    case blink::mojom::IDBKeyPathDataDataView::Tag::STRING_ARRAY: {
-      Vector<String> array;
-      if (!data_view.ReadStringArray(&array))
-        return false;
-      *out = blink::WebIDBKeyPath(array);
-      return true;
-    }
-  }
-
-  return false;
-}
-
-// static
-bool StructTraits<blink::mojom::IDBKeyRangeDataView, blink::WebIDBKeyRange>::
-    Read(blink::mojom::IDBKeyRangeDataView data, blink::WebIDBKeyRange* out) {
-  // TODO(cmp): Use WebIDBKey and WebIDBKeyRange directly.
-  blink::IndexedDBKey lower;
-  blink::IndexedDBKey upper;
-  if (!data.ReadLower(&lower) || !data.ReadUpper(&upper))
-    return false;
-
-  blink::IndexedDBKeyRange temp(lower, upper, data.lower_open(),
-                                data.upper_open());
-  *out = blink::WebIDBKeyRangeBuilder::Build(temp);
-  return true;
-}
-
-// static
-bool StructTraits<blink::mojom::IDBObjectStoreMetadataDataView,
-                  blink::WebIDBMetadata::ObjectStore>::
-    Read(blink::mojom::IDBObjectStoreMetadataDataView data,
-         blink::WebIDBMetadata::ObjectStore* out) {
-  out->id = data.id();
-  String name;
-  if (!data.ReadName(&name))
-    return false;
-  out->name = name;
-  if (!data.ReadKeyPath(&out->key_path))
-    return false;
-  out->auto_increment = data.auto_increment();
-  out->max_index_id = data.max_index_id();
-  if (!data.ReadIndexes(&out->indexes))
-    return false;
-  return true;
-}
-
-}  // namespace mojo
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.h
deleted file mode 100644
index 3cacae4..0000000
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_mojom_traits.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_MOJOM_TRAITS_H_
-
-#include <stdint.h>
-
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace mojo {
-
-template <>
-struct MODULES_EXPORT StructTraits<blink::mojom::IDBDatabaseMetadataDataView,
-                                   blink::WebIDBMetadata> {
-  static int64_t id(const blink::WebIDBMetadata& metadata) {
-    return metadata.id;
-  }
-  static WTF::String name(const blink::WebIDBMetadata& metadata) {
-    if (metadata.name.IsNull())
-      return g_empty_string;
-    return metadata.name;
-  }
-  static int64_t version(const blink::WebIDBMetadata& metadata) {
-    return metadata.version;
-  }
-  static int64_t max_object_store_id(const blink::WebIDBMetadata& metadata) {
-    return metadata.max_object_store_id;
-  }
-  static const blink::WebVector<blink::WebIDBMetadata::ObjectStore>&
-  object_stores(const blink::WebIDBMetadata& metadata) {
-    return metadata.object_stores;
-  }
-  static bool Read(blink::mojom::IDBDatabaseMetadataDataView data,
-                   blink::WebIDBMetadata* out);
-};
-
-template <>
-struct MODULES_EXPORT
-    StructTraits<blink::mojom::IDBIndexKeysDataView, blink::WebIDBIndexKeys> {
-  static int64_t index_id(const blink::WebIDBIndexKeys& index_keys) {
-    return index_keys.first;
-  }
-  static const blink::WebVector<blink::WebIDBKey>& index_keys(
-      const blink::WebIDBIndexKeys& index_keys) {
-    return index_keys.second;
-  }
-  static bool Read(blink::mojom::IDBIndexKeysDataView data,
-                   blink::WebIDBIndexKeys* out);
-};
-
-template <>
-struct MODULES_EXPORT StructTraits<blink::mojom::IDBIndexMetadataDataView,
-                                   blink::WebIDBMetadata::Index> {
-  static int64_t id(const blink::WebIDBMetadata::Index& metadata) {
-    return metadata.id;
-  }
-  static WTF::String name(const blink::WebIDBMetadata::Index& metadata) {
-    if (metadata.name.IsNull())
-      return g_empty_string;
-    return metadata.name;
-  }
-  static const blink::WebIDBKeyPath& key_path(
-      const blink::WebIDBMetadata::Index& metadata) {
-    return metadata.key_path;
-  }
-  static bool unique(const blink::WebIDBMetadata::Index& metadata) {
-    return metadata.unique;
-  }
-  static bool multi_entry(const blink::WebIDBMetadata::Index& metadata) {
-    return metadata.multi_entry;
-  }
-  static bool Read(blink::mojom::IDBIndexMetadataDataView data,
-                   blink::WebIDBMetadata::Index* out);
-};
-
-template <>
-struct MODULES_EXPORT
-    UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey> {
-  static blink::mojom::IDBKeyDataDataView::Tag GetTag(
-      const blink::WebIDBKey& key);
-  static bool Read(blink::mojom::IDBKeyDataDataView data,
-                   blink::WebIDBKey* out);
-  static const blink::WebVector<blink::WebIDBKey> key_array(
-      const blink::WebIDBKey& key);
-  static const Vector<uint8_t> binary(const blink::WebIDBKey& key);
-  static const WTF::String string(const blink::WebIDBKey& key) {
-    String key_string = key.View().String();
-    if (key_string.IsNull())
-      key_string = g_empty_string;
-    return key_string;
-  }
-  static double date(const blink::WebIDBKey& key) { return key.View().Date(); }
-  static double number(const blink::WebIDBKey& key) {
-    return key.View().Number();
-  }
-  static blink::mojom::IDBDatalessKeyType other(const blink::WebIDBKey& key) {
-    switch (key.View().KeyType()) {
-      case blink::kWebIDBKeyTypeInvalid:
-        return blink::mojom::IDBDatalessKeyType::Invalid;
-      case blink::kWebIDBKeyTypeNull:
-        return blink::mojom::IDBDatalessKeyType::Null;
-      default:
-        NOTREACHED();
-        return blink::mojom::IDBDatalessKeyType::Invalid;
-    }
-  }
-};
-
-template <>
-struct MODULES_EXPORT
-    StructTraits<blink::mojom::IDBKeyDataView, blink::WebIDBKey> {
-  static const blink::WebIDBKey& data(const blink::WebIDBKey& key);
-  static bool Read(blink::mojom::IDBKeyDataView data, blink::WebIDBKey* out);
-};
-
-template <>
-struct MODULES_EXPORT
-    StructTraits<blink::mojom::IDBKeyPathDataView, blink::WebIDBKeyPath> {
-  static blink::mojom::blink::IDBKeyPathDataPtr data(
-      const blink::WebIDBKeyPath& key_path);
-  static bool Read(blink::mojom::IDBKeyPathDataView data,
-                   blink::WebIDBKeyPath* out);
-};
-
-template <>
-struct MODULES_EXPORT
-    StructTraits<blink::mojom::IDBKeyRangeDataView, blink::WebIDBKeyRange> {
-  static blink::WebIDBKey lower(const blink::WebIDBKeyRange& key_range) {
-    return blink::WebIDBKeyBuilder::Build(key_range.Lower());
-  }
-  static blink::WebIDBKey upper(const blink::WebIDBKeyRange& key_range) {
-    return blink::WebIDBKeyBuilder::Build(key_range.Upper());
-  }
-  static bool lower_open(const blink::WebIDBKeyRange& key_range) {
-    return key_range.LowerOpen();
-  }
-  static bool upper_open(const blink::WebIDBKeyRange& key_range) {
-    return key_range.UpperOpen();
-  }
-  static bool Read(blink::mojom::IDBKeyRangeDataView data,
-                   blink::WebIDBKeyRange* out);
-};
-
-template <>
-struct MODULES_EXPORT StructTraits<blink::mojom::IDBObjectStoreMetadataDataView,
-                                   blink::WebIDBMetadata::ObjectStore> {
-  static int64_t id(const blink::WebIDBMetadata::ObjectStore& metadata) {
-    return metadata.id;
-  }
-  static WTF::String name(const blink::WebIDBMetadata::ObjectStore& metadata) {
-    return metadata.name;
-  }
-  static const blink::WebIDBKeyPath& key_path(
-      const blink::WebIDBMetadata::ObjectStore& metadata) {
-    return metadata.key_path;
-  }
-  static bool auto_increment(
-      const blink::WebIDBMetadata::ObjectStore& metadata) {
-    return metadata.auto_increment;
-  }
-  static int64_t max_index_id(
-      const blink::WebIDBMetadata::ObjectStore& metadata) {
-    return metadata.max_index_id;
-  }
-  static const blink::WebVector<blink::WebIDBMetadata::Index>& indexes(
-      const blink::WebIDBMetadata::ObjectStore& metadata) {
-    return metadata.indexes;
-  }
-  static bool Read(blink::mojom::IDBObjectStoreMetadataDataView data,
-                   blink::WebIDBMetadata::ObjectStore* out);
-};
-
-}  // namespace mojo
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_MOJOM_TRAITS_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
index 44fbbba..00ff718 100644
--- a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
+++ b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
@@ -34,6 +34,7 @@
 #include <utility>
 
 #include "third_party/blink/public/common/indexeddb/web_idb_types.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -58,7 +59,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
index c38507f..a7325498 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
@@ -7,10 +7,10 @@
 
 #include <gmock/gmock.h>
 #include <memory>
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 
 namespace blink {
 
@@ -23,7 +23,7 @@
   MOCK_METHOD5(CreateObjectStore,
                void(long long transaction_id,
                     long long object_store_id,
-                    const String& name,
+                    const WebString& name,
                     const WebIDBKeyPath&,
                     bool auto_increment));
   MOCK_METHOD2(DeleteObjectStore,
@@ -31,10 +31,10 @@
   MOCK_METHOD3(RenameObjectStore,
                void(long long transaction_id,
                     long long object_store_id,
-                    const String& new_name));
+                    const WebString& new_name));
   MOCK_METHOD3(CreateTransaction,
                void(long long id,
-                    const Vector<int64_t>& scope,
+                    const WebVector<long long>& scope,
                     WebIDBTransactionMode));
   MOCK_METHOD0(Close, void());
   MOCK_METHOD0(VersionChangeIgnored, void());
@@ -44,7 +44,7 @@
                void(long long transaction_id,
                     long long object_store_id,
                     long long index_id,
-                    const String& name,
+                    const WebString& name,
                     const WebIDBKeyPath&,
                     bool unique,
                     bool multi_entry));
@@ -56,7 +56,7 @@
                void(long long transaction_id,
                     long long object_store_id,
                     long long index_id,
-                    const String& new_name));
+                    const WebString& new_name));
   MOCK_METHOD6(
       AddObserver,
       void(long long transaction_id,
@@ -67,7 +67,7 @@
            const std::bitset<kWebIDBOperationTypeCount>& operation_types));
   MOCK_CONST_METHOD1(ContainsObserverId, bool(int32_t id));
   MOCK_METHOD1(RemoveObservers,
-               void(const Vector<int32_t>& observer_ids_to_remove));
+               void(const WebVector<int32_t>& observer_ids_to_remove));
   MOCK_METHOD6(Get,
                void(long long transaction_id,
                     long long object_store_id,
@@ -88,21 +88,21 @@
                void(long long transaction_id,
                     long long object_store_id,
                     const WebData& value,
-                    const Vector<WebBlobInfo>&,
+                    const WebVector<WebBlobInfo>&,
                     WebIDBKeyView primary_key,
                     WebIDBPutMode,
                     WebIDBCallbacks*,
-                    const Vector<WebIDBIndexKeys>&));
+                    const WebVector<WebIDBIndexKeys>&));
 
   MOCK_METHOD4(SetIndexKeys,
                void(long long transaction_id,
                     long long object_store_id,
                     WebIDBKeyView primary_key,
-                    const Vector<WebIDBIndexKeys>&));
+                    const WebVector<WebIDBIndexKeys>&));
   MOCK_METHOD3(SetIndexesReady,
                void(long long transaction_id,
                     long long object_store_id,
-                    const Vector<int64_t>& index_ids));
+                    const WebVector<long long>& index_ids));
   MOCK_METHOD8(OpenCursor,
                void(long long transaction_id,
                     long long object_store_id,
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
index 47ffe2f..83c890d 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
@@ -9,9 +9,9 @@
 #include <memory>
 
 #include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory.h"
 
 namespace base {
 class SingleThreadTaskRunner;
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
index 6fb6626..34f3c12 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
@@ -31,6 +31,8 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
+#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_name_and_version.h"
@@ -41,8 +43,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
deleted file mode 100644
index f9b04bee..0000000
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_IMPL_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_callbacks.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class IndexedDBCallbacksImpl;
-
-class MODULES_EXPORT WebIDBCursorImpl : public WebIDBCursor {
- public:
-  WebIDBCursorImpl(mojom::blink::IDBCursorAssociatedPtrInfo cursor,
-                   int64_t transaction_id);
-  ~WebIDBCursorImpl() override;
-
-  void Advance(unsigned long count, WebIDBCallbacks* callback) override;
-  void CursorContinue(WebIDBKeyView key,
-                      WebIDBKeyView primary_key,
-                      WebIDBCallbacks* callback) override;
-  void PostSuccessHandlerCallback() override;
-
-  void SetPrefetchData(Vector<WebIDBKey> keys,
-                       Vector<WebIDBKey> primary_keys,
-                       Vector<WebIDBValue> values);
-
-  void CachedAdvance(unsigned long count, WebIDBCallbacks* callbacks);
-  void CachedContinue(WebIDBCallbacks* callbacks);
-
-  // This method is virtual so it can be overridden in unit tests.
-  virtual void ResetPrefetchCache();
-
-  int64_t transaction_id() const { return transaction_id_; }
-
- private:
-  mojom::blink::IDBCallbacksAssociatedPtrInfo GetCallbacksProxy(
-      std::unique_ptr<IndexedDBCallbacksImpl> callbacks);
-
-  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorReset);
-  FRIEND_TEST_ALL_PREFIXES(IndexedDBDispatcherTest, CursorTransactionId);
-  FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, AdvancePrefetchTest);
-  FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchReset);
-  FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
-
-  static constexpr int kPrefetchContinueThreshold = 2;
-  static constexpr int kMinPrefetchAmount = 5;
-  static constexpr int kMaxPrefetchAmount = 100;
-
-  int64_t transaction_id_;
-
-  mojom::blink::IDBCursorAssociatedPtr cursor_;
-
-  // Prefetch cache. Keys and values are stored in reverse order so that a
-  // cache'd continue can pop a value off of the back and prevent new memory
-  // allocations.
-  Vector<WebIDBKey> prefetch_keys_;
-  Vector<WebIDBKey> prefetch_primary_keys_;
-  Vector<WebIDBValue> prefetch_values_;
-
-  // Number of continue calls that would qualify for a pre-fetch.
-  int continue_count_;
-
-  // Number of items used from the last prefetch.
-  int used_prefetches_;
-
-  // Number of onsuccess handlers we are waiting for.
-  int pending_onsuccess_callbacks_;
-
-  // Number of items to request in next prefetch.
-  int prefetch_amount_;
-
-  base::WeakPtrFactory<WebIDBCursorImpl> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImpl);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_CURSOR_IMPL_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc
deleted file mode 100644
index af94537..0000000
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "base/format_macros.h"
-#include "base/memory/ptr_util.h"
-#include "mojo/public/cpp/bindings/strong_associated_binding.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/modules/indexeddb/indexed_db_key_builder.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_error.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_path.h"
-#include "third_party/blink/public/platform/modules/indexeddb/web_idb_metadata.h"
-#include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
-#include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h"
-
-namespace blink {
-
-WebIDBDatabaseImpl::WebIDBDatabaseImpl(
-    mojom::blink::IDBDatabaseAssociatedPtrInfo database_info)
-    : database_(std::move(database_info)) {}
-
-WebIDBDatabaseImpl::~WebIDBDatabaseImpl() = default;
-
-void WebIDBDatabaseImpl::CreateObjectStore(long long transaction_id,
-                                           long long object_store_id,
-                                           const String& name,
-                                           const WebIDBKeyPath& key_path,
-                                           bool auto_increment) {
-  database_->CreateObjectStore(transaction_id, object_store_id, name, key_path,
-                               auto_increment);
-}
-
-void WebIDBDatabaseImpl::DeleteObjectStore(long long transaction_id,
-                                           long long object_store_id) {
-  database_->DeleteObjectStore(transaction_id, object_store_id);
-}
-
-void WebIDBDatabaseImpl::RenameObjectStore(long long transaction_id,
-                                           long long object_store_id,
-                                           const String& new_name) {
-  database_->RenameObjectStore(transaction_id, object_store_id, new_name);
-}
-
-void WebIDBDatabaseImpl::CreateTransaction(
-    long long transaction_id,
-    const Vector<int64_t>& object_store_ids,
-    WebIDBTransactionMode mode) {
-  database_->CreateTransaction(transaction_id, object_store_ids, mode);
-}
-
-void WebIDBDatabaseImpl::Close() {
-  database_->Close();
-}
-
-void WebIDBDatabaseImpl::VersionChangeIgnored() {
-  database_->VersionChangeIgnored();
-}
-
-void WebIDBDatabaseImpl::AddObserver(
-    long long transaction_id,
-    int32_t observer_id,
-    bool include_transaction,
-    bool no_records,
-    bool values,
-    const std::bitset<kWebIDBOperationTypeCount>& operation_types) {
-  static_assert(kWebIDBOperationTypeCount < sizeof(uint16_t) * CHAR_BIT,
-                "WebIDBOperationType Count exceeds size of uint16_t");
-  database_->AddObserver(transaction_id, observer_id, include_transaction,
-                         no_records, values, operation_types.to_ulong());
-}
-
-void WebIDBDatabaseImpl::RemoveObservers(const Vector<int32_t>& observer_ids) {
-  database_->RemoveObservers(observer_ids);
-}
-
-void WebIDBDatabaseImpl::Get(long long transaction_id,
-                             long long object_store_id,
-                             long long index_id,
-                             const WebIDBKeyRange& key_range,
-                             bool key_only,
-                             WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->Get(transaction_id, object_store_id, index_id, key_range, key_only,
-                 GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::GetAll(long long transaction_id,
-                                long long object_store_id,
-                                long long index_id,
-                                const WebIDBKeyRange& key_range,
-                                long long max_count,
-                                bool key_only,
-                                WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->GetAll(transaction_id, object_store_id, index_id, key_range,
-                    key_only, max_count,
-                    GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::Put(long long transaction_id,
-                             long long object_store_id,
-                             const WebData& value,
-                             const Vector<WebBlobInfo>& web_blob_info,
-                             WebIDBKeyView web_primary_key,
-                             WebIDBPutMode put_mode,
-                             WebIDBCallbacks* callbacks,
-                             const Vector<WebIDBIndexKeys>& index_keys) {
-  WebIDBKey key = WebIDBKeyBuilder::Build(web_primary_key);
-
-  if (value.size() + key.SizeEstimate() > max_put_value_size_) {
-    callbacks->OnError(WebIDBDatabaseError(
-        kWebIDBDatabaseExceptionUnknownError,
-        WebString(String::Format("The serialized value is too large"
-                                 " (size=%" PRIuS " bytes, max=%" PRIuS
-                                 " bytes).",
-                                 value.size(), max_put_value_size_))));
-    return;
-  }
-
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto mojo_value = mojom::blink::IDBValue::New();
-  DCHECK(mojo_value->bits.IsEmpty());
-  value.ForEachSegment([&mojo_value](const char* segment, size_t segment_size,
-                                     size_t segment_offset) {
-    mojo_value->bits.append(String(segment, segment_size));
-    return true;
-  });
-  mojo_value->blob_or_file_info.ReserveInitialCapacity(web_blob_info.size());
-  for (const WebBlobInfo& info : web_blob_info) {
-    auto blob_info = mojom::blink::IDBBlobInfo::New();
-    if (info.IsFile()) {
-      blob_info->file = mojom::blink::IDBFileInfo::New();
-      blob_info->file->path = WebStringToFilePath(info.FilePath());
-      String name = info.FileName();
-      if (name.IsNull())
-        name = g_empty_string;
-      blob_info->file->name = name;
-      blob_info->file->last_modified =
-          base::Time::FromDoubleT(info.LastModified());
-    }
-    blob_info->size = info.size();
-    blob_info->uuid = info.Uuid();
-    DCHECK(!blob_info->uuid.IsEmpty());
-    String mime_type = info.GetType();
-    if (mime_type.IsNull())
-      mime_type = g_empty_string;
-    blob_info->mime_type = mime_type;
-    blob_info->blob = mojom::blink::BlobPtrInfo(info.CloneBlobHandle(),
-                                                mojom::blink::Blob::Version_);
-    mojo_value->blob_or_file_info.push_back(std::move(blob_info));
-  }
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->Put(transaction_id, object_store_id, std::move(mojo_value),
-                 std::move(key), put_mode, std::move(index_keys),
-                 GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::SetIndexKeys(
-    long long transaction_id,
-    long long object_store_id,
-    WebIDBKeyView primary_key,
-    const Vector<WebIDBIndexKeys>& index_keys) {
-  IndexedDBKey temp(IndexedDBKeyBuilder::Build(primary_key));
-  database_->SetIndexKeys(transaction_id, object_store_id,
-                          WebIDBKeyBuilder::Build(temp), std::move(index_keys));
-}
-
-void WebIDBDatabaseImpl::SetIndexesReady(long long transaction_id,
-                                         long long object_store_id,
-                                         const Vector<int64_t>& index_ids) {
-  database_->SetIndexesReady(transaction_id, object_store_id,
-                             std::move(index_ids));
-}
-
-void WebIDBDatabaseImpl::OpenCursor(long long transaction_id,
-                                    long long object_store_id,
-                                    long long index_id,
-                                    const WebIDBKeyRange& key_range,
-                                    WebIDBCursorDirection direction,
-                                    bool key_only,
-                                    WebIDBTaskType task_type,
-                                    WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->OpenCursor(transaction_id, object_store_id, index_id, key_range,
-                        direction, key_only, task_type,
-                        GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::Count(long long transaction_id,
-                               long long object_store_id,
-                               long long index_id,
-                               const WebIDBKeyRange& key_range,
-                               WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->Count(transaction_id, object_store_id, index_id, key_range,
-                   GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::Delete(long long transaction_id,
-                                long long object_store_id,
-                                WebIDBKeyView primary_key,
-                                WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->DeleteRange(transaction_id, object_store_id,
-                         WebIDBKeyRangeBuilder::Build(primary_key),
-                         GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::DeleteRange(long long transaction_id,
-                                     long long object_store_id,
-                                     const WebIDBKeyRange& key_range,
-                                     WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->DeleteRange(transaction_id, object_store_id, key_range,
-                         GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::Clear(long long transaction_id,
-                               long long object_store_id,
-                               WebIDBCallbacks* callbacks) {
-  IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr);
-
-  auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
-      base::WrapUnique(callbacks), transaction_id, nullptr);
-  database_->Clear(transaction_id, object_store_id,
-                   GetCallbacksProxy(std::move(callbacks_impl)));
-}
-
-void WebIDBDatabaseImpl::CreateIndex(long long transaction_id,
-                                     long long object_store_id,
-                                     long long index_id,
-                                     const String& name,
-                                     const WebIDBKeyPath& key_path,
-                                     bool unique,
-                                     bool multi_entry) {
-  database_->CreateIndex(transaction_id, object_store_id, index_id, name,
-                         key_path, unique, multi_entry);
-}
-
-void WebIDBDatabaseImpl::DeleteIndex(long long transaction_id,
-                                     long long object_store_id,
-                                     long long index_id) {
-  database_->DeleteIndex(transaction_id, object_store_id, index_id);
-}
-
-void WebIDBDatabaseImpl::RenameIndex(long long transaction_id,
-                                     long long object_store_id,
-                                     long long index_id,
-                                     const String& new_name) {
-  DCHECK(!new_name.IsNull());
-  database_->RenameIndex(transaction_id, object_store_id, index_id, new_name);
-}
-
-void WebIDBDatabaseImpl::Abort(long long transaction_id) {
-  database_->Abort(transaction_id);
-}
-
-void WebIDBDatabaseImpl::Commit(long long transaction_id) {
-  database_->Commit(transaction_id);
-}
-
-mojom::blink::IDBCallbacksAssociatedPtrInfo
-WebIDBDatabaseImpl::GetCallbacksProxy(
-    std::unique_ptr<IndexedDBCallbacksImpl> callbacks) {
-  mojom::blink::IDBCallbacksAssociatedPtrInfo ptr_info;
-  auto request = mojo::MakeRequest(&ptr_info);
-  mojo::MakeStrongAssociatedBinding(std::move(callbacks), std::move(request));
-  return ptr_info;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc
deleted file mode 100644
index a960ec61..0000000
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/public/platform/web_data.h"
-#include "third_party/blink/public/web/web_heap.h"
-#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h"
-#include "third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h"
-
-using testing::_;
-using testing::Invoke;
-using testing::StrictMock;
-using testing::WithArgs;
-
-namespace blink {
-
-class WebIDBDatabaseImplTest : public testing::Test {};
-
-TEST_F(WebIDBDatabaseImplTest, ValueSizeTest) {
-  // For testing use a much smaller maximum size to prevent allocating >100 MB
-  // of memory, which crashes on memory-constrained systems.
-  const size_t kMaxValueSizeForTesting = 10 * 1024 * 1024;  // 10 MB
-
-  const std::vector<char> data(kMaxValueSizeForTesting + 1);
-  const WebData value(&data.front(), data.size());
-  const Vector<WebBlobInfo> blob_info;
-  const WebIDBKey key = WebIDBKey::CreateNumber(0);
-  const int64_t transaction_id = 1;
-  const int64_t object_store_id = 2;
-  StrictMock<MockWebIDBCallbacks> callbacks;
-
-  ASSERT_GT(value.size() + key.SizeEstimate(), kMaxValueSizeForTesting);
-  ThreadState::Current()->CollectAllGarbage();
-  EXPECT_CALL(callbacks, OnError(_)).Times(1);
-
-  WebIDBDatabaseImpl database_impl(nullptr);
-  database_impl.max_put_value_size_ = kMaxValueSizeForTesting;
-  database_impl.Put(transaction_id, object_store_id, value, blob_info,
-                    key.View(), blink::kWebIDBPutModeAddOrUpdate, &callbacks,
-                    Vector<blink::WebIDBIndexKeys>());
-}
-
-TEST_F(WebIDBDatabaseImplTest, KeyAndValueSizeTest) {
-  // For testing use a much smaller maximum size to prevent allocating >100 MB
-  // of memory, which crashes on memory-constrained systems.
-  const size_t kMaxValueSizeForTesting = 10 * 1024 * 1024;  // 10 MB
-  const size_t kKeySize = 1024 * 1024;
-
-  const std::vector<char> data(kMaxValueSizeForTesting - kKeySize);
-  const WebData value(&data.front(), data.size());
-  const Vector<WebBlobInfo> blob_info;
-  const int64_t transaction_id = 1;
-  const int64_t object_store_id = 2;
-  StrictMock<MockWebIDBCallbacks> callbacks;
-
-  // For this test, we want IDBKey::SizeEstimate() minus kKeySize to be the
-  // smallest value > 0.  An IDBKey with a string has a size_estimate_ equal to
-  // kOverheadSize (~16) + (string.length * sizeof(UChar)).  Create
-  // |kKeySize / sizeof(UChar)| characters in String.
-  const unsigned int number_of_chars = kKeySize / sizeof(UChar);
-  Vector<UChar> key_string_vector;
-  key_string_vector.ReserveInitialCapacity(number_of_chars);
-  key_string_vector.Fill(u'0', number_of_chars);
-  String key_string(key_string_vector);
-  DCHECK_EQ(key_string.length(), number_of_chars);
-
-  WebIDBKey key = WebIDBKey::CreateString(key_string);
-  DCHECK_EQ(value.size(), kMaxValueSizeForTesting - kKeySize);
-  DCHECK_GT(key.SizeEstimate() - kKeySize, static_cast<unsigned long>(0));
-  DCHECK_GT(value.size() + key.SizeEstimate(), kMaxValueSizeForTesting);
-
-  ThreadState::Current()->CollectAllGarbage();
-  EXPECT_CALL(callbacks, OnError(_)).Times(1);
-
-  WebIDBDatabaseImpl database_impl(nullptr);
-  database_impl.max_put_value_size_ = kMaxValueSizeForTesting;
-  database_impl.Put(transaction_id, object_store_id, value, blob_info,
-                    key.View(), blink::kWebIDBPutModeAddOrUpdate, &callbacks,
-                    Vector<blink::WebIDBIndexKeys>());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/BUILD.gn b/third_party/blink/renderer/modules/media_controls/BUILD.gn
index 0517d28d..4ab9dd5 100644
--- a/third_party/blink/renderer/modules/media_controls/BUILD.gn
+++ b/third_party/blink/renderer/modules/media_controls/BUILD.gn
@@ -15,6 +15,8 @@
     "elements/media_control_button_panel_element.h",
     "elements/media_control_cast_button_element.cc",
     "elements/media_control_cast_button_element.h",
+    "elements/media_control_consts.cc",
+    "elements/media_control_consts.h",
     "elements/media_control_current_time_display_element.cc",
     "elements/media_control_current_time_display_element.h",
     "elements/media_control_display_cutout_fullscreen_button_element.cc",
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_consts.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_consts.cc
new file mode 100644
index 0000000..4941a77f
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_consts.cc
@@ -0,0 +1,11 @@
+// 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 "third_party/blink/renderer/modules/media_controls/elements/media_control_consts.h"
+
+namespace blink {
+
+const char kClosedCSSClass[] = "closed";
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_consts.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_consts.h
new file mode 100644
index 0000000..d1a8577
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_consts.h
@@ -0,0 +1,14 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_CONSTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_CONSTS_H_
+
+namespace blink {
+
+extern const char kClosedCSSClass[];
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_CONSTS_H_
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc
index cb7d4e6..f92fbaf8 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc
@@ -6,7 +6,9 @@
 
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/dom_token_list.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/modules/media_controls/elements/media_control_consts.h"
 #include "third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.h"
 #include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
 #include "third_party/blink/renderer/platform/histogram.h"
@@ -18,6 +20,15 @@
     : MediaControlPopupMenuElement(media_controls, kMediaOverflowList) {
   SetShadowPseudoId(
       AtomicString("-internal-media-controls-overflow-menu-list"));
+  CloseOverflowMenu();
+}
+
+void MediaControlOverflowMenuListElement::OpenOverflowMenu() {
+  classList().Remove(kClosedCSSClass);
+}
+
+void MediaControlOverflowMenuListElement::CloseOverflowMenu() {
+  classList().Add(kClosedCSSClass);
 }
 
 void MediaControlOverflowMenuListElement::MaybeRecordTimeTaken(
@@ -47,6 +58,11 @@
 void MediaControlOverflowMenuListElement::SetIsWanted(bool wanted) {
   MediaControlPopupMenuElement::SetIsWanted(wanted);
 
+  if (wanted)
+    OpenOverflowMenu();
+  else if (!GetMediaControls().TextTrackListIsWanted())
+    CloseOverflowMenu();
+
   // Record the time the overflow menu was shown to a histogram.
   if (wanted) {
     DCHECK(!time_shown_);
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h
index 4da049d..a9b23f7c0 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h
@@ -21,6 +21,9 @@
  public:
   explicit MediaControlOverflowMenuListElement(MediaControlsImpl&);
 
+  void OpenOverflowMenu();
+  void CloseOverflowMenu();
+
   // Override MediaControlPopupMenuElement
   void SetIsWanted(bool) final;
   Element* PopupAnchor() const final;
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
index cdd7036..8f04c6ac 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
@@ -63,6 +63,9 @@
   if (wanted)
     RefreshTextTrackListMenu();
 
+  if (!wanted && !GetMediaControls().OverflowMenuIsWanted())
+    GetMediaControls().CloseOverflowMenu();
+
   MediaControlPopupMenuElement::SetIsWanted(wanted);
 }
 
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
index d4f0e31..a8693de 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
@@ -10,17 +10,12 @@
 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/modules/media_controls/elements/media_control_consts.h"
 #include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
 #include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
 
 namespace blink {
 
-namespace {
-
-const char kClosedCSSClass[] = "closed";
-
-}  // anonymous namespace
-
 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(
     MediaControlsImpl& media_controls)
     : MediaControlSliderElement(media_controls, kMediaVolumeSlider) {
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc b/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
index 76f544a..eacec448 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
@@ -1155,6 +1155,10 @@
   }
 }
 
+bool MediaControlsImpl::TextTrackListIsWanted() {
+  return text_track_list_->IsWanted();
+}
+
 String MediaControlsImpl::GetTextTrackLabel(TextTrack* track) const {
   if (!track) {
     return MediaElement().GetLocale().QueryString(
@@ -2099,6 +2103,18 @@
   UpdateCSSClassFromState();
 }
 
+void MediaControlsImpl::OpenOverflowMenu() {
+  overflow_list_->OpenOverflowMenu();
+}
+
+void MediaControlsImpl::CloseOverflowMenu() {
+  overflow_list_->CloseOverflowMenu();
+}
+
+bool MediaControlsImpl::OverflowMenuIsWanted() {
+  return overflow_list_->IsWanted();
+}
+
 bool MediaControlsImpl::OverflowMenuVisible() {
   return overflow_list_ ? overflow_list_->IsWanted() : false;
 }
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl.h b/third_party/blink/renderer/modules/media_controls/media_controls_impl.h
index 53e85b7..43f3a294 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_impl.h
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl.h
@@ -128,12 +128,17 @@
   void ToggleTextTrackList();
   void ShowTextTrackAtIndex(unsigned);
   void DisableShowingTextTracks();
+  bool TextTrackListIsWanted();
 
   // Returns the label for the track when a valid track is passed in and "Off"
   // when the parameter is null.
   String GetTextTrackLabel(TextTrack*) const;
 
   // Methods related to the overflow menu.
+  void OpenOverflowMenu();
+  void CloseOverflowMenu();
+  bool OverflowMenuIsWanted();
+
   void ToggleOverflowMenu();
   bool OverflowMenuVisible();
 
diff --git a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
index 3a81d47..5b2017f 100644
--- a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
@@ -637,8 +637,29 @@
   background: #FFFFFF;
   box-shadow: 0 1px 9px 0 rgba(0,0,0,0.40);
   border-radius: 2px;
+  transition: transform .2s ease-out, opacity .2s linear;
+  transform-origin: bottom right;
 }
 
+audio::-internal-media-controls-overflow-menu-list.closed,
+video::-internal-media-controls-overflow-menu-list.closed {
+  transform: scale(0);
+  opacity: 0;
+}
+
+
+audio::-webkit-media-controls div[pseudo="-internal-media-controls-overflow-menu-list" i].closed > *,
+video::-webkit-media-controls div[pseudo="-internal-media-controls-overflow-menu-list" i].closed > * {
+  opacity: 0;
+}
+
+audio::-webkit-media-controls div[pseudo="-internal-media-controls-overflow-menu-list" i] > *,
+video::-webkit-media-controls div[pseudo="-internal-media-controls-overflow-menu-list" i] > * {
+  transition: opacity .2s linear .2s;
+}
+
+
+
 audio::-internal-media-controls-text-track-list-header,
 video::-internal-media-controls-text-track-list-header,
 audio::-internal-media-controls-text-track-list-item,
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index 340dc7b..30a23c0 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -200,7 +200,7 @@
  public:
   using MediaDeviceInfos = HeapVector<Member<MediaDeviceInfo>>;
 
-  MediaDevicesTest() : device_infos_(new MediaDeviceInfos) {
+  MediaDevicesTest() : device_infos_(MakeGarbageCollected<MediaDeviceInfos>()) {
     dispatcher_host_ = std::make_unique<MockMediaDevicesDispatcherHost>();
   }
 
diff --git a/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc b/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc
index c9826ad..7df08e2050 100644
--- a/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc
+++ b/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc
@@ -111,7 +111,7 @@
       source_as_message_port_ = initializer.source().GetAsMessagePort();
   }
   if (initializer.hasPorts())
-    ports_ = new MessagePortArray(initializer.ports());
+    ports_ = MakeGarbageCollected<MessagePortArray>(initializer.ports());
 }
 
 ExtendableMessageEvent::ExtendableMessageEvent(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index 3a98213..084dbeff 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -134,7 +134,6 @@
 
 void ServiceWorkerGlobalScope::EvaluateClassicScript(
     const KURL& script_url,
-    AccessControlStatus access_control_status,
     String source_code,
     std::unique_ptr<Vector<char>> cached_meta_data) {
   DCHECK(IsContextThread());
@@ -142,8 +141,8 @@
   if (!evaluate_script_ready_) {
     evaluate_script_ =
         WTF::Bind(&ServiceWorkerGlobalScope::EvaluateClassicScript,
-                  WrapWeakPersistent(this), script_url, access_control_status,
-                  std::move(source_code), std::move(cached_meta_data));
+                  WrapWeakPersistent(this), script_url, std::move(source_code),
+                  std::move(cached_meta_data));
     return;
   }
 
@@ -182,8 +181,7 @@
     ReportingProxy().DidLoadInstalledScript();
   }
 
-  WorkerGlobalScope::EvaluateClassicScript(script_url, access_control_status,
-                                           source_code,
+  WorkerGlobalScope::EvaluateClassicScript(script_url, source_code,
                                            std::move(cached_meta_data));
 }
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
index 1e633a72..091b66e 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -76,7 +76,6 @@
   // Implements WorkerGlobalScope.
   void EvaluateClassicScript(
       const KURL& script_url,
-      AccessControlStatus access_control_status,
       String source_code,
       std::unique_ptr<Vector<char>> cached_meta_data) override;
   void ImportModuleScript(
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_node.cc b/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
index 066029e0..6916853 100644
--- a/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
@@ -51,8 +51,8 @@
     unsigned number_of_output_channels)
     : AudioHandler(kNodeTypeScriptProcessor, node, sample_rate),
       double_buffer_index_(0),
-      input_buffers_(new HeapVector<Member<AudioBuffer>>()),
-      output_buffers_(new HeapVector<Member<AudioBuffer>>()),
+      input_buffers_(MakeGarbageCollected<HeapVector<Member<AudioBuffer>>>()),
+      output_buffers_(MakeGarbageCollected<HeapVector<Member<AudioBuffer>>>()),
       buffer_size_(buffer_size),
       buffer_read_write_index_(0),
       number_of_input_channels_(number_of_input_channels),
diff --git a/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc
index 2d052f9..981a4fe 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc
@@ -56,7 +56,7 @@
   Vector<network::mojom::blink::HttpHeaderPtr> additional_headers;
   if (!user_agent_override.IsNull()) {
     additional_headers.push_back(network::mojom::blink::HttpHeader::New(
-        HTTPNames::User_Agent, user_agent_override));
+        http_names::kUserAgent, user_agent_override));
   }
   client_binding_.Bind(mojo::MakeRequest(&client_proxy, task_runner));
   websocket_->AddChannelRequest(url, protocols, site_for_cookies,
diff --git a/third_party/blink/renderer/platform/exported/web_cors.cc b/third_party/blink/renderer/platform/exported/web_cors.cc
index 91f6863..d9e50d1 100644
--- a/third_party/blink/renderer/platform/exported/web_cors.cc
+++ b/third_party/blink/renderer/platform/exported/web_cors.cc
@@ -145,7 +145,7 @@
 
   WebHTTPHeaderSet header_set;
   HTTPHeaderNameListParser parser(response.HttpHeaderField(
-      WebString(HTTPNames::Access_Control_Expose_Headers)));
+      WebString(http_names::kAccessControlExposeHeaders)));
   parser.Parse(header_set);
 
   if (credentials_mode != network::mojom::FetchCredentialsMode::kInclude &&
diff --git a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
index c81f9c56..35c806f 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -203,7 +203,6 @@
                        chunk.begin_index, chunk.end_index,
                        DisplayItemList::kSkipNonDrawings |
                            DisplayItemList::kShownOnlyDisplayItemTypes));
-    json->SetString("propertyTreeState", chunk.properties.ToTreeString());
     paint_chunk_debug_data_->PushObject(std::move(json));
   }
 #endif
diff --git a/third_party/blink/renderer/platform/graphics/contiguous_container.h b/third_party/blink/renderer/platform/graphics/contiguous_container.h
index d551da7..37066cf 100644
--- a/third_party/blink/renderer/platform/graphics/contiguous_container.h
+++ b/third_party/blink/renderer/platform/graphics/contiguous_container.h
@@ -138,6 +138,8 @@
       IteratorWrapper<Vector<void*>::const_reverse_iterator,
                       const BaseElementType>;
 
+  using value_type = BaseElementType;
+
   explicit ContiguousContainer(size_t max_object_size)
       : ContiguousContainerBase(Align(max_object_size)) {}
 
diff --git a/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
index 71029cd6..0e1d2ee 100644
--- a/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -578,7 +578,7 @@
 }
 
 LoggingCanvas::LoggingCanvas()
-    : InterceptingCanvasBase(0, 0), log_(JSONArray::Create()) {}
+    : InterceptingCanvasBase(999999, 999999), log_(JSONArray::Create()) {}
 
 void LoggingCanvas::onDrawPaint(const SkPaint& paint) {
   AutoLogger logger(this);
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
index 5f5984a..81e23a7 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -26,9 +26,9 @@
     case 0:
       return "PaintPhaseBlockBackground";
     case 1:
-      return "PaintPhaseSelfBlockBackground";
+      return "PaintPhaseSelfBlockBackgroundOnly";
     case 2:
-      return "PaintPhaseChildBlockBackgrounds";
+      return "PaintPhaseDescendantBlockBackgroundsOnly";
     case 3:
       return "PaintPhaseFloat";
     case 4:
@@ -36,9 +36,9 @@
     case 5:
       return "PaintPhaseOutline";
     case 6:
-      return "PaintPhaseSelfOutline";
+      return "PaintPhaseSelfOutlineOnly";
     case 7:
-      return "PaintPhaseChildOutlines";
+      return "PaintPhaseDescendantOutlinesOnly";
     case 8:
       return "PaintPhaseSelection";
     case 9:
@@ -174,16 +174,36 @@
     json.SetDouble("outset", OutsetForRasterEffects());
 }
 
-#endif
+#endif  // DCHECK_IS_ON()
 
 String DisplayItem::Id::ToString() const {
 #if DCHECK_IS_ON()
-  return String::Format("%p:%s:%d", &client,
-                        DisplayItem::TypeAsDebugString(type).Ascii().data(),
+  return String::Format("%s:%s:%d", client.ToString().Utf8().data(),
+                        DisplayItem::TypeAsDebugString(type).Utf8().data(),
                         fragment);
 #else
   return String::Format("%p:%d:%d", &client, static_cast<int>(type), fragment);
 #endif
 }
 
+std::ostream& operator<<(std::ostream& os, DisplayItem::Type type) {
+#if DCHECK_IS_ON()
+  return os << DisplayItem::TypeAsDebugString(type).Utf8().data();
+#else
+  return os << static_cast<int>(type);
+#endif
+}
+
+std::ostream& operator<<(std::ostream& os, const DisplayItem::Id& id) {
+  return os << id.ToString().Utf8().data();
+}
+
+std::ostream& operator<<(std::ostream& os, const DisplayItem& item) {
+#if DCHECK_IS_ON()
+  return os << item.AsDebugString().Utf8().data();
+#else
+  return os << "{\"id\": " << item.GetId() << "}";
+#endif
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h
index 1304ddda..e3680134 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -225,20 +225,20 @@
 
 // See comments of enum Type for usage of the following macros.
 #define DEFINE_CATEGORY_METHODS(Category)                           \
-  static bool Is##Category##Type(Type type) {                       \
+  static constexpr bool Is##Category##Type(Type type) {             \
     return type >= k##Category##First && type <= k##Category##Last; \
   }                                                                 \
   bool Is##Category() const { return Is##Category##Type(GetType()); }
 
-#define DEFINE_PAINT_PHASE_CONVERSION_METHOD(Category)                \
-  static Type PaintPhaseTo##Category##Type(PaintPhase paint_phase) {  \
-    static_assert(                                                    \
-        k##Category##PaintPhaseLast - k##Category##PaintPhaseFirst == \
-            kPaintPhaseMax,                                           \
-        "Invalid paint-phase-based category " #Category               \
-        ". See comments of DisplayItem::Type");                       \
-    return static_cast<Type>(static_cast<int>(paint_phase) +          \
-                             k##Category##PaintPhaseFirst);           \
+#define DEFINE_PAINT_PHASE_CONVERSION_METHOD(Category)                         \
+  static constexpr Type PaintPhaseTo##Category##Type(PaintPhase paint_phase) { \
+    static_assert(                                                             \
+        k##Category##PaintPhaseLast - k##Category##PaintPhaseFirst ==          \
+            kPaintPhaseMax,                                                    \
+        "Invalid paint-phase-based category " #Category                        \
+        ". See comments of DisplayItem::Type");                                \
+    return static_cast<Type>(static_cast<int>(paint_phase) +                   \
+                             k##Category##PaintPhaseFirst);                    \
   }
 
   DEFINE_CATEGORY_METHODS(Drawing)
@@ -308,6 +308,10 @@
   return !(a == b);
 }
 
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, DisplayItem::Type);
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const DisplayItem::Id&);
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const DisplayItem&);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc b/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc
index c739385ef..3888b08 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc
@@ -30,21 +30,39 @@
          g_live_display_item_clients->Contains(this);
 }
 
-String DisplayItemClient::SafeDebugName(const DisplayItemClient& client,
-                                        bool known_to_be_safe) {
+String DisplayItemClient::SafeDebugName(bool known_to_be_safe) const {
   if (known_to_be_safe) {
-    DCHECK(client.IsAlive());
-    return client.DebugName();
+    DCHECK(IsAlive());
+    return DebugName();
   }
 
   // If the caller is not sure, we must ensure the client is alive, and it's
   // not a destroyed client at the same address of a new client.
-  if (client.IsAlive() && !client.IsJustCreated())
-    return client.DebugName();
-
+  if (IsJustCreated())
+    return "Just created:" + DebugName();
+  if (IsAlive())
+    return DebugName();
   return "DEAD";
 }
 
 #endif  // DCHECK_IS_ON()
 
+String DisplayItemClient::ToString() const {
+#if DCHECK_IS_ON()
+  return String::Format("%p:%s", this, SafeDebugName().Utf8().data());
+#else
+  return String::Format("%p", this);
+#endif
+}
+
+std::ostream& operator<<(std::ostream& out, const DisplayItemClient& client) {
+  return out << client.ToString();
+}
+
+std::ostream& operator<<(std::ostream& out, const DisplayItemClient* client) {
+  if (!client)
+    return out << "<null>";
+  return out << *client;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_client.h b/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
index 2d6ec1c..27a43f1 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
@@ -36,7 +36,7 @@
   // Tests if this DisplayItemClient object has been created and has not been
   // deleted yet.
   bool IsAlive() const;
-  static String SafeDebugName(const DisplayItemClient&, bool known_to_be_safe);
+  String SafeDebugName(bool known_to_be_safe = false) const;
 #endif
 
   virtual String DebugName() const = 0;
@@ -114,6 +114,8 @@
     return paint_invalidation_reason_ == PaintInvalidationReason::kNone;
   }
 
+  String ToString() const;
+
  private:
   friend class FakeDisplayItemClient;
   friend class PaintController;
@@ -141,6 +143,11 @@
   return &client1 != &client2;
 }
 
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&,
+                                         const DisplayItemClient*);
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&,
+                                         const DisplayItemClient&);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_CLIENT_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc b/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
index 6bd2940..efbdaea 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
@@ -49,9 +49,13 @@
     if (flags & kShownOnlyDisplayItemTypes) {
       json->SetString("type", DisplayItem::TypeAsDebugString(item.GetType()));
     } else {
-      json->SetString("clientDebugName",
-                      DisplayItemClient::SafeDebugName(
-                          item.Client(), flags & kClientKnownToBeAlive));
+      json->SetString("clientDebugName", item.Client().SafeDebugName(
+                                             flags & kClientKnownToBeAlive));
+      if (flags & kClientKnownToBeAlive) {
+        json->SetString("invalidation",
+                        PaintInvalidationReasonToString(
+                            item.Client().GetPaintInvalidationReason()));
+      }
       item.PropertiesAsJSON(*json);
     }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc b/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
index 37f21620..7d9ded94 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
@@ -9,6 +9,8 @@
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
 #include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
 
+using testing::ElementsAre;
+
 namespace blink {
 
 using DrawingRecorderTest = PaintControllerTestBase;
@@ -23,8 +25,8 @@
   InitRootChunk();
   DrawNothing(context, client, kForegroundType);
   CommitAndFinishCycle();
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kForegroundType)));
   EXPECT_FALSE(static_cast<const DrawingDisplayItem&>(
                    GetPaintController().GetDisplayItemList()[0])
                    .GetPaintRecord());
@@ -36,8 +38,8 @@
   InitRootChunk();
   DrawRect(context, client, kForegroundType, kBounds);
   CommitAndFinishCycle();
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kForegroundType)));
 }
 
 TEST_F(DrawingRecorderTest, Cached) {
@@ -48,9 +50,9 @@
   DrawRect(context, client, kForegroundType, kBounds);
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(client, kBackgroundType),
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType),
+                          IsSameId(&client, kForegroundType)));
 
   InitRootChunk();
   DrawNothing(context, client, kBackgroundType);
@@ -60,9 +62,9 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(client, kBackgroundType),
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType),
+                          IsSameId(&client, kForegroundType)));
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
index 799cafd..0f6858a3 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
@@ -26,8 +26,8 @@
   String ret_val = String::Format(
       "PaintChunk(begin=%zu, end=%zu, id=%s cacheable=%d props=(%s) bounds=%s "
       "known_to_be_opaque=%d",
-      begin_index, end_index, id.ToString().Ascii().data(), is_cacheable,
-      properties.ToString().Ascii().data(), bounds.ToString().Ascii().data(),
+      begin_index, end_index, id.ToString().Utf8().data(), is_cacheable,
+      properties.ToString().Utf8().data(), bounds.ToString().Utf8().data(),
       known_to_be_opaque);
   if (hit_test_data) {
     ret_val.append(String::Format(
@@ -37,17 +37,17 @@
         hit_test_data->touch_action_rects.size(),
         HitTestRect::GetBounds(hit_test_data->touch_action_rects)
             .ToString()
-            .Ascii()
+            .Utf8()
             .data(),
         hit_test_data->wheel_event_handler_region.size(),
         HitTestRect::GetBounds(hit_test_data->wheel_event_handler_region)
             .ToString()
-            .Ascii()
+            .Utf8()
             .data(),
         hit_test_data->non_fast_scrollable_region.size(),
         HitTestRect::GetBounds(hit_test_data->non_fast_scrollable_region)
             .ToString()
-            .Ascii()
+            .Utf8()
             .data()));
   } else {
     ret_val.append(")");
@@ -56,7 +56,7 @@
 }
 
 std::ostream& operator<<(std::ostream& os, const PaintChunk& chunk) {
-  return os << chunk.ToString().Utf8().data();
+  return os << chunk.ToString().Utf8().data() << "\n";
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
index 0bd65f75..5538e570 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
@@ -117,17 +117,6 @@
 
   String ToString() const;
 
-  bool operator==(const PaintChunk& rhs) const {
-    return begin_index == rhs.begin_index && end_index == rhs.end_index &&
-           id == rhs.id && properties == rhs.properties &&
-           is_cacheable == rhs.is_cacheable &&
-           ((!hit_test_data && !rhs.hit_test_data) ||
-            (hit_test_data && rhs.hit_test_data &&
-             *hit_test_data == *rhs.hit_test_data));
-  }
-
-  bool operator!=(const PaintChunk& rhs) const { return !(*this == rhs); }
-
  private:
   std::unique_ptr<HitTestData> hit_test_data;
 };
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
index 04f41a4c..a96ab6fc 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
 #include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
 
 using testing::ElementsAre;
@@ -62,13 +63,13 @@
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
 
   const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 1u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 2, id, DefaultPaintChunkProperties()));
+  EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 2, id,
+                                               DefaultPaintChunkProperties())));
 
   auto chunks1 = chunker.ReleasePaintChunks();
   EXPECT_TRUE(chunker.PaintChunks().IsEmpty());
-  EXPECT_EQ(chunks1.size(), 1u);
-  EXPECT_EQ(chunks1[0], PaintChunk(0, 2, id, DefaultPaintChunkProperties()));
+  EXPECT_THAT(chunks1, ElementsAre(IsPaintChunk(
+                           0, 2, id, DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk) {
@@ -81,13 +82,13 @@
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
 
   const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 1u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 3, id, DefaultPaintChunkProperties()));
+  EXPECT_THAT(chunks, ElementsAre(IsPaintChunk(0, 3, id,
+                                               DefaultPaintChunkProperties())));
 
   auto chunks1 = chunker.ReleasePaintChunks();
   EXPECT_TRUE(chunker.PaintChunks().IsEmpty());
-  EXPECT_EQ(chunks1.size(), 1u);
-  EXPECT_EQ(chunks1[0], PaintChunk(0, 3, id, DefaultPaintChunkProperties()));
+  EXPECT_THAT(chunks1, ElementsAre(IsPaintChunk(
+                           0, 3, id, DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
@@ -114,11 +115,11 @@
   chunker.UpdateCurrentPaintChunkProperties(id3, another_transform);
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 3u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 2, id1, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1], PaintChunk(2, 3, id2, simple_transform));
-  EXPECT_EQ(chunks[2], PaintChunk(3, 4, id3, another_transform));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 2, id1, DefaultPaintChunkProperties()),
+                  IsPaintChunk(2, 3, id2, simple_transform),
+                  IsPaintChunk(3, 4, id3, another_transform)));
 }
 
 TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
@@ -168,16 +169,16 @@
   chunker.IncrementDisplayItemIndex(item_after_restore);
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 5u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 1, id1, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1], PaintChunk(1, 3, id2, simple_transform));
-  EXPECT_EQ(chunks[2], PaintChunk(3, 5, id3, simple_transform_and_effect));
-  EXPECT_EQ(chunks[3],
-            PaintChunk(5, 7, id4,
-                       simple_transform_and_effect_with_updated_transform));
-  EXPECT_EQ(chunks[4], PaintChunk(7, 9, item_after_restore.GetId(),
-                                  simple_transform_and_effect));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(
+          IsPaintChunk(0, 1, id1, DefaultPaintChunkProperties()),
+          IsPaintChunk(1, 3, id2, simple_transform),
+          IsPaintChunk(3, 5, id3, simple_transform_and_effect),
+          IsPaintChunk(5, 7, id4,
+                       simple_transform_and_effect_with_updated_transform),
+          IsPaintChunk(7, 9, item_after_restore.GetId(),
+                       simple_transform_and_effect)));
 }
 
 TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms) {
@@ -209,12 +210,12 @@
   TestChunkerDisplayItem item_after_restore(client_, DisplayItemType(10));
   chunker.IncrementDisplayItemIndex(item_after_restore);
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 3u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 1, id1, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1], PaintChunk(1, 3, id2, simple_transform));
-  EXPECT_EQ(chunks[2], PaintChunk(3, 4, item_after_restore.GetId(),
-                                  DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, id1, DefaultPaintChunkProperties()),
+                  IsPaintChunk(1, 3, id2, simple_transform),
+                  IsPaintChunk(3, 4, item_after_restore.GetId(),
+                               DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems) {
@@ -239,10 +240,10 @@
   chunker.UpdateCurrentPaintChunkProperties(id3, second_transform);
 
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 2u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 1, id1, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1], PaintChunk(1, 2, id3, second_transform));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, id1, DefaultPaintChunkProperties()),
+                  IsPaintChunk(1, 2, id3, second_transform)));
 }
 
 TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested) {
@@ -266,17 +267,14 @@
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
   chunker.IncrementDisplayItemIndex(i3);
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 5u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 1, id0, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1],
-            PaintChunk(1, 2, i1.GetId(), DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[2],
-            PaintChunk(2, 3, i2.GetId(), DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[3],
-            PaintChunk(3, 5, after_i2.GetId(), DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[4],
-            PaintChunk(5, 6, i3.GetId(), DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(
+          IsPaintChunk(0, 1, id0, DefaultPaintChunkProperties()),
+          IsPaintChunk(1, 2, i1.GetId(), DefaultPaintChunkProperties()),
+          IsPaintChunk(2, 3, i2.GetId(), DefaultPaintChunkProperties()),
+          IsPaintChunk(3, 5, after_i2.GetId(), DefaultPaintChunkProperties()),
+          IsPaintChunk(5, 6, i3.GetId(), DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ForceNewChunkWithNewId) {
@@ -298,11 +296,11 @@
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 3u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 2, id0, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1], PaintChunk(2, 4, id1, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[2], PaintChunk(4, 6, id2, DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 2, id0, DefaultPaintChunkProperties()),
+                  IsPaintChunk(2, 4, id1, DefaultPaintChunkProperties()),
+                  IsPaintChunk(4, 6, id2, DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ForceNewChunkWithoutNewId) {
@@ -328,11 +326,11 @@
   chunker.IncrementDisplayItemIndex(
       TestChunkerDisplayItem(client_, DisplayItemType(21)));
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 3u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 2, id0, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1], PaintChunk(2, 4, id1, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[2], PaintChunk(4, 6, id2, DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 2, id0, DefaultPaintChunkProperties()),
+                  IsPaintChunk(2, 4, id1, DefaultPaintChunkProperties()),
+                  IsPaintChunk(4, 6, id2, DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, NoNewChunkForSamePropertyDifferentIds) {
@@ -352,9 +350,9 @@
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
   chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 1u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 6, id0, DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 6, id0, DefaultPaintChunkProperties())));
 }
 
 class TestScrollHitTestRequiringSeparateChunk : public TestChunkerDisplayItem {
@@ -385,13 +383,13 @@
   chunker.IncrementDisplayItemIndex(after_forced1);
   chunker.IncrementDisplayItemIndex(after_forced2);
 
-  const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 3u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 2, id0, DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[1],
-            PaintChunk(2, 3, forced.GetId(), DefaultPaintChunkProperties()));
-  EXPECT_EQ(chunks[2], PaintChunk(3, 5, after_forced1.GetId(),
-                                  DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunker.PaintChunks(),
+      ElementsAre(
+          IsPaintChunk(0, 2, id0, DefaultPaintChunkProperties()),
+          IsPaintChunk(2, 3, forced.GetId(), DefaultPaintChunkProperties()),
+          IsPaintChunk(3, 5, after_forced1.GetId(),
+                       DefaultPaintChunkProperties())));
 }
 
 TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
@@ -429,19 +427,20 @@
   chunker.IncrementDisplayItemIndex(after_restore);
 
   const auto& chunks = chunker.PaintChunks();
-  EXPECT_EQ(chunks.size(), 5u);
-  EXPECT_EQ(chunks[0], PaintChunk(0, 2, id1, DefaultPaintChunkProperties()));
+  EXPECT_THAT(
+      chunks,
+      ElementsAre(
+          IsPaintChunk(0, 2, id1, DefaultPaintChunkProperties()),
+          IsPaintChunk(2, 4, id2, simple_transform),
+          IsPaintChunk(4, 5, uncacheable_separate_chunk_item.GetId(),
+                       simple_transform),
+          IsPaintChunk(5, 6, after_separate_chunk.GetId(), simple_transform),
+          IsPaintChunk(6, 7, after_restore.GetId(),
+                       DefaultPaintChunkProperties())));
   EXPECT_TRUE(chunks[0].is_cacheable);
-  EXPECT_EQ(chunks[1], PaintChunk(2, 4, id2, simple_transform));
   EXPECT_FALSE(chunks[1].is_cacheable);
-  EXPECT_EQ(chunks[2], PaintChunk(4, 5, uncacheable_separate_chunk_item.GetId(),
-                                  simple_transform));
   EXPECT_FALSE(chunks[2].is_cacheable);
-  EXPECT_EQ(chunks[3],
-            PaintChunk(5, 6, after_separate_chunk.GetId(), simple_transform));
   EXPECT_TRUE(chunks[3].is_cacheable);
-  EXPECT_EQ(chunks[4], PaintChunk(6, 7, after_restore.GetId(),
-                                  DefaultPaintChunkProperties()));
   EXPECT_TRUE(chunks[4].is_cacheable);
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
index 8f70d35b..0d0289e4 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
@@ -146,17 +146,20 @@
 
 String PaintController::DisplayItemListAsJSON::ClientName(
     const DisplayItemClient& client) const {
-  return DisplayItemClient::SafeDebugName(
-      client, flags_ & DisplayItemList::kClientKnownToBeAlive);
+  return client.SafeDebugName(flags_ & DisplayItemList::kClientKnownToBeAlive);
 }
 
 void PaintController::ShowDebugDataInternal(
     DisplayItemList::JsonFlags flags) const {
+  auto current_list_flags = flags;
+  // The clients in the current list are known to be alive before FinishCycle().
+  if (committed_)
+    current_list_flags |= DisplayItemList::kClientKnownToBeAlive;
   LOG(ERROR) << "current display item list: "
              << DisplayItemListAsJSON(
                     current_paint_artifact_->GetDisplayItemList(),
                     current_cached_subsequences_,
-                    current_paint_artifact_->PaintChunks(), flags)
+                    current_paint_artifact_->PaintChunks(), current_list_flags)
                     .ToString()
                     .Utf8()
                     .data();
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
index 5ad0cab6..eb7d89d2 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
@@ -15,6 +15,8 @@
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
 
+using testing::ElementsAre;
+
 namespace blink {
 
 // Tests using this class will be tested with under-invalidation-checking
@@ -23,6 +25,11 @@
                             public PaintControllerTestBase {
 };
 
+#define EXPECT_DEFAULT_ROOT_CHUNK(size)                               \
+  EXPECT_THAT(GetPaintController().PaintChunks(),                     \
+              ElementsAre(IsPaintChunk(0, size, DefaultRootChunkId(), \
+                                       DefaultPaintChunkProperties())))
+
 INSTANTIATE_TEST_CASE_P(
     All,
     PaintControllerTest,
@@ -41,10 +48,9 @@
   DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 200, 200));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
-                      TestDisplayItem(client, kBackgroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(1);
 }
 
 TEST_P(PaintControllerTest, UpdateBasic) {
@@ -61,12 +67,11 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&first, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(3);
 
   InitRootChunk();
   DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
@@ -81,11 +86,10 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(2);
 }
 
 TEST_P(PaintControllerTest, UpdateSwapOrder) {
@@ -103,13 +107,13 @@
   DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType),
-                      TestDisplayItem(unaffected, kBackgroundType),
-                      TestDisplayItem(unaffected, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType),
+                          IsSameId(&unaffected, kBackgroundType),
+                          IsSameId(&unaffected, kForegroundType)));
 
   InitRootChunk();
   DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
@@ -128,15 +132,14 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType),
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(unaffected, kBackgroundType),
-                      TestDisplayItem(unaffected, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType),
+                          IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&unaffected, kBackgroundType),
+                          IsSameId(&unaffected, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(6);
 }
 
 TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
@@ -154,13 +157,13 @@
   DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType),
-                      TestDisplayItem(unaffected, kBackgroundType),
-                      TestDisplayItem(unaffected, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType),
+                          IsSameId(&unaffected, kBackgroundType),
+                          IsSameId(&unaffected, kForegroundType)));
 
   InitRootChunk();
   first.Invalidate();
@@ -180,15 +183,14 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType),
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(unaffected, kBackgroundType),
-                      TestDisplayItem(unaffected, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType),
+                          IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&unaffected, kBackgroundType),
+                          IsSameId(&unaffected, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(6);
 }
 
 TEST_P(PaintControllerTest, UpdateNewItemInMiddle) {
@@ -202,9 +204,9 @@
   DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType)));
 
   InitRootChunk();
 
@@ -221,12 +223,11 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(third, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&third, kBackgroundType),
+                          IsSameId(&second, kBackgroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(3);
 }
 
 TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
@@ -244,13 +245,13 @@
   DrawRect(context, third, kForegroundType, FloatRect(300, 100, 50, 50));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(third, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(second, kForegroundType),
-                      TestDisplayItem(third, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&third, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&second, kForegroundType),
+                          IsSameId(&third, kForegroundType)));
 
   InitRootChunk();
 
@@ -271,45 +272,14 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(third, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(second, kForegroundType),
-                      TestDisplayItem(third, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-}
-
-TEST_P(PaintControllerTest, IncrementalRasterInvalidation) {
-  LayoutRect initial_rect(100, 100, 100, 100);
-  std::unique_ptr<FakeDisplayItemClient> clients[6];
-  for (auto& client : clients)
-    client = std::make_unique<FakeDisplayItemClient>("", initial_rect);
-  GraphicsContext context(GetPaintController());
-
-  InitRootChunk();
-
-  for (auto& client : clients)
-    DrawRect(context, *client, kBackgroundType, FloatRect(initial_rect));
-  CommitAndFinishCycle();
-
-  InitRootChunk();
-  clients[0]->SetVisualRect(LayoutRect(100, 100, 150, 100));
-  clients[1]->SetVisualRect(LayoutRect(100, 100, 100, 150));
-  clients[2]->SetVisualRect(LayoutRect(100, 100, 150, 80));
-  clients[3]->SetVisualRect(LayoutRect(100, 100, 80, 150));
-  clients[4]->SetVisualRect(LayoutRect(100, 100, 150, 150));
-  clients[5]->SetVisualRect(LayoutRect(100, 100, 80, 80));
-  for (auto& client : clients) {
-    client->Invalidate(PaintInvalidationReason::kIncremental);
-    DrawRect(context, *client, kBackgroundType,
-             FloatRect(client->VisualRect()));
-  }
-  CommitAndFinishCycle();
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&third, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&second, kForegroundType),
+                          IsSameId(&third, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(6);
 }
 
 TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
@@ -322,9 +292,9 @@
   DrawRect(context, second, kForegroundType, FloatRect(200, 200, 50, 50));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType)));
 
   InitRootChunk();
 
@@ -338,13 +308,12 @@
   EXPECT_EQ(0, NumCachedNewItems());
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(4);
 
   InitRootChunk();
   DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
@@ -359,11 +328,10 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(2);
 }
 
 TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
@@ -376,9 +344,9 @@
   DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType)));
 
   InitRootChunk();
 
@@ -392,13 +360,12 @@
   EXPECT_EQ(0, NumCachedNewItems());
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(second, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&second, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(4);
 
   InitRootChunk();
   first.Invalidate();
@@ -409,11 +376,10 @@
   EXPECT_EQ(0, NumCachedNewItems());
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(first, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&first, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(2);
 }
 
 TEST_P(PaintControllerTest, CachedDisplayItems) {
@@ -426,9 +392,9 @@
   DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 150, 150));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType)));
   EXPECT_TRUE(ClientCacheIsValid(first));
   EXPECT_TRUE(ClientCacheIsValid(second));
   sk_sp<const PaintRecord> first_paint_record =
@@ -449,9 +415,9 @@
   DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 150, 150));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType)));
   // The first display item should be updated.
   EXPECT_NE(first_paint_record,
             static_cast<const DrawingDisplayItem&>(
@@ -492,15 +458,15 @@
   DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType),
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType)));
 
   InitRootChunk();
 
@@ -516,17 +482,16 @@
   DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType),
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(8);
 }
 
 TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
@@ -549,15 +514,15 @@
   DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType),
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType)));
 
   InitRootChunk();
 
@@ -574,17 +539,16 @@
   DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType),
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType));
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType)));
+  EXPECT_DEFAULT_ROOT_CHUNK(8);
 }
 
 TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
@@ -601,10 +565,9 @@
   DrawRect(context, root, kBackgroundType, FloatRect(100, 100, 100, 100));
 
   FakeDisplayItemClient container("container");
+  auto container_properties = DefaultPaintChunkProperties();
+  PaintChunk::Id container_id(container, DisplayItem::kCaret);
   {
-    auto container_properties = DefaultPaintChunkProperties();
-    PaintChunk::Id container_id(container, DisplayItem::kCaret);
-
     SubsequenceRecorder r(context, container);
     GetPaintController().UpdateCurrentPaintChunkProperties(
         container_id, container_properties);
@@ -620,13 +583,12 @@
 
   // Even though the paint properties match, |container| should receive its
   // own PaintChunk because it created a subsequence.
-  EXPECT_EQ(3u, GetPaintController().GetPaintArtifact().PaintChunks().size());
-  EXPECT_EQ(root,
-            GetPaintController().GetPaintArtifact().PaintChunks()[0].id.client);
-  EXPECT_EQ(container,
-            GetPaintController().GetPaintArtifact().PaintChunks()[1].id.client);
-  EXPECT_EQ(root,
-            GetPaintController().GetPaintArtifact().PaintChunks()[2].id.client);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_id, root_properties),
+                  IsPaintChunk(1, 3, container_id, container_properties),
+                  IsPaintChunk(3, 4, PaintChunk::Id(root, kForegroundType),
+                               root_properties)));
 
   GetPaintController().UpdateCurrentPaintChunkProperties(root_id,
                                                          root_properties);
@@ -637,13 +599,12 @@
 
   // |container| should still receive its own PaintChunk because it is a cached
   // subsequence.
-  EXPECT_EQ(3u, GetPaintController().GetPaintArtifact().PaintChunks().size());
-  EXPECT_EQ(root,
-            GetPaintController().GetPaintArtifact().PaintChunks()[0].id.client);
-  EXPECT_EQ(container,
-            GetPaintController().GetPaintArtifact().PaintChunks()[1].id.client);
-  EXPECT_EQ(root,
-            GetPaintController().GetPaintArtifact().PaintChunks()[2].id.client);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, root_id, root_properties),
+                  IsPaintChunk(1, 3, container_id, container_properties),
+                  IsPaintChunk(3, 4, PaintChunk::Id(root, kForegroundType),
+                               container_properties)));
 }
 
 TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
@@ -655,17 +616,19 @@
   FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
   GraphicsContext context(GetPaintController());
 
+  PaintChunk::Id container1_id(container1, kBackgroundType);
   auto container1_effect = CreateOpacityEffect(e0(), 0.5);
   auto container1_properties = DefaultPaintChunkProperties();
   container1_properties.SetEffect(container1_effect.get());
 
+  PaintChunk::Id container2_id(container2, kBackgroundType);
   auto container2_effect = CreateOpacityEffect(e0(), 0.5);
   auto container2_properties = DefaultPaintChunkProperties();
   container2_properties.SetEffect(container2_effect.get());
 
   {
     GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(container1, kBackgroundType), container1_properties);
+        container1_id, container1_properties);
 
     SubsequenceRecorder r(context, container1);
     DrawRect(context, container1, kBackgroundType,
@@ -677,7 +640,7 @@
   }
   {
     GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(container2, kBackgroundType), container2_properties);
+        container2_id, container2_properties);
 
     SubsequenceRecorder r(context, container2);
     DrawRect(context, container2, kBackgroundType,
@@ -689,16 +652,16 @@
   }
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType),
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType),
 
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType));
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType)));
 
   auto* markers = GetSubsequenceMarkers(container1);
   CHECK(markers);
@@ -710,11 +673,10 @@
   EXPECT_EQ(4u, markers->start);
   EXPECT_EQ(8u, markers->end);
 
-  EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
-  EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
-            GetPaintController().PaintChunks()[0].id);
-  EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
-            GetPaintController().PaintChunks()[1].id);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 4, container1_id, container1_properties),
+                  IsPaintChunk(4, 8, container2_id, container2_properties)));
 
   // Simulate the situation when |container1| gets a z-index that is greater
   // than that of |container2|.
@@ -725,9 +687,8 @@
     EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
         context, container2));
     {
-      PaintChunk::Id id(container2, kBackgroundType);
       GetPaintController().UpdateCurrentPaintChunkProperties(
-          id, container2_properties);
+          container2_id, container2_properties);
 
       SubsequenceRecorder r(context, container2);
       DrawRect(context, container2, kBackgroundType,
@@ -742,9 +703,8 @@
     EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
         context, container1));
     {
-      PaintChunk::Id id(container1, kBackgroundType);
       GetPaintController().UpdateCurrentPaintChunkProperties(
-          id, container1_properties);
+          container1_id, container1_properties);
 
       SubsequenceRecorder r(context, container1);
       DrawRect(context, container1, kBackgroundType,
@@ -772,15 +732,15 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType),
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType),
+                          IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType)));
 
   markers = GetSubsequenceMarkers(container2);
   CHECK(markers);
@@ -792,11 +752,10 @@
   EXPECT_EQ(4u, markers->start);
   EXPECT_EQ(8u, markers->end);
 
-  EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
-  EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
-            GetPaintController().PaintChunks()[0].id);
-  EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
-            GetPaintController().PaintChunks()[1].id);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 4, container2_id, container2_properties),
+                  IsPaintChunk(4, 8, container1_id, container1_properties)));
 }
 
 TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
@@ -822,13 +781,13 @@
   DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType),
-                      TestDisplayItem(content1, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&content1, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType),
+                          IsSameId(&content1, kForegroundType)));
 
   auto* markers = GetSubsequenceMarkers(container2);
   CHECK(markers);
@@ -875,13 +834,13 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(container2, kForegroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&content2, kForegroundType),
+                          IsSameId(&container2, kForegroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType)));
 
   markers = GetSubsequenceMarkers(container2);
   CHECK(markers);
@@ -918,17 +877,17 @@
   CommitAndFinishCycle();
 
   auto check_paint_results = [this, &root, &container]() {
-    const auto& chunks = GetPaintController().PaintChunks();
-    EXPECT_EQ(chunks.size(), 3u);
-    EXPECT_EQ(chunks[0], PaintChunk(0, 1, PaintChunk::Id(root, kBackgroundType),
-                                    DefaultPaintChunkProperties()));
-    // One chunk for all of the fragments because they have the
-    // same properties.
-    EXPECT_EQ(chunks[1],
-              PaintChunk(1, 4, PaintChunk::Id(container, kBackgroundType),
-                         DefaultPaintChunkProperties()));
-    EXPECT_EQ(chunks[2], PaintChunk(4, 5, PaintChunk::Id(root, kForegroundType),
-                                    DefaultPaintChunkProperties()));
+    EXPECT_THAT(
+        GetPaintController().PaintChunks(),
+        ElementsAre(
+            IsPaintChunk(0, 1, PaintChunk::Id(root, kBackgroundType),
+                         DefaultPaintChunkProperties()),
+            // One chunk for all of the fragments because they have the
+            // same properties.
+            IsPaintChunk(1, 4, PaintChunk::Id(container, kBackgroundType),
+                         DefaultPaintChunkProperties()),
+            IsPaintChunk(4, 5, PaintChunk::Id(root, kForegroundType),
+                         DefaultPaintChunkProperties())));
   };
   // Check results of the first paint.
   check_paint_results();
@@ -965,44 +924,45 @@
   FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
   GraphicsContext context(GetPaintController());
 
+  PaintChunk::Id container1_id(container1, kBackgroundType);
   auto container1_effect = CreateOpacityEffect(e0(), 0.5);
   auto container1_properties = DefaultPaintChunkProperties();
   container1_properties.SetEffect(container1_effect.get());
 
+  PaintChunk::Id container2_id(container2, kBackgroundType);
   auto container2_effect = CreateOpacityEffect(e0(), 0.5);
   auto container2_properties = DefaultPaintChunkProperties();
   container2_properties.SetEffect(container2_effect.get());
 
-  GetPaintController().UpdateCurrentPaintChunkProperties(
-      PaintChunk::Id(container1, kBackgroundType), container1_properties);
+  GetPaintController().UpdateCurrentPaintChunkProperties(container1_id,
+                                                         container1_properties);
   DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
   DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
-  GetPaintController().UpdateCurrentPaintChunkProperties(
-      PaintChunk::Id(container2, kBackgroundType), container2_properties);
+  GetPaintController().UpdateCurrentPaintChunkProperties(container2_id,
+                                                         container2_properties);
   DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
   DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType)));
 
-  EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
-  EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
-            GetPaintController().PaintChunks()[0].id);
-  EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
-            GetPaintController().PaintChunks()[1].id);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 2, container1_id, container1_properties),
+                  IsPaintChunk(2, 4, container2_id, container2_properties)));
 
   // Move content2 into container1, without invalidation.
-  GetPaintController().UpdateCurrentPaintChunkProperties(
-      PaintChunk::Id(container1, kBackgroundType), container1_properties);
+  GetPaintController().UpdateCurrentPaintChunkProperties(container1_id,
+                                                         container1_properties);
   DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
   DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
   DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
-  GetPaintController().UpdateCurrentPaintChunkProperties(
-      PaintChunk::Id(container2, kBackgroundType), container2_properties);
+  GetPaintController().UpdateCurrentPaintChunkProperties(container2_id,
+                                                         container2_properties);
   DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
 
   EXPECT_EQ(4, NumCachedNewItems());
@@ -1014,17 +974,16 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType),
-                      TestDisplayItem(container2, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType),
+                          IsSameId(&container2, kBackgroundType)));
 
-  EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
-  EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
-            GetPaintController().PaintChunks()[0].id);
-  EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
-            GetPaintController().PaintChunks()[1].id);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 3, container1_id, container1_properties),
+                  IsPaintChunk(3, 4, container2_id, container2_properties)));
 }
 
 TEST_P(PaintControllerTest, OutOfOrderNoCrash) {
@@ -1065,71 +1024,73 @@
   FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
   GraphicsContext context(GetPaintController());
 
+  PaintChunk::Id container1_background_id(container1, kBackgroundType);
   auto container1_effect = CreateOpacityEffect(e0(), 0.5);
   auto container1_background_properties = DefaultPaintChunkProperties();
   container1_background_properties.SetEffect(container1_effect.get());
+  PaintChunk::Id container1_foreground_id(container1, kForegroundType);
   auto container1_foreground_properties = DefaultPaintChunkProperties();
   container1_foreground_properties.SetEffect(container1_effect.get());
 
+  PaintChunk::Id content1_id(content1, kBackgroundType);
   auto content1_effect = CreateOpacityEffect(e0(), 0.6);
   auto content1_properties = DefaultPaintChunkProperties();
   content1_properties.SetEffect(content1_effect.get());
 
+  PaintChunk::Id container2_background_id(container2, kBackgroundType);
   auto container2_effect = CreateOpacityEffect(e0(), 0.7);
   auto container2_background_properties = DefaultPaintChunkProperties();
   container2_background_properties.SetEffect(container2_effect.get());
 
+  PaintChunk::Id content2_id(content2, kBackgroundType);
   auto content2_effect = CreateOpacityEffect(e0(), 0.8);
   auto content2_properties = DefaultPaintChunkProperties();
   content2_properties.SetEffect(content2_effect.get());
 
   {
-    GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(container1, kBackgroundType),
-        container1_background_properties);
     SubsequenceRecorder r(context, container1);
+    GetPaintController().UpdateCurrentPaintChunkProperties(
+        container1_background_id, container1_background_properties);
     DrawRect(context, container1, kBackgroundType,
              FloatRect(100, 100, 100, 100));
 
     {
-      GetPaintController().UpdateCurrentPaintChunkProperties(
-          PaintChunk::Id(content1, kBackgroundType), content1_properties);
       SubsequenceRecorder r(context, content1);
+      GetPaintController().UpdateCurrentPaintChunkProperties(
+          content1_id, content1_properties);
       DrawRect(context, content1, kBackgroundType,
                FloatRect(100, 100, 50, 200));
       DrawRect(context, content1, kForegroundType,
                FloatRect(100, 100, 50, 200));
     }
     GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(container1, kForegroundType),
-        container1_foreground_properties);
+        container1_foreground_id, container1_foreground_properties);
     DrawRect(context, container1, kForegroundType,
              FloatRect(100, 100, 100, 100));
   }
   {
-    GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(container2, kBackgroundType),
-        container2_background_properties);
     SubsequenceRecorder r(context, container2);
+    GetPaintController().UpdateCurrentPaintChunkProperties(
+        container2_background_id, container2_background_properties);
     DrawRect(context, container2, kBackgroundType,
              FloatRect(100, 200, 100, 100));
     {
-      GetPaintController().UpdateCurrentPaintChunkProperties(
-          PaintChunk::Id(content2, kBackgroundType), content2_properties);
       SubsequenceRecorder r(context, content2);
+      GetPaintController().UpdateCurrentPaintChunkProperties(
+          content2_id, content2_properties);
       DrawRect(context, content2, kBackgroundType,
                FloatRect(100, 200, 50, 200));
     }
   }
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
-                      TestDisplayItem(container1, kBackgroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType),
-                      TestDisplayItem(container2, kBackgroundType),
-                      TestDisplayItem(content2, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&container1, kBackgroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType),
+                          IsSameId(&container2, kBackgroundType),
+                          IsSameId(&content2, kBackgroundType)));
 
   auto* markers = GetSubsequenceMarkers(container1);
   CHECK(markers);
@@ -1151,17 +1112,16 @@
   EXPECT_EQ(5u, markers->start);
   EXPECT_EQ(6u, markers->end);
 
-  EXPECT_EQ(5u, GetPaintController().PaintChunks().size());
-  EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
-            GetPaintController().PaintChunks()[0].id);
-  EXPECT_EQ(PaintChunk::Id(content1, kBackgroundType),
-            GetPaintController().PaintChunks()[1].id);
-  EXPECT_EQ(PaintChunk::Id(container1, kForegroundType),
-            GetPaintController().PaintChunks()[2].id);
-  EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
-            GetPaintController().PaintChunks()[3].id);
-  EXPECT_EQ(PaintChunk::Id(content2, kBackgroundType),
-            GetPaintController().PaintChunks()[4].id);
+  EXPECT_THAT(
+      GetPaintController().PaintChunks(),
+      ElementsAre(IsPaintChunk(0, 1, container1_background_id,
+                               container1_background_properties),
+                  IsPaintChunk(1, 3, content1_id, content1_properties),
+                  IsPaintChunk(3, 4, container1_foreground_id,
+                               container1_foreground_properties),
+                  IsPaintChunk(4, 5, container2_background_id,
+                               container2_background_properties),
+                  IsPaintChunk(5, 6, content2_id, content2_properties)));
 
   // Invalidate container1 but not content1.
   container1.Invalidate();
@@ -1177,16 +1137,16 @@
       SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, content2));
   // Content2 now outputs foreground only.
   {
-    GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(content2, kForegroundType), content2_properties);
     SubsequenceRecorder r(context, content2);
+    GetPaintController().UpdateCurrentPaintChunkProperties(content2_id,
+                                                           content2_properties);
     DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
   }
   // Repaint container1 with foreground only.
   {
+    SubsequenceRecorder r(context, container1);
     EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
         context, container1));
-    SubsequenceRecorder r(context, container1);
     // Use cached subsequence of content1.
     if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
       // When under-invalidation-checking is enabled,
@@ -1194,9 +1154,9 @@
       // expected to create the same painting as in the previous paint.
       EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
           context, content1));
-        GetPaintController().UpdateCurrentPaintChunkProperties(
-            PaintChunk::Id(content1, kBackgroundType), content1_properties);
       SubsequenceRecorder r(context, content1);
+      GetPaintController().UpdateCurrentPaintChunkProperties(
+          content1_id, content1_properties);
       DrawRect(context, content1, kBackgroundType,
                FloatRect(100, 100, 50, 200));
       DrawRect(context, content1, kForegroundType,
@@ -1206,8 +1166,7 @@
           context, content1));
     }
     GetPaintController().UpdateCurrentPaintChunkProperties(
-        PaintChunk::Id(container1, kForegroundType),
-        container1_foreground_properties);
+        container1_foreground_id, container1_foreground_properties);
     DrawRect(context, container1, kForegroundType,
              FloatRect(100, 100, 100, 100));
   }
@@ -1221,11 +1180,11 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(content2, kForegroundType),
-                      TestDisplayItem(content1, kBackgroundType),
-                      TestDisplayItem(content1, kForegroundType),
-                      TestDisplayItem(container1, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&content2, kForegroundType),
+                          IsSameId(&content1, kBackgroundType),
+                          IsSameId(&content1, kForegroundType),
+                          IsSameId(&container1, kForegroundType)));
 
   markers = GetSubsequenceMarkers(content2);
   CHECK(markers);
@@ -1242,13 +1201,11 @@
   EXPECT_EQ(1u, markers->start);
   EXPECT_EQ(3u, markers->end);
 
-  EXPECT_EQ(3u, GetPaintController().PaintChunks().size());
-  EXPECT_EQ(PaintChunk::Id(content2, kForegroundType),
-            GetPaintController().PaintChunks()[0].id);
-  EXPECT_EQ(PaintChunk::Id(content1, kBackgroundType),
-            GetPaintController().PaintChunks()[1].id);
-  EXPECT_EQ(PaintChunk::Id(container1, kForegroundType),
-            GetPaintController().PaintChunks()[2].id);
+  EXPECT_THAT(GetPaintController().PaintChunks(),
+              ElementsAre(IsPaintChunk(0, 1, content2_id, content2_properties),
+                          IsPaintChunk(1, 3, content1_id, content1_properties),
+                          IsPaintChunk(3, 4, container1_foreground_id,
+                                       container1_foreground_properties)));
 }
 
 TEST_P(PaintControllerTest, SkipCache) {
@@ -1270,10 +1227,10 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(multicol, kBackgroundType),
-                      TestDisplayItem(content, kForegroundType),
-                      TestDisplayItem(content, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&multicol, kBackgroundType),
+                          IsSameId(&content, kForegroundType),
+                          IsSameId(&content, kForegroundType)));
   sk_sp<const PaintRecord> record1 =
       static_cast<const DrawingDisplayItem&>(
           GetPaintController().GetDisplayItemList()[1])
@@ -1283,8 +1240,7 @@
           GetPaintController().GetDisplayItemList()[2])
           .GetPaintRecord();
   EXPECT_NE(record1, record2);
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_DEFAULT_ROOT_CHUNK(3);
 
   InitRootChunk();
   // Draw again with nothing invalidated.
@@ -1305,18 +1261,17 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(multicol, kBackgroundType),
-                      TestDisplayItem(content, kForegroundType),
-                      TestDisplayItem(content, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&multicol, kBackgroundType),
+                          IsSameId(&content, kForegroundType),
+                          IsSameId(&content, kForegroundType)));
   EXPECT_NE(record1, static_cast<const DrawingDisplayItem&>(
                          GetPaintController().GetDisplayItemList()[1])
                          .GetPaintRecord());
   EXPECT_NE(record2, static_cast<const DrawingDisplayItem&>(
                          GetPaintController().GetDisplayItemList()[2])
                          .GetPaintRecord());
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_DEFAULT_ROOT_CHUNK(3);
 
   InitRootChunk();
   // Now the multicol becomes 3 columns and repaints.
@@ -1330,11 +1285,11 @@
   GetPaintController().EndSkippingCache();
 
   // We should repaint everything on invalidation of the scope container.
-  EXPECT_DISPLAY_LIST(GetPaintController().NewDisplayItemList(), 4,
-                      TestDisplayItem(multicol, kBackgroundType),
-                      TestDisplayItem(content, kForegroundType),
-                      TestDisplayItem(content, kForegroundType),
-                      TestDisplayItem(content, kForegroundType));
+  EXPECT_THAT(GetPaintController().NewDisplayItemList(),
+              ElementsAre(IsSameId(&multicol, kBackgroundType),
+                          IsSameId(&content, kForegroundType),
+                          IsSameId(&content, kForegroundType),
+                          IsSameId(&content, kForegroundType)));
   EXPECT_NE(record1, static_cast<const DrawingDisplayItem&>(
                          GetPaintController().NewDisplayItemList()[1])
                          .GetPaintRecord());
@@ -1343,8 +1298,7 @@
                          .GetPaintRecord());
 
   CommitAndFinishCycle();
-
-  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_DEFAULT_ROOT_CHUNK(4);
 }
 
 TEST_P(PaintControllerTest, PartialSkipCache) {
@@ -1364,10 +1318,10 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(content, kBackgroundType),
-                      TestDisplayItem(content, kForegroundType),
-                      TestDisplayItem(content, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&content, kBackgroundType),
+                          IsSameId(&content, kForegroundType),
+                          IsSameId(&content, kForegroundType)));
   sk_sp<const PaintRecord> record0 =
       static_cast<const DrawingDisplayItem&>(
           GetPaintController().GetDisplayItemList()[0])
@@ -1404,10 +1358,10 @@
 
   CommitAndFinishCycle();
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
-                      TestDisplayItem(content, kBackgroundType),
-                      TestDisplayItem(content, kForegroundType),
-                      TestDisplayItem(content, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&content, kBackgroundType),
+                          IsSameId(&content, kForegroundType),
+                          IsSameId(&content, kForegroundType)));
   EXPECT_NE(record0, static_cast<const DrawingDisplayItem&>(
                          GetPaintController().GetDisplayItemList()[0])
                          .GetPaintRecord());
@@ -1542,11 +1496,11 @@
 
   EXPECT_EQ(0, NumCachedNewItems());
   CommitAndFinishCycle();
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(third, kBackgroundType),
-                      TestDisplayItem(fourth, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&third, kBackgroundType),
+                          IsSameId(&fourth, kBackgroundType)));
   EXPECT_TRUE(first.IsValid());
   EXPECT_TRUE(second.IsValid());
   EXPECT_TRUE(third.IsValid());
@@ -1567,9 +1521,9 @@
 #endif
 
   CommitAndFinishCycle();
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(third, kBackgroundType),
-                      TestDisplayItem(fourth, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&third, kBackgroundType),
+                          IsSameId(&fourth, kBackgroundType)));
   EXPECT_TRUE(first.IsValid());
   EXPECT_TRUE(second.IsValid());
   EXPECT_TRUE(third.IsValid());
@@ -1591,11 +1545,11 @@
 #endif
 
   CommitAndFinishCycle();
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
-                      TestDisplayItem(first, kBackgroundType),
-                      TestDisplayItem(second, kBackgroundType),
-                      TestDisplayItem(third, kBackgroundType),
-                      TestDisplayItem(fourth, kBackgroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&first, kBackgroundType),
+                          IsSameId(&second, kBackgroundType),
+                          IsSameId(&third, kBackgroundType),
+                          IsSameId(&fourth, kBackgroundType)));
   EXPECT_TRUE(first.IsValid());
   EXPECT_TRUE(second.IsValid());
   EXPECT_TRUE(third.IsValid());
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
index 2ec882b5..1d5e6c4 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CONTROLLER_TEST_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CONTROLLER_TEST_H_
 
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -17,12 +18,6 @@
 
 class PaintControllerTestBase : public testing::Test {
  public:
-  PaintControllerTestBase()
-      : root_paint_property_client_("root"),
-        root_paint_chunk_id_(root_paint_property_client_,
-                             DisplayItem::kUninitializedType),
-        paint_controller_(PaintController::Create()) {}
-
   static void DrawNothing(GraphicsContext& context,
                           const DisplayItemClient& client,
                           DisplayItem::Type type) {
@@ -42,13 +37,22 @@
     context.DrawRect(RoundedIntRect(FloatRect(bounds)));
   }
 
+ protected:
+  PaintControllerTestBase()
+      : root_paint_property_client_("root"),
+        root_paint_chunk_id_(root_paint_property_client_,
+                             DisplayItem::kUninitializedType),
+        paint_controller_(PaintController::Create()) {}
+
   void InitRootChunk() { InitRootChunk(GetPaintController()); }
   void InitRootChunk(PaintController& paint_controller) {
     paint_controller.UpdateCurrentPaintChunkProperties(
         root_paint_chunk_id_, DefaultPaintChunkProperties());
   }
+  const PaintChunk::Id DefaultRootChunkId() const {
+    return root_paint_chunk_id_;
+  }
 
- protected:
   PaintController& GetPaintController() { return *paint_controller_; }
 
   int NumCachedNewItems() const {
@@ -92,37 +96,39 @@
   std::unique_ptr<PaintController> paint_controller_;
 };
 
-class TestDisplayItem final : public DisplayItem {
- public:
-  TestDisplayItem(const DisplayItemClient& client, Type type)
-      : DisplayItem(client, type, sizeof(*this)) {}
+// Matcher for checking display item list. Sample usage:
+// EXPECT_THAT(paint_controller.GetDisplayItemList(),
+//             ElementsAre(IsSameId(client1, kBackgroundType),
+//                         IsSameId(client2, kForegroundType)));
+MATCHER_P(IsSameId, id, "") {
+  return arg.GetId() == id;
+}
+MATCHER_P2(IsSameId, client, type, "") {
+  return arg.GetId() == DisplayItem::Id(*client, type);
+}
 
-  void Replay(GraphicsContext&) const final { NOTREACHED(); }
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const final {
-    NOTREACHED();
-  }
-};
-
-#define EXPECT_DISPLAY_LIST(actual, expected_size, ...)                   \
-  do {                                                                    \
-    EXPECT_EQ((size_t)expected_size, actual.size());                      \
-    if (expected_size != actual.size())                                   \
-      break;                                                              \
-    const TestDisplayItem expected[] = {__VA_ARGS__};                     \
-    for (size_t i = 0; i < expected_size; ++i) {                          \
-      SCOPED_TRACE(                                                       \
-          String::Format("%d: Expected:(client=%p:\"%s\" type=%d) "       \
-                         "Actual:(client=%p:%s type=%d)",                 \
-                         (int)i, &expected[i].Client(),                   \
-                         expected[i].Client().DebugName().Ascii().data(), \
-                         (int)expected[i].GetType(), &actual[i].Client(), \
-                         actual[i].Client().DebugName().Ascii().data(),   \
-                         (int)actual[i].GetType()));                      \
-      EXPECT_EQ(&expected[i].Client(), &actual[i].Client());              \
-      EXPECT_EQ(expected[i].GetType(), actual[i].GetType());              \
-    }                                                                     \
-  } while (false);
+// Matcher for checking paint chunks. Sample usage:
+// EXPACT_THAT(paint_controller.PaintChunks(),
+//             ELementsAre(IsPaintChunk(0, 1, id1, properties1),
+//                         IsPaintChunk(1, 3, id2, properties2)));
+inline bool CheckChunk(const PaintChunk& chunk,
+                       size_t begin,
+                       size_t end,
+                       const PaintChunk::Id& id,
+                       const PropertyTreeState& properties,
+                       const HitTestData* hit_test_data = nullptr) {
+  return chunk.begin_index == begin && chunk.end_index == end &&
+         chunk.id == id && chunk.properties == properties &&
+         ((!chunk.GetHitTestData() && !hit_test_data) ||
+          (chunk.GetHitTestData() && hit_test_data &&
+           *chunk.GetHitTestData() == *hit_test_data));
+}
+MATCHER_P4(IsPaintChunk, begin, end, id, properties, "") {
+  return CheckChunk(arg, begin, end, id, properties);
+}
+MATCHER_P5(IsPaintChunk, begin, end, id, properties, hit_test_data, "") {
+  return CheckChunk(arg, begin, end, id, properties, &hit_test_data);
+}
 
 // Shorter names for frequently used display item types in tests.
 const DisplayItem::Type kBackgroundType = DisplayItem::kBoxDecorationBackground;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc b/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc
index baac60e..712f046 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
 
 using testing::_;
+using testing::ElementsAre;
 
 namespace blink {
 
@@ -27,9 +28,9 @@
   EXPECT_CALL(canvas, drawPicture(_)).Times(1);
   builder.EndRecording(canvas);
 
-  EXPECT_DISPLAY_LIST(context.GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(client, kBackgroundType),
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(context.GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType),
+                          IsSameId(&client, kForegroundType)));
   EXPECT_FALSE(ClientCacheIsValid(context.GetPaintController(), client));
 }
 
@@ -51,9 +52,9 @@
   builder.EndRecording(canvas);
   EXPECT_TRUE(ClientCacheIsValid(client));
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(client, kBackgroundType),
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType),
+                          IsSameId(&client, kForegroundType)));
 
   InitRootChunk();
   EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
@@ -63,9 +64,9 @@
   EXPECT_CALL(canvas, drawPicture(_)).Times(1);
   builder.EndRecording(canvas);
 
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(client, kBackgroundType),
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType),
+                          IsSameId(&client, kForegroundType)));
   EXPECT_TRUE(ClientCacheIsValid(client));
 }
 
@@ -77,9 +78,9 @@
   DrawRect(context, client, kBackgroundType, FloatRect(10, 10, 20, 20));
   DrawRect(context, client, kForegroundType, FloatRect(15, 15, 10, 10));
   CommitAndFinishCycle();
-  EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
-                      TestDisplayItem(client, kBackgroundType),
-                      TestDisplayItem(client, kForegroundType));
+  EXPECT_THAT(GetPaintController().GetDisplayItemList(),
+              ElementsAre(IsSameId(&client, kBackgroundType),
+                          IsSameId(&client, kForegroundType)));
   // EXPECT_TRUE(ClientCacheIsValid(client));
 
   PaintRecordBuilder builder;
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
index 6aa156a..77924ae6 100644
--- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
@@ -64,4 +64,8 @@
          Transform()->CacheMemoryUsageInBytes();
 }
 
+std::ostream& operator<<(std::ostream& os, const PropertyTreeState& state) {
+  return os << state.ToString().Utf8().data();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
index 366a720..2637cb3 100644
--- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
+++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
@@ -75,6 +75,9 @@
   return !(a == b);
 }
 
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&,
+                                         const PropertyTreeState&);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PROPERTY_TREE_STATE_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h
index c13b643..95bcacf2 100644
--- a/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -518,10 +518,8 @@
                                                                eagerly_sweep);
   }
 
-  // TODO(keishi): Delete new/delete after transition to MakeGarbageCollected is
-  // complete.
-  void* operator new(size_t size) { return Base::operator new(size); }
-  void operator delete(void* p) { return Base::operator delete(p); };
+  void* operator new(size_t size) = delete;
+  void operator delete(void* p) = delete;
   void* operator new[](size_t size) = delete;
   void operator delete[](void* p) = delete;
   void* operator new(size_t size, NotNullTag null_tag, void* location) {
diff --git a/third_party/blink/renderer/platform/heap/heap_compact_test.cc b/third_party/blink/renderer/platform/heap/heap_compact_test.cc
index bc50ef6..b38b72b 100644
--- a/third_party/blink/renderer/platform/heap/heap_compact_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_compact_test.cc
@@ -242,7 +242,7 @@
   ClearOutOldGarbage();
 
   IntWrapper* val = IntWrapper::Create(1, VectorsAreCompacted);
-  Persistent<IntVector> vector = new IntVector(10, val);
+  Persistent<IntVector> vector = MakeGarbageCollected<IntVector>(10, val);
   EXPECT_EQ(10u, vector->size());
 
   for (IntWrapper* item : *vector)
@@ -279,7 +279,8 @@
 
   using IntMapVector = HeapVector<IntMap>;
 
-  Persistent<IntMapVector> int_map_vector = new IntMapVector();
+  Persistent<IntMapVector> int_map_vector =
+      MakeGarbageCollected<IntMapVector>();
   for (size_t i = 0; i < 10; ++i) {
     IntMap map;
     for (wtf_size_t j = 0; j < 10; ++j) {
@@ -409,7 +410,7 @@
   Persistent<OrderedHashSet> set = new OrderedHashSet;
   for (int i = 0; i < 13; ++i) {
     IntWrapper* value = IntWrapper::Create(i);
-    IntVector* vector = new IntVector(19, value);
+    IntVector* vector = MakeGarbageCollected<IntVector>(19, value);
     set->insert(vector);
   }
   EXPECT_EQ(13u, set->size());
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc
index fa987f1..2ba9a35 100644
--- a/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -2399,7 +2399,8 @@
   // Try to allocate a HeapVectors larger than kMaxHeapObjectSize
   // (crbug.com/597953).
   wtf_size_t size = kMaxHeapObjectSize / sizeof(int);
-  Persistent<HeapVector<int>> vector = new HeapVector<int>(size);
+  Persistent<HeapVector<int>> vector =
+      MakeGarbageCollected<HeapVector<int>>(size);
   EXPECT_LE(size, vector->capacity());
 }
 
@@ -2620,12 +2621,12 @@
   Persistent<MemberSet> set = new MemberSet();
   Persistent<MemberSet> set2 = new MemberSet();
   Persistent<MemberCountedSet> set3 = new MemberCountedSet();
-  Persistent<MemberVector> vector = new MemberVector();
-  Persistent<MemberVector> vector2 = new MemberVector();
-  Persistent<VectorWU> vector_wu = new VectorWU();
-  Persistent<VectorWU> vector_wu2 = new VectorWU();
-  Persistent<VectorUW> vector_uw = new VectorUW();
-  Persistent<VectorUW> vector_uw2 = new VectorUW();
+  Persistent<MemberVector> vector = MakeGarbageCollected<MemberVector>();
+  Persistent<MemberVector> vector2 = MakeGarbageCollected<MemberVector>();
+  Persistent<VectorWU> vector_wu = MakeGarbageCollected<VectorWU>();
+  Persistent<VectorWU> vector_wu2 = MakeGarbageCollected<VectorWU>();
+  Persistent<VectorUW> vector_uw = MakeGarbageCollected<VectorUW>();
+  Persistent<VectorUW> vector_uw2 = MakeGarbageCollected<VectorUW>();
   Persistent<MemberDeque> deque = new MemberDeque();
   Persistent<MemberDeque> deque2 = new MemberDeque();
   Persistent<DequeWU> deque_wu = new DequeWU();
@@ -3185,7 +3186,7 @@
   IntWrapper::destructor_calls_ = 0;
 
   Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
-      new HeapVector<Member<IntWrapper>>;
+      MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
 
   typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper>> WeakStrong;
   typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeak;
@@ -3246,7 +3247,7 @@
   IntWrapper::destructor_calls_ = 0;
 
   Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
-      new HeapVector<Member<IntWrapper>>;
+      MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
 
   Persistent<Set> set1 = new Set();
   Persistent<Set> set2 = new Set();
@@ -3554,7 +3555,7 @@
   IntWrapper::destructor_calls_ = 0;
 
   Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
-      new HeapVector<Member<IntWrapper>>;
+      MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
 
   Persistent<WSSet> weak_strong = new WSSet();
   Persistent<SWSet> strong_weak = new SWSet();
@@ -3650,7 +3651,7 @@
       Persistent<WeakOrderedSet> weak_ordered_set = new WeakOrderedSet();
 
       Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
-          new HeapVector<Member<IntWrapper>>;
+          MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
       for (int i = 0; i < 128; i += 2) {
         IntWrapper* wrapped = IntWrapper::Create(i);
         IntWrapper* wrapped2 = IntWrapper::Create(i + 1);
@@ -4185,7 +4186,7 @@
   IntWrapper::destructor_calls_ = 0;
   typedef HeapVector<Member<IntWrapper>> IntVector;
   typedef HeapDeque<Member<IntWrapper>> IntDeque;
-  HeapVector<IntVector>* vector = new HeapVector<IntVector>();
+  HeapVector<IntVector>* vector = MakeGarbageCollected<HeapVector<IntVector>>();
   HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
 
   vector->push_back(IntVector());
@@ -4214,9 +4215,9 @@
   SimpleFinalizedObject::destructor_calls_ = 0;
   {
     Persistent<HeapVector<VectorObject, 2>> inline_vector =
-        new HeapVector<VectorObject, 2>;
+        MakeGarbageCollected<HeapVector<VectorObject, 2>>();
     Persistent<HeapVector<VectorObject>> outline_vector =
-        new HeapVector<VectorObject>;
+        MakeGarbageCollected<HeapVector<VectorObject>>();
     VectorObject i1, i2;
     inline_vector->push_back(i1);
     inline_vector->push_back(i2);
@@ -4226,7 +4227,7 @@
     outline_vector->push_back(o2);
 
     Persistent<HeapVector<VectorObjectInheritedTrace>> vector_inherited_trace =
-        new HeapVector<VectorObjectInheritedTrace>;
+        MakeGarbageCollected<HeapVector<VectorObjectInheritedTrace>>();
     VectorObjectInheritedTrace it1, it2;
     vector_inherited_trace->push_back(it1);
     vector_inherited_trace->push_back(it2);
@@ -5207,7 +5208,7 @@
       Persistent<IntWrapper> home = IntWrapper::Create(103);
       Persistent<IntWrapper> composite = IntWrapper::Create(91);
       Persistent<HeapVector<Member<IntWrapper>>> keep_alive =
-          new HeapVector<Member<IntWrapper>>();
+          MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
       for (int i = 0; i < 10000; i++) {
         IntWrapper* value = IntWrapper::Create(i);
         keep_alive->push_back(value);
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index b30c431..dbfdb4a 100644
--- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -1732,7 +1732,7 @@
 TEST(IncrementalMarkingTest, DropReferenceWithHeapCompaction) {
   using Store = HeapHashCountedSet<Member<Object>>;
 
-  Persistent<Store> persistent(new Store);
+  Persistent<Store> persistent(new Store());
   persistent->insert(Object::Create());
   IncrementalMarkingTestDriver driver(ThreadState::Current());
   HeapCompact::ScheduleCompactionGCForTesting(true);
@@ -1747,8 +1747,8 @@
 TEST(IncrementalMarkingTest, HasInlineCapacityCollectionWithHeapCompaction) {
   using Store = HeapVector<Member<Object>, 2>;
 
-  Persistent<Store> persistent(new Store);
-  Persistent<Store> persistent2(new Store);
+  Persistent<Store> persistent(MakeGarbageCollected<Store>());
+  Persistent<Store> persistent2(MakeGarbageCollected<Store>());
 
   IncrementalMarkingTestDriver driver(ThreadState::Current());
   HeapCompact::ScheduleCompactionGCForTesting(true);
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
index 811f4c65e..dbc8c6f 100644
--- a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
+++ b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
@@ -112,6 +112,10 @@
   traced_value_.AppendAsTraceFormat(out);
 }
 
+bool TracedValue::AppendToProto(ProtoAppender* appender) {
+  return traced_value_.AppendToProto(appender);
+}
+
 void TracedValue::EstimateTraceMemoryOverhead(
     base::trace_event::TraceEventMemoryOverhead* overhead) {
   traced_value_.EstimateTraceMemoryOverhead(overhead);
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
index 54070be2..1efbf63 100644
--- a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
+++ b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
@@ -52,6 +52,7 @@
   // ConvertableToTraceFormat
 
   void AppendAsTraceFormat(std::string*) const final;
+  bool AppendToProto(ProtoAppender* appender) final;
   void EstimateTraceMemoryOverhead(
       base::trace_event::TraceEventMemoryOverhead*) final;
 
diff --git a/third_party/blink/renderer/platform/loader/cors/cors.cc b/third_party/blink/renderer/platform/loader/cors/cors.cc
index 40e51eb..cb454f44 100644
--- a/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -87,9 +87,9 @@
     const SecurityOrigin& origin) {
   return network::cors::CheckAccess(
       response_url, response_status_code,
-      GetHeaderValue(response_header, HTTPNames::Access_Control_Allow_Origin),
+      GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
       GetHeaderValue(response_header,
-                     HTTPNames::Access_Control_Allow_Credentials),
+                     http_names::kAccessControlAllowCredentials),
       credentials_mode, AsUrlOrigin(origin));
 }
 
@@ -101,9 +101,9 @@
     const SecurityOrigin& origin) {
   return network::cors::CheckPreflightAccess(
       response_url, response_status_code,
-      GetHeaderValue(response_header, HTTPNames::Access_Control_Allow_Origin),
+      GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
       GetHeaderValue(response_header,
-                     HTTPNames::Access_Control_Allow_Credentials),
+                     http_names::kAccessControlAllowCredentials),
       actual_credentials_mode, AsUrlOrigin(origin));
 }
 
@@ -129,8 +129,8 @@
 
 base::Optional<network::CORSErrorStatus> CheckExternalPreflight(
     const HTTPHeaderMap& response_header) {
-  return network::cors::CheckExternalPreflight(GetHeaderValue(
-      response_header, HTTPNames::Access_Control_Allow_External));
+  return network::cors::CheckExternalPreflight(
+      GetHeaderValue(response_header, http_names::kAccessControlAllowExternal));
 }
 
 bool IsCORSEnabledRequestMode(network::mojom::FetchRequestMode request_mode) {
@@ -153,11 +153,11 @@
       network::cors::PreflightResult::Create(
           request_credentials_mode,
           GetOptionalHeaderValue(response_header_map,
-                                 HTTPNames::Access_Control_Allow_Methods),
+                                 http_names::kAccessControlAllowMethods),
           GetOptionalHeaderValue(response_header_map,
-                                 HTTPNames::Access_Control_Allow_Headers),
+                                 http_names::kAccessControlAllowHeaders),
           GetOptionalHeaderValue(response_header_map,
-                                 HTTPNames::Access_Control_Max_Age),
+                                 http_names::kAccessControlMaxAge),
           &error);
   if (error)
     return network::CORSErrorStatus(*error);
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
index 6c75b45..aa91bb4 100644
--- a/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
@@ -283,11 +283,11 @@
 TEST_F(MemoryCacheCorrectnessTest, FreshButNoCache) {
   ResourceResponse fresh200_nocache_response;
   fresh200_nocache_response.SetHTTPStatusCode(200);
-  fresh200_nocache_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_nocache_response.SetHTTPHeaderField(http_names::kDate,
                                                kOriginalRequestDateAsString);
-  fresh200_nocache_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_nocache_response.SetHTTPHeaderField(http_names::kExpires,
                                                kOneDayAfterOriginalRequest);
-  fresh200_nocache_response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+  fresh200_nocache_response.SetHTTPHeaderField(http_names::kCacheControl,
                                                "no-cache");
 
   MockResource* fresh200_nocache =
@@ -303,7 +303,7 @@
 
 TEST_F(MemoryCacheCorrectnessTest, RequestWithNoCache) {
   ResourceRequest no_cache_request;
-  no_cache_request.SetHTTPHeaderField(HTTPNames::Cache_Control, "no-cache");
+  no_cache_request.SetHTTPHeaderField(http_names::kCacheControl, "no-cache");
   no_cache_request.SetRequestorOrigin(GetSecurityOrigin());
   MockResource* no_cache_resource =
       ResourceFromResourceRequest(no_cache_request);
@@ -314,11 +314,11 @@
 TEST_F(MemoryCacheCorrectnessTest, FreshButNoStore) {
   ResourceResponse fresh200_nostore_response;
   fresh200_nostore_response.SetHTTPStatusCode(200);
-  fresh200_nostore_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_nostore_response.SetHTTPHeaderField(http_names::kDate,
                                                kOriginalRequestDateAsString);
-  fresh200_nostore_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_nostore_response.SetHTTPHeaderField(http_names::kExpires,
                                                kOneDayAfterOriginalRequest);
-  fresh200_nostore_response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+  fresh200_nostore_response.SetHTTPHeaderField(http_names::kCacheControl,
                                                "no-store");
 
   MockResource* fresh200_nostore =
@@ -334,7 +334,7 @@
 
 TEST_F(MemoryCacheCorrectnessTest, RequestWithNoStore) {
   ResourceRequest no_store_request;
-  no_store_request.SetHTTPHeaderField(HTTPNames::Cache_Control, "no-store");
+  no_store_request.SetHTTPHeaderField(http_names::kCacheControl, "no-store");
   no_store_request.SetRequestorOrigin(GetSecurityOrigin());
   MockResource* no_store_resource =
       ResourceFromResourceRequest(no_store_request);
@@ -348,11 +348,11 @@
   ResourceResponse fresh200_must_revalidate_response;
   fresh200_must_revalidate_response.SetHTTPStatusCode(200);
   fresh200_must_revalidate_response.SetHTTPHeaderField(
-      HTTPNames::Date, kOriginalRequestDateAsString);
+      http_names::kDate, kOriginalRequestDateAsString);
   fresh200_must_revalidate_response.SetHTTPHeaderField(
-      HTTPNames::Expires, kOneDayAfterOriginalRequest);
-  fresh200_must_revalidate_response.SetHTTPHeaderField(HTTPNames::Cache_Control,
-                                                       "must-revalidate");
+      http_names::kExpires, kOneDayAfterOriginalRequest);
+  fresh200_must_revalidate_response.SetHTTPHeaderField(
+      http_names::kCacheControl, "must-revalidate");
 
   MockResource* fresh200_must_revalidate =
       ResourceFromResourceResponse(fresh200_must_revalidate_response);
@@ -376,11 +376,12 @@
 
   ResourceResponse fresh301_response(redirect_url);
   fresh301_response.SetHTTPStatusCode(301);
-  fresh301_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh301_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh301_response.SetHTTPHeaderField(HTTPNames::Location,
+  fresh301_response.SetHTTPHeaderField(http_names::kLocation,
                                        kRedirectTargetUrlString);
-  fresh301_response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=600");
+  fresh301_response.SetHTTPHeaderField(http_names::kCacheControl,
+                                       "max-age=600");
 
   // Add the redirect to our request.
   ResourceRequest redirect_request = ResourceRequest(redirect_target_url);
@@ -390,9 +391,9 @@
   // Add the final response to our request.
   ResourceResponse fresh200_response(redirect_target_url);
   fresh200_response.SetHTTPStatusCode(200);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_response.SetHTTPHeaderField(http_names::kExpires,
                                        kOneDayAfterOriginalRequest);
 
   first_resource->SetResponse(fresh200_response);
@@ -417,9 +418,9 @@
 
   ResourceResponse stale301_response(redirect_url);
   stale301_response.SetHTTPStatusCode(301);
-  stale301_response.SetHTTPHeaderField(HTTPNames::Date,
+  stale301_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  stale301_response.SetHTTPHeaderField(HTTPNames::Location,
+  stale301_response.SetHTTPHeaderField(http_names::kLocation,
                                        kRedirectTargetUrlString);
 
   // Add the redirect to our request.
@@ -430,9 +431,9 @@
   // Add the final response to our request.
   ResourceResponse fresh200_response(redirect_target_url);
   fresh200_response.SetHTTPStatusCode(200);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_response.SetHTTPHeaderField(http_names::kExpires,
                                        kOneDayAfterOriginalRequest);
 
   first_resource->SetResponse(fresh200_response);
@@ -447,7 +448,7 @@
 
 TEST_F(MemoryCacheCorrectnessTest, PostToSameURLTwice) {
   ResourceRequest request1{KURL(kResourceURL)};
-  request1.SetHTTPMethod(HTTPNames::POST);
+  request1.SetHTTPMethod(http_names::kPOST);
   request1.SetRequestorOrigin(GetSecurityOrigin());
   RawResource* resource1 =
       RawResource::CreateForTest(request1, ResourceType::kRaw);
@@ -455,7 +456,7 @@
   AddResourceToMemoryCache(resource1);
 
   ResourceRequest request2{KURL(kResourceURL)};
-  request2.SetHTTPMethod(HTTPNames::POST);
+  request2.SetHTTPMethod(http_names::kPOST);
   request2.SetRequestorOrigin(GetSecurityOrigin());
   FetchParameters fetch2(request2);
   RawResource* resource2 = RawResource::FetchSynchronously(fetch2, Fetcher());
@@ -472,11 +473,11 @@
 
   ResourceResponse fresh302_response(redirect_url);
   fresh302_response.SetHTTPStatusCode(302);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh302_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Last_Modified,
+  fresh302_response.SetHTTPHeaderField(http_names::kLastModified,
                                        kOneDayBeforeOriginalRequest);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Location,
+  fresh302_response.SetHTTPHeaderField(http_names::kLocation,
                                        kRedirectTargetUrlString);
 
   // Add the redirect to our request.
@@ -487,9 +488,9 @@
   // Add the final response to our request.
   ResourceResponse fresh200_response(redirect_target_url);
   fresh200_response.SetHTTPStatusCode(200);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_response.SetHTTPHeaderField(http_names::kExpires,
                                        kOneDayAfterOriginalRequest);
 
   first_resource->SetResponse(fresh200_response);
@@ -513,10 +514,11 @@
 
   ResourceResponse fresh302_response(redirect_url);
   fresh302_response.SetHTTPStatusCode(302);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh302_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=600");
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Location,
+  fresh302_response.SetHTTPHeaderField(http_names::kCacheControl,
+                                       "max-age=600");
+  fresh302_response.SetHTTPHeaderField(http_names::kLocation,
                                        kRedirectTargetUrlString);
 
   // Add the redirect to our request.
@@ -527,9 +529,9 @@
   // Add the final response to our request.
   ResourceResponse fresh200_response(redirect_target_url);
   fresh200_response.SetHTTPStatusCode(200);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_response.SetHTTPHeaderField(http_names::kExpires,
                                        kOneDayAfterOriginalRequest);
 
   first_resource->SetResponse(fresh200_response);
@@ -553,11 +555,11 @@
 
   ResourceResponse fresh302_response(redirect_url);
   fresh302_response.SetHTTPStatusCode(302);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh302_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh302_response.SetHTTPHeaderField(http_names::kExpires,
                                        kOneDayAfterOriginalRequest);
-  fresh302_response.SetHTTPHeaderField(HTTPNames::Location,
+  fresh302_response.SetHTTPHeaderField(http_names::kLocation,
                                        kRedirectTargetUrlString);
 
   // Add the redirect to our request.
@@ -567,9 +569,9 @@
   // Add the final response to our request.
   ResourceResponse fresh200_response(redirect_target_url);
   fresh200_response.SetHTTPStatusCode(200);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Date,
+  fresh200_response.SetHTTPHeaderField(http_names::kDate,
                                        kOriginalRequestDateAsString);
-  fresh200_response.SetHTTPHeaderField(HTTPNames::Expires,
+  fresh200_response.SetHTTPHeaderField(http_names::kExpires,
                                        kOneDayAfterOriginalRequest);
 
   first_resource->SetResponse(fresh200_response);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc
index 062c3c78..69a9427 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -1072,7 +1072,7 @@
 
 bool Resource::MustReloadDueToVaryHeader(
     const ResourceRequest& new_request) const {
-  const AtomicString& vary = GetResponse().HttpHeaderField(HTTPNames::Vary);
+  const AtomicString& vary = GetResponse().HttpHeaderField(http_names::kVary);
   if (vary.IsNull())
     return false;
   if (vary == "*")
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 8c98a0f3..823f8d0 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -160,7 +160,7 @@
 static bool IsCacheableHTTPMethod(const AtomicString& method) {
   // Per http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.10,
   // these methods always invalidate the cache entry.
-  return method != HTTPNames::POST && method != HTTPNames::PUT &&
+  return method != http_names::kPOST && method != http_names::kPUT &&
          method != "DELETE";
 }
 
@@ -701,7 +701,7 @@
         resource_type, kImageNotImageSet, Context().IsMainFrame()));
   }
   if (resource_type == ResourceType::kLinkPrefetch)
-    resource_request.SetHTTPHeaderField(HTTPNames::Purpose, "prefetch");
+    resource_request.SetHTTPHeaderField(http_names::kPurpose, "prefetch");
 
   // Indicate whether the network stack can return a stale resource. If a
   // stale resource is returned a StaleRevalidation request will be scheduled.
@@ -712,7 +712,7 @@
   // critical.
   resource_request.SetAllowStaleResponse(
       stale_while_revalidate_enabled_ &&
-      resource_request.HttpMethod() == HTTPNames::GET &&
+      resource_request.HttpMethod() == http_names::kGET &&
       !IsRawResource(resource_type) && !params.IsStaleRevalidation());
 
   Context().AddAdditionalRequestHeaders(
@@ -955,24 +955,24 @@
   revalidating_request.SetIsRevalidating(true);
 
   const AtomicString& last_modified =
-      resource->GetResponse().HttpHeaderField(HTTPNames::Last_Modified);
+      resource->GetResponse().HttpHeaderField(http_names::kLastModified);
   const AtomicString& e_tag =
-      resource->GetResponse().HttpHeaderField(HTTPNames::ETag);
+      resource->GetResponse().HttpHeaderField(http_names::kETag);
   if (!last_modified.IsEmpty() || !e_tag.IsEmpty()) {
     DCHECK_NE(mojom::FetchCacheMode::kBypassCache,
               revalidating_request.GetCacheMode());
     if (revalidating_request.GetCacheMode() ==
         mojom::FetchCacheMode::kValidateCache) {
-      revalidating_request.SetHTTPHeaderField(HTTPNames::Cache_Control,
+      revalidating_request.SetHTTPHeaderField(http_names::kCacheControl,
                                               "max-age=0");
     }
   }
   if (!last_modified.IsEmpty()) {
-    revalidating_request.SetHTTPHeaderField(HTTPNames::If_Modified_Since,
+    revalidating_request.SetHTTPHeaderField(http_names::kIfModifiedSince,
                                             last_modified);
   }
   if (!e_tag.IsEmpty())
-    revalidating_request.SetHTTPHeaderField(HTTPNames::If_None_Match, e_tag);
+    revalidating_request.SetHTTPHeaderField(http_names::kIfNoneMatch, e_tag);
 
   resource->SetRevalidatingRequest(revalidating_request);
 }
@@ -1033,7 +1033,7 @@
 
   if (resource->IsCacheValidator()) {
     const AtomicString& timing_allow_origin =
-        resource->GetResponse().HttpHeaderField(HTTPNames::Timing_Allow_Origin);
+        resource->GetResponse().HttpHeaderField(http_names::kTimingAllowOrigin);
     if (!timing_allow_origin.IsEmpty())
       info->SetOriginalTimingAllowOrigin(timing_allow_origin);
   }
@@ -1630,7 +1630,7 @@
           WebString::FromUTF8(timing_info.alpn_negotiated_protocol));
       response.SetConnectionInfo(timing_info.connection_info);
       response.SetHTTPHeaderField(
-          HTTPNames::Timing_Allow_Origin,
+          http_names::kTimingAllowOrigin,
           WebString::FromUTF8(timing_info.timing_allow_origin));
       response.SetEncodedDataLength(timing_info.transfer_size);
       preflight_info->SetFinalResponse(response);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index db273b6..a859f6c 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -140,7 +140,7 @@
   KURL url("http://127.0.0.1:8000/foo.html");
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=3600");
   RegisterMockedURLLoadWithCustomResponse(url, response);
 
   FetchParameters fetch_params{ResourceRequest(url)};
@@ -167,7 +167,7 @@
   AddResourceToMemoryCache(resource);
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=3600");
   resource->ResponseReceived(response, nullptr);
   resource->FinishForTest();
 
@@ -200,8 +200,8 @@
 
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
-  response.SetHTTPHeaderField(HTTPNames::Vary, "*");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=3600");
+  response.SetHTTPHeaderField(http_names::kVary, "*");
   resource->ResponseReceived(response, nullptr);
   resource->FinishForTest();
   ASSERT_TRUE(resource->MustReloadDueToVaryHeader(ResourceRequest(url)));
@@ -268,8 +268,8 @@
 
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
-  response.SetHTTPHeaderField(HTTPNames::Vary, "*");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=3600");
+  response.SetHTTPHeaderField(http_names::kVary, "*");
   resource->ResponseReceived(response, nullptr);
   resource->FinishForTest();
   ASSERT_TRUE(resource->MustReloadDueToVaryHeader(ResourceRequest(url)));
@@ -288,8 +288,8 @@
   KURL url("http://127.0.0.1:8000/foo.html");
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
-  response.SetHTTPHeaderField(HTTPNames::Vary, "*");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=3600");
+  response.SetHTTPHeaderField(http_names::kVary, "*");
   RegisterMockedURLLoadWithCustomResponse(url, response);
 
   FetchParameters fetch_params_original{ResourceRequest(url)};
@@ -353,13 +353,13 @@
 
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
-  response.SetHTTPHeaderField(HTTPNames::ETag, "1234567890");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=3600");
+  response.SetHTTPHeaderField(http_names::kETag, "1234567890");
   RegisterMockedURLLoadWithCustomResponse(url, response);
 
   ResourceFetcher* fetcher1 = ResourceFetcher::Create(Context());
   ResourceRequest request1(url);
-  request1.SetHTTPHeaderField(HTTPNames::Cache_Control, "no-cache");
+  request1.SetHTTPHeaderField(http_names::kCacheControl, "no-cache");
   FetchParameters fetch_params1(request1);
   Persistent<RequestSameResourceOnComplete> client =
       new RequestSameResourceOnComplete(fetch_params1, fetcher1);
@@ -464,7 +464,7 @@
     WebURLResponse redirect_response;
     redirect_response.SetURL(redirect_url);
     redirect_response.SetHTTPStatusCode(301);
-    redirect_response.SetHTTPHeaderField(HTTPNames::Location, to_url);
+    redirect_response.SetHTTPHeaderField(http_names::kLocation, to_url);
     redirect_response.SetEncodedDataLength(kRedirectResponseOverheadBytes);
     Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
         redirect_url, redirect_response, "");
@@ -883,7 +883,7 @@
 
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+  response.SetHTTPHeaderField(http_names::kCacheControl,
                               "max-age=0, stale-while-revalidate=40");
 
   RegisterMockedURLLoadWithCustomResponse(url, response);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 4c5c35a..2af5efa 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -1176,7 +1176,7 @@
                                      const ResourceResponse& response) const {
   bool sniffing_allowed =
       ParseContentTypeOptionsHeader(response.HttpHeaderField(
-          HTTPNames::X_Content_Type_Options)) != kContentTypeOptionsNosniff;
+          http_names::kXContentTypeOptions)) != kContentTypeOptionsNosniff;
   if (sniffing_allowed)
     return base::nullopt;
 
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 1c8aaca..499ba65 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -48,7 +48,7 @@
 ResourceRequest::ResourceRequest(const KURL& url)
     : url_(url),
       timeout_interval_(default_timeout_interval_),
-      http_method_(HTTPNames::GET),
+      http_method_(http_names::kGET),
       allow_stored_credentials_(true),
       report_upload_progress_(false),
       report_raw_headers_(false),
@@ -203,25 +203,25 @@
 
 void ResourceRequest::SetHTTPReferrer(const Referrer& referrer) {
   if (referrer.referrer.IsEmpty())
-    http_header_fields_.Remove(HTTPNames::Referer);
+    http_header_fields_.Remove(http_names::kReferer);
   else
-    SetHTTPHeaderField(HTTPNames::Referer, referrer.referrer);
+    SetHTTPHeaderField(http_names::kReferer, referrer.referrer);
   referrer_policy_ = referrer.referrer_policy;
   did_set_http_referrer_ = true;
 }
 
 void ResourceRequest::ClearHTTPReferrer() {
-  http_header_fields_.Remove(HTTPNames::Referer);
+  http_header_fields_.Remove(http_names::kReferer);
   referrer_policy_ = kReferrerPolicyDefault;
   did_set_http_referrer_ = false;
 }
 
 void ResourceRequest::SetHTTPOrigin(const SecurityOrigin* origin) {
-  SetHTTPHeaderField(HTTPNames::Origin, origin->ToAtomicString());
+  SetHTTPHeaderField(http_names::kOrigin, origin->ToAtomicString());
 }
 
 void ResourceRequest::ClearHTTPOrigin() {
-  http_header_fields_.Remove(HTTPNames::Origin);
+  http_header_fields_.Remove(http_names::kOrigin);
 }
 
 void ResourceRequest::SetHTTPOriginIfNeeded(const SecurityOrigin* origin) {
@@ -232,13 +232,13 @@
 void ResourceRequest::SetHTTPOriginToMatchReferrerIfNeeded() {
   if (NeedsHTTPOrigin()) {
     SetHTTPOrigin(
-        SecurityOrigin::CreateFromString(HttpHeaderField(HTTPNames::Referer))
+        SecurityOrigin::CreateFromString(HttpHeaderField(http_names::kReferer))
             .get());
   }
 }
 
 void ResourceRequest::ClearHTTPUserAgent() {
-  http_header_fields_.Remove(HTTPNames::User_Agent);
+  http_header_fields_.Remove(http_names::kUserAgent);
 }
 
 EncodedFormData* ResourceRequest::HttpBody() const {
@@ -321,11 +321,11 @@
 }
 
 bool ResourceRequest::IsConditional() const {
-  return (http_header_fields_.Contains(HTTPNames::If_Match) ||
-          http_header_fields_.Contains(HTTPNames::If_Modified_Since) ||
-          http_header_fields_.Contains(HTTPNames::If_None_Match) ||
-          http_header_fields_.Contains(HTTPNames::If_Range) ||
-          http_header_fields_.Contains(HTTPNames::If_Unmodified_Since));
+  return (http_header_fields_.Contains(http_names::kIfMatch) ||
+          http_header_fields_.Contains(http_names::kIfModifiedSince) ||
+          http_header_fields_.Contains(http_names::kIfNoneMatch) ||
+          http_header_fields_.Contains(http_names::kIfRange) ||
+          http_header_fields_.Contains(http_names::kIfUnmodifiedSince));
 }
 
 void ResourceRequest::SetHasUserGesture(bool has_user_gesture) {
@@ -335,8 +335,8 @@
 const CacheControlHeader& ResourceRequest::GetCacheControlHeader() const {
   if (!cache_control_header_cache_.parsed) {
     cache_control_header_cache_ = ParseCacheControlDirectives(
-        http_header_fields_.Get(HTTPNames::Cache_Control),
-        http_header_fields_.Get(HTTPNames::Pragma));
+        http_header_fields_.Get(http_names::kCacheControl),
+        http_header_fields_.Get(http_names::kPragma));
   }
   return cache_control_header_cache_;
 }
@@ -350,8 +350,8 @@
 }
 
 bool ResourceRequest::HasCacheValidatorFields() const {
-  return !http_header_fields_.Get(HTTPNames::Last_Modified).IsEmpty() ||
-         !http_header_fields_.Get(HTTPNames::ETag).IsEmpty();
+  return !http_header_fields_.Get(http_names::kLastModified).IsEmpty() ||
+         !http_header_fields_.Get(http_names::kETag).IsEmpty();
 }
 
 bool ResourceRequest::NeedsHTTPOrigin() const {
@@ -364,7 +364,7 @@
   // will leak the internal host name. Similar privacy concerns have lead
   // to the widespread suppression of the Referer header at the network
   // layer.
-  if (HttpMethod() == HTTPNames::GET || HttpMethod() == HTTPNames::HEAD)
+  if (HttpMethod() == http_names::kGET || HttpMethod() == http_names::kHEAD)
     return false;
 
   // For non-GET and non-HEAD methods, always send an Origin header so the
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 c0d99958..28d96ee 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -127,17 +127,17 @@
   void ClearHTTPHeaderField(const AtomicString& name);
 
   const AtomicString& HttpContentType() const {
-    return HttpHeaderField(HTTPNames::Content_Type);
+    return HttpHeaderField(http_names::kContentType);
   }
   void SetHTTPContentType(const AtomicString& http_content_type) {
-    SetHTTPHeaderField(HTTPNames::Content_Type, http_content_type);
+    SetHTTPHeaderField(http_names::kContentType, http_content_type);
   }
 
   // TODO(domfarolino): Remove this once we stop storing the generated referrer
   // as a header, and instead use a separate member. See
   // https://crbug.com/850813.
   const AtomicString& HttpReferrer() const {
-    return HttpHeaderField(HTTPNames::Referer);
+    return HttpHeaderField(http_names::kReferer);
   }
   void SetHTTPReferrer(const Referrer&);
   bool DidSetHTTPReferrer() const { return did_set_http_referrer_; }
@@ -154,7 +154,7 @@
   const String& ReferrerString() const { return referrer_string_; }
 
   const AtomicString& HttpOrigin() const {
-    return HttpHeaderField(HTTPNames::Origin);
+    return HttpHeaderField(http_names::kOrigin);
   }
   void SetHTTPOrigin(const SecurityOrigin*);
   void ClearHTTPOrigin();
@@ -162,12 +162,12 @@
   void SetHTTPOriginToMatchReferrerIfNeeded();
 
   void SetHTTPUserAgent(const AtomicString& http_user_agent) {
-    SetHTTPHeaderField(HTTPNames::User_Agent, http_user_agent);
+    SetHTTPHeaderField(http_names::kUserAgent, http_user_agent);
   }
   void ClearHTTPUserAgent();
 
   void SetHTTPAccept(const AtomicString& http_accept) {
-    SetHTTPHeaderField(HTTPNames::Accept, http_accept);
+    SetHTTPHeaderField(http_names::kAccept, http_accept);
   }
 
   EncodedFormData* HttpBody() const;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
index 5405a2e..ae7b255 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -342,7 +342,7 @@
 
 bool ResourceResponse::IsAttachment() const {
   static const char kAttachmentString[] = "attachment";
-  String value = http_header_fields_.Get(HTTPNames::Content_Disposition);
+  String value = http_header_fields_.Get(http_names::kContentDisposition);
   size_t loc = value.find(';');
   if (loc != kNotFound)
     value = value.Left(loc);
@@ -352,7 +352,7 @@
 
 AtomicString ResourceResponse::HttpContentType() const {
   return ExtractMIMETypeFromMediaType(
-      HttpHeaderField(HTTPNames::Content_Type).DeprecatedLower());
+      HttpHeaderField(http_names::kContentType).DeprecatedLower());
 }
 
 bool ResourceResponse::WasCached() const {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
index 9788ff1b..a413ef18 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
@@ -105,46 +105,46 @@
   ResourceRequest new_request(url);
   EXPECT_FALSE(resource->MustReloadDueToVaryHeader(new_request));
 
-  response.SetHTTPHeaderField(HTTPNames::Vary, "*");
+  response.SetHTTPHeaderField(http_names::kVary, "*");
   resource->SetResponse(response);
   EXPECT_TRUE(resource->MustReloadDueToVaryHeader(new_request));
 
   // Irrelevant header
-  response.SetHTTPHeaderField(HTTPNames::Vary, "definitelynotarealheader");
+  response.SetHTTPHeaderField(http_names::kVary, "definitelynotarealheader");
   resource->SetResponse(response);
   EXPECT_FALSE(resource->MustReloadDueToVaryHeader(new_request));
 
   // Header present on new but not old
-  new_request.SetHTTPHeaderField(HTTPNames::User_Agent, "something");
-  response.SetHTTPHeaderField(HTTPNames::Vary, HTTPNames::User_Agent);
+  new_request.SetHTTPHeaderField(http_names::kUserAgent, "something");
+  response.SetHTTPHeaderField(http_names::kVary, http_names::kUserAgent);
   resource->SetResponse(response);
   EXPECT_TRUE(resource->MustReloadDueToVaryHeader(new_request));
-  new_request.ClearHTTPHeaderField(HTTPNames::User_Agent);
+  new_request.ClearHTTPHeaderField(http_names::kUserAgent);
 
   ResourceRequest old_request(url);
-  old_request.SetHTTPHeaderField(HTTPNames::User_Agent, "something");
-  old_request.SetHTTPHeaderField(HTTPNames::Referer, "http://foo.com");
+  old_request.SetHTTPHeaderField(http_names::kUserAgent, "something");
+  old_request.SetHTTPHeaderField(http_names::kReferer, "http://foo.com");
   resource = MockResource::Create(old_request);
   resource->ResponseReceived(response, nullptr);
   resource->FinishForTest();
 
   // Header present on old but not new
-  new_request.ClearHTTPHeaderField(HTTPNames::User_Agent);
-  response.SetHTTPHeaderField(HTTPNames::Vary, HTTPNames::User_Agent);
+  new_request.ClearHTTPHeaderField(http_names::kUserAgent);
+  response.SetHTTPHeaderField(http_names::kVary, http_names::kUserAgent);
   resource->SetResponse(response);
   EXPECT_TRUE(resource->MustReloadDueToVaryHeader(new_request));
 
   // Header present on both
-  new_request.SetHTTPHeaderField(HTTPNames::User_Agent, "something");
+  new_request.SetHTTPHeaderField(http_names::kUserAgent, "something");
   EXPECT_FALSE(resource->MustReloadDueToVaryHeader(new_request));
 
   // One matching, one mismatching
-  response.SetHTTPHeaderField(HTTPNames::Vary, "User-Agent, Referer");
+  response.SetHTTPHeaderField(http_names::kVary, "User-Agent, Referer");
   resource->SetResponse(response);
   EXPECT_TRUE(resource->MustReloadDueToVaryHeader(new_request));
 
   // Two matching
-  new_request.SetHTTPHeaderField(HTTPNames::Referer, "http://foo.com");
+  new_request.SetHTTPHeaderField(http_names::kReferer, "http://foo.com");
   EXPECT_FALSE(resource->MustReloadDueToVaryHeader(new_request));
 }
 
@@ -431,7 +431,7 @@
   const KURL url("http://127.0.0.1:8000/foo.html");
   ResourceResponse response(url);
   response.SetHTTPStatusCode(200);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+  response.SetHTTPHeaderField(http_names::kCacheControl,
                               "max-age=0, stale-while-revalidate=40");
 
   MockResource* resource = MockResource::Create(url);
@@ -458,7 +458,7 @@
   const KURL url("http://127.0.0.1:8000/foo.html");
   const KURL redirect_target_url("http://127.0.0.1:8000/food.html");
   ResourceResponse response(url);
-  response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=50");
+  response.SetHTTPHeaderField(http_names::kCacheControl, "max-age=50");
   response.SetHTTPStatusCode(200);
 
   // The revalidating request is redirected.
@@ -466,7 +466,7 @@
   redirect_response.SetHTTPHeaderField(
       "location", AtomicString(redirect_target_url.GetString()));
   redirect_response.SetHTTPStatusCode(302);
-  redirect_response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+  redirect_response.SetHTTPHeaderField(http_names::kCacheControl,
                                        "max-age=0, stale-while-revalidate=40");
   redirect_response.SetAsyncRevalidationRequested(true);
   ResourceRequest redirected_revalidating_request(redirect_target_url);
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index b6b298b..2048446 100644
--- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -10,7 +10,6 @@
   "//mojo/public/cpp/base/unguessable_token.typemap",
   "//third_party/blink/renderer/core/messaging/blink_cloneable_message.typemap",
   "//third_party/blink/renderer/core/messaging/blink_transferable_message.typemap",
-  "//third_party/blink/renderer/modules/indexeddb/indexed_db.typemap",
   "//third_party/blink/renderer/platform/blob/serialized_blob.typemap",
   "//third_party/blink/renderer/platform/mojo/big_buffer.typemap",
   "//third_party/blink/renderer/platform/mojo/big_string.typemap",
diff --git a/third_party/blink/renderer/platform/network/content_security_policy_response_headers.cc b/third_party/blink/renderer/platform/network/content_security_policy_response_headers.cc
index f19a8487e..83a957a4 100644
--- a/third_party/blink/renderer/platform/network/content_security_policy_response_headers.cc
+++ b/third_party/blink/renderer/platform/network/content_security_policy_response_headers.cc
@@ -42,9 +42,9 @@
 ContentSecurityPolicyResponseHeaders::ContentSecurityPolicyResponseHeaders(
     const HTTPHeaderMap& headers,
     bool should_parse_wasm_eval)
-    : content_security_policy_(headers.Get(HTTPNames::Content_Security_Policy)),
+    : content_security_policy_(headers.Get(http_names::kContentSecurityPolicy)),
       content_security_policy_report_only_(
-          headers.Get(HTTPNames::Content_Security_Policy_Report_Only)),
+          headers.Get(http_names::kContentSecurityPolicyReportOnly)),
       should_parse_wasm_eval_(should_parse_wasm_eval) {}
 
 ContentSecurityPolicyResponseHeaders
diff --git a/third_party/blink/renderer/platform/network/http_names.json5 b/third_party/blink/renderer/platform/network/http_names.json5
index e12b5fe..ca872fe 100644
--- a/third_party/blink/renderer/platform/network/http_names.json5
+++ b/third_party/blink/renderer/platform/network/http_names.json5
@@ -1,6 +1,6 @@
 {
   metadata: {
-    namespace: "HTTP",
+    namespace: "http_names",
     export: "PLATFORM_EXPORT",
   },
 
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc
index 2c1ab2e..9057bd1 100644
--- a/third_party/blink/renderer/platform/network/http_parsers.cc
+++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -646,7 +646,7 @@
 
   // Copy selected header fields.
   const AtomicString* const headerNamePointers[] = {
-      &HTTPNames::Content_Disposition, &HTTPNames::Content_Type};
+      &http_names::kContentDisposition, &http_names::kContentType};
   for (const AtomicString* headerNamePointer : headerNamePointers) {
     StringUTF8Adaptor adaptor(*headerNamePointer);
     size_t iterator = 0;
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
index 0a52588..f1a23b5 100644
--- a/third_party/blink/renderer/platform/testing/testing_platform_support.cc
+++ b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -110,6 +110,10 @@
   return old_platform_ ? old_platform_->GetBlobRegistry() : nullptr;
 }
 
+std::unique_ptr<WebIDBFactory> TestingPlatformSupport::CreateIdbFactory() {
+  return old_platform_ ? old_platform_->CreateIdbFactory() : nullptr;
+}
+
 WebURLLoaderMockFactory* TestingPlatformSupport::GetURLLoaderMockFactory() {
   return old_platform_ ? old_platform_->GetURLLoaderMockFactory() : nullptr;
 }
@@ -182,7 +186,7 @@
   ThreadState::AttachMainThread();
   ThreadState::Current()->RegisterTraceDOMWrappers(nullptr, nullptr, nullptr,
                                                    nullptr);
-  HTTPNames::init();
+  http_names::init();
   FetchInitiatorTypeNames::init();
 
   InitializePlatformLanguage();
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.h b/third_party/blink/renderer/platform/testing/testing_platform_support.h
index 38bf520..87cfa93 100644
--- a/third_party/blink/renderer/platform/testing/testing_platform_support.h
+++ b/third_party/blink/renderer/platform/testing/testing_platform_support.h
@@ -61,6 +61,7 @@
   // Platform:
   WebString DefaultLocale() override;
   WebBlobRegistry* GetBlobRegistry() override;
+  std::unique_ptr<WebIDBFactory> CreateIdbFactory() override;
   WebURLLoaderMockFactory* GetURLLoaderMockFactory() override;
   std::unique_ptr<blink::WebURLLoaderFactory> CreateDefaultURLLoaderFactory()
       override;
diff --git a/third_party/blink/renderer/platform/testing/url_test_helpers.cc b/third_party/blink/renderer/platform/testing/url_test_helpers.cc
index b7e6f777..1548d0f 100644
--- a/third_party/blink/renderer/platform/testing/url_test_helpers.cc
+++ b/third_party/blink/renderer/platform/testing/url_test_helpers.cc
@@ -70,7 +70,7 @@
 
   WebURLResponse response(full_url);
   response.SetMIMEType(mime_type);
-  response.SetHTTPHeaderField(HTTPNames::Content_Type, mime_type);
+  response.SetHTTPHeaderField(http_names::kContentType, mime_type);
   response.SetHTTPStatusCode(200);
   response.SetLoadTiming(timing);
 
@@ -83,7 +83,7 @@
 
   WebURLResponse response;
   response.SetMIMEType("image/png");
-  response.SetHTTPHeaderField(HTTPNames::Content_Type, "image/png");
+  response.SetHTTPHeaderField(http_names::kContentType, "image/png");
   response.SetHTTPStatusCode(404);
   response.SetLoadTiming(timing);
 
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.h b/third_party/blink/renderer/platform/weborigin/kurl.h
index b74bd5e..9dfcab29 100644
--- a/third_party/blink/renderer/platform/weborigin/kurl.h
+++ b/third_party/blink/renderer/platform/weborigin/kurl.h
@@ -36,6 +36,9 @@
 #include "url/url_canon.h"
 #include "url/url_util.h"
 
+// KURL stands for the URL parser in KDE's HTML Widget (KHTML). The name hasn't
+// changed since Blink forked WebKit, which in turn forked KHTML.
+//
 // KURL is Blink's main URL class, and is the analog to GURL in other Chromium
 // code. It is not thread safe but is generally cheap to copy and compare KURLs
 // to each other.
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 929c0e4..f8fc7b7 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -233,6 +233,7 @@
             'paint_filter_builder::.+',
             'root_scroller_util::.+',
             'scheduler::.+',
+            'style_change_extra_data::.+',
             'style_change_reason::.+',
             'svg_path_parser::.+',
             'touch_action_util::.+',
diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py
index b196b25..6c9d7479 100755
--- a/tools/grit/grit/format/html_inline.py
+++ b/tools/grit/grit/format/html_inline.py
@@ -437,18 +437,18 @@
 
     return pattern % InlineCSSText(text, filepath)
 
-
   def InlineCSSImages(text, filepath=input_filepath):
     """Helper function that inlines external images in CSS backgrounds."""
     # Replace contents of url() for css attributes: content, background,
     # or *-image.
-    return re.sub('(content|background|[\w-]*-image):[^;]*' +
-                  '(url\((?!\[\[|{{)(?P<quote1>"|\'|)[^"\'()]*(?P=quote1)\)|' +
-                      'image-set\(([ ]*url\((?!\[\[|{{)' +
-                          '(?P<quote2>"|\'|)[^"\'()]*(?P=quote2)\)' +
-                              '[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\))',
-                  lambda m: InlineCSSUrls(m, filepath),
-                  text)
+    property_re = '(content|background|[\w-]*-image):[^;]*'
+    url_value_re = 'url\((?!\[\[|{{)(?P<quote1>"|\'|)[^"\'()]*(?P=quote1)\)'
+    image_set_value_re = 'image-set\(([ ]*url\((?!\[\[|{{)' + \
+        '(?P<quote2>"|\'|)[^"\'()]*(?P=quote2)\)' + \
+        '[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\)'
+    value_re = '(%s|%s)' % (url_value_re, image_set_value_re)
+    css_re = property_re + value_re
+    return re.sub(css_re, lambda m: InlineCSSUrls(m, filepath), text)
 
   def InlineCSSUrls(src_match, filepath=input_filepath):
     """Helper function that inlines each url on a CSS image rule match."""
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 47d7cdd..6389201 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -20528,7 +20528,7 @@
   <int value="2532" label="V8WasmSharedMemory"/>
   <int value="2533" label="V8WasmThreadOpcodes"/>
   <int value="2534" label="CacheStorageAddAllSuccessWithDuplicate"/>
-  <int value="2535" label="LegendDelegateFocusOrAccessKey"/>
+  <int value="2535" label="OBSOLETE_LegendDelegateFocusOrAccessKey"/>
   <int value="2536" label="FeaturePolicyReport"/>
   <int value="2537" label="V8Window_WebkitRTCPeerConnection_ConstructorGetter"/>
   <int value="2538" label="V8Window_WebkitMediaStream_ConstructorGetter"/>
@@ -20611,6 +20611,7 @@
   <int value="2611" label="HTMLCanvasElementLowLatency"/>
   <int value="2612" label="V8OptimizedFunctionWithOneShotBytecode"/>
   <int value="2613" label="SVGGeometryPropertyHasNonZeroUnitlessValue"/>
+  <int value="2614" label="CSSValueAppearanceNoImplementationSkipBorder"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
@@ -30183,6 +30184,7 @@
   <int value="357138275" label="enable-floating-virtual-keyboard:disabled"/>
   <int value="358399482" label="enable-high-dpi-fixed-position-compositing"/>
   <int value="358493847" label="BackgroundLoader:disabled"/>
+  <int value="359601954" label="CrostiniUsbSupport:enabled"/>
   <int value="360391863" label="NTPOfflineBadge:enabled"/>
   <int value="360599302" label="enable-gpu-rasterization"/>
   <int value="365467768" label="prefetch-search-results"/>
@@ -30414,6 +30416,7 @@
   <int value="772348426" label="AffiliationBasedMatching:enabled"/>
   <int value="772360813"
       label="enable-fullscreen-handwriting-virtual-keyboard:enabled"/>
+  <int value="773563826" label="CrostiniUsbSupport:disabled"/>
   <int value="773743944" label="show-android-files-in-files-app"/>
   <int value="773919225" label="disable-office-editing-component-extension"/>
   <int value="777667507" label="DesktopPWAsLinkCapturing:enabled"/>
@@ -33746,6 +33749,15 @@
   <int value="2" label="Existing user, new Chromebook added"/>
 </enum>
 
+<enum name="MultiDeviceSetupOOBEUserChoice">
+  <int value="0" label="MULTI_DEVICE_SETUP_OOBE_USER_CHOICE_ACCEPTED">
+    Accepted MultiDevice OOBE Setup.
+  </int>
+  <int value="1" label="MULTI_DEVICE_SETUP_OOBE_USER_CHOICE_DECLINED">
+    Declined MultiDevice OOBE Setup.
+  </int>
+</enum>
+
 <enum name="MultiDisplayModeDisplayCountRanges">
   <summary>
     Defines the ranges in which the number of displays connected in multi
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 6b24c67..b6af614 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8917,10 +8917,10 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.Canvas.ToBlob.CompleteEncodingDelay"
+<histogram base="true" name="Blink.Canvas.ToBlob.CompleteEncodingDelay"
     units="microseconds">
-  <owner>junov@chromium.org</owner>
-  <owner>xlai@chromium.org</owner>
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
   <summary>
     This metric measures the total time spent on completing encoding all the
     rows of an image (jpeg or png), as part of a canvas.toBlob API call.
@@ -8939,11 +8939,9 @@
     same as canvas.toBlob. It's worth to note that the values can come from idle
     tasks on either main or worker thread.
 
-    Warning: This metric may include reports from clients with low-resolution
-    clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
-    will cause this metric to have an abnormal distribution. When considering
-    revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
-    solution.
+    Note: This metric drops reports on clients with low-resolution clocks, which
+    means these reports will be biased against a portion of the population on
+    Windows. See Windows.HasHighResolutionTimeTicks for the affected sample.
   </summary>
 </histogram>
 
@@ -8961,9 +8959,10 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.Canvas.ToBlob.IdleTaskStatus" enum="IdleTaskStatus">
-  <owner>junov@chromium.org</owner>
-  <owner>xlai@chromium.org</owner>
+<histogram base="true" name="Blink.Canvas.ToBlob.IdleTaskStatus"
+    enum="IdleTaskStatus">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
   <summary>
     Records the status of the idle task when finishing a toBlob call.
 
@@ -8974,10 +8973,10 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.Canvas.ToBlob.InitiateEncodingDelay"
+<histogram base="true" name="Blink.Canvas.ToBlob.InitiateEncodingDelay"
     units="microseconds">
-  <owner>junov@chromium.org</owner>
-  <owner>xlai@chromium.org</owner>
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
   <summary>
     This metric measures the time spent from initiating image encoding (jpeg or
     png) on idle task to the actual execution time of initiation, as part of a
@@ -8993,15 +8992,35 @@
     same as canvas.toBlob. It's worth to note that the values can come from idle
     tasks on either main or worker thread.
 
-    Warning: This metric may include reports from clients with low-resolution
-    clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
-    will cause this metric to have an abnormal distribution. When considering
-    revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
-    solution.
+    Note: This metric drops reports on clients with low-resolution clocks, which
+    means these reports will be biased against a portion of the population on
+    Windows. See Windows.HasHighResolutionTimeTicks for the affected sample.
+  </summary>
+</histogram>
+
+<histogram base="true" name="Blink.Canvas.ToBlob.ScaledDuration"
+    units="microseconds/sqrt(pixels)" expires_after="2019-12-31">
+  <owner>fserb@chromium.org</owner>
+  <owner>davidqu@chromium.org</owner>
+  <summary>
+    Time in microseconds spent on the 2D canvas toBlob API call, divided by the
+    square root of the total number of pixels of the canvas.
+
+    In addition, metric values from OffscreenCanvas.convertToBlob API call are
+    also gathered into this histogram, because the logic flow is exactly the
+    same as canvas.toBlob. It's worth to note that the values can come from idle
+    tasks on either main or worker thread.
+
+    Note: This metric drops reports on clients with low-resolution clocks, which
+    means these reports will be biased against a portion of the population on
+    Windows. See Windows.HasHighResolutionTimeTicks for the affected sample.
   </summary>
 </histogram>
 
 <histogram name="Blink.Canvas.ToBlobDuration" units="microseconds">
+  <obsolete>
+    Replaced with Blink.Canvas.ToBlob.ScaledDuration in 10/2018.
+  </obsolete>
   <owner>junov@chromium.org</owner>
   <owner>xlai@chromium.org</owner>
   <summary>
@@ -50716,6 +50735,17 @@
   </summary>
 </histogram>
 
+<histogram name="MultiDeviceSetup.OOBE.UserChoice"
+    enum="MultiDeviceSetupOOBEUserChoice">
+  <owner>hansberry@chromium.org</owner>
+  <owner>khorimoto@chromium.org</owner>
+  <owner>hsuregan@chromium.org</owner>
+  <summary>
+    Breaks down the percentage of users who either accepted or declined
+    MultiDevice OOBE setup.
+  </summary>
+</histogram>
+
 <histogram name="MultiDeviceSetup_NotificationClicked"
     enum="MultiDeviceSetupNotification">
   <owner>jordynass@chromium.org</owner>
@@ -107519,7 +107549,7 @@
 <histogram base="true" name="Sync.ModelTypeEntityChange"
     enum="SyncEntityChange" expires_after="2020-02-01">
   <obsolete>
-    Deprecated as of 10/2018. Replaced by Sync.ModelTypeEntityChange2 which
+    Deprecated as of 10/2018. Replaced by Sync.ModelTypeEntityChange3 which
     splits initial remote updates from incremental remote updates.
   </obsolete>
   <owner>jkrcal@chromium.org</owner>
@@ -107533,6 +107563,21 @@
 
 <histogram base="true" name="Sync.ModelTypeEntityChange2"
     enum="SyncEntityChange" expires_after="2020-04-01">
+  <obsolete>
+    Deprecated as of 11/2018. Replaced by Sync.ModelTypeEntityChange3 which
+    fixes a bug affecting a subset of datatypes (directory codepath).
+  </obsolete>
+  <owner>jkrcal@chromium.org</owner>
+  <summary>
+    Recorded once for every sync entity change (whenever it is commited to the
+    server or updated from the server). This metric is used for monitoring
+    general health of sync client-side code. Note: This is only recorded with a
+    data type suffix. The base version is never recorded.
+  </summary>
+</histogram>
+
+<histogram base="true" name="Sync.ModelTypeEntityChange3"
+    enum="SyncEntityChange" expires_after="2020-04-01">
   <owner>jkrcal@chromium.org</owner>
   <summary>
     Recorded once for every sync entity change (whenever it is commited to the
@@ -124096,7 +124141,7 @@
   <suffix name="JPEG"/>
   <suffix name="PNG"/>
   <suffix name="WEBP"/>
-  <affected-histogram name="Blink.Canvas.ToBlobDuration"/>
+  <affected-histogram name="Blink.Canvas.ToBlob.ScaledDuration"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="BlinkCanvasToDataURLTime" separator=".">
@@ -135182,10 +135227,15 @@
   <affected-histogram name="Sync.ModelTypeCount4"/>
   <affected-histogram name="Sync.ModelTypeEntityChange">
     <obsolete>
-      Deprecated 10/2018. Replaced by Sync.ModelTypeEntityChange2.
+      Deprecated 10/2018. Replaced by Sync.ModelTypeEntityChange3.
     </obsolete>
   </affected-histogram>
-  <affected-histogram name="Sync.ModelTypeEntityChange2"/>
+  <affected-histogram name="Sync.ModelTypeEntityChange2">
+    <obsolete>
+      Deprecated 11/2018. Replaced by Sync.ModelTypeEntityChange3.
+    </obsolete>
+  </affected-histogram>
+  <affected-histogram name="Sync.ModelTypeEntityChange3"/>
   <affected-histogram name="Sync.ModelTypeMemoryKB"/>
   <affected-histogram name="Sync.USSMigrationEntityCount"/>
 </histogram_suffixes>
diff --git a/tools/perf/core/stacktrace_unittest.py b/tools/perf/core/stacktrace_unittest.py
index 912f453..48a30b85d 100644
--- a/tools/perf/core/stacktrace_unittest.py
+++ b/tools/perf/core/stacktrace_unittest.py
@@ -43,7 +43,9 @@
   # The breakpad file specific test only apply to platforms which use the
   # breakpad symbol format. This also must be tested in isolation because it can
   # potentially interfere with other tests symbol parsing.
-  @decorators.Enabled('mac', 'linux')
+  # @decorators.Enabled('mac', 'linux')
+  # Disabled tests due to flakiness: http://crbug.com/820282
+  @decorators.Disabled('all')
   @decorators.Isolated
   def testBadBreakpadFileIgnored(self):
     # pylint: disable=protected-access
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 897a255..dab5eb2 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -154,7 +154,7 @@
  <item id="network_location_provider" hash_code="23472048" type="1" second_id="96590038" content_hash_code="41087976" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="services/device/geolocation/network_location_provider.cc"/>
  <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="80741011" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="services/device/geolocation/network_location_request.cc"/>
  <item id="network_time_component" hash_code="46188932" type="0" content_hash_code="28051857" os_list="linux,windows" file_path="components/network_time/network_time_tracker.cc"/>
- <item id="ntp_custom_link_checker_request" hash_code="78408551" type="0" content_hash_code="13407730" os_list="linux,windows" file_path="chrome/browser/search/instant_service.cc"/>
+ <item id="ntp_custom_link_checker_request" hash_code="78408551" type="0" deprecated="2018-10-26" content_hash_code="13407730" file_path=""/>
  <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" content_hash_code="107035434" os_list="linux,windows" file_path="components/ntp_snippets/contextual/contextual_suggestions_fetch.cc"/>
  <item id="ntp_icon_source" hash_code="29197139" type="0" content_hash_code="16399294" os_list="linux,windows" file_path="chrome/browser/search/ntp_icon_source.cc"/>
  <item id="ntp_snippets_fetch" hash_code="15418154" type="0" content_hash_code="10078959" os_list="linux,windows" file_path="components/ntp_snippets/remote/json_request.cc"/>
diff --git a/ui/aura/mus/gesture_synchronizer_unittest.cc b/ui/aura/mus/gesture_synchronizer_unittest.cc
index cd1e7e0..81b75132 100644
--- a/ui/aura/mus/gesture_synchronizer_unittest.cc
+++ b/ui/aura/mus/gesture_synchronizer_unittest.cc
@@ -12,6 +12,9 @@
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/aura/test/aura_mus_test_base.h"
 #include "ui/aura/test/mus/test_window_tree.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/test/test_windows.h"
+#include "ui/events/test/event_generator.h"
 
 namespace aura {
 
@@ -20,31 +23,17 @@
   GestureSynchronizerTest() = default;
   ~GestureSynchronizerTest() override = default;
 
-  void SetUp() override {
-    test::AuraMusClientTestBase::SetUp();
-
-    window_tree_host_ = std::make_unique<WindowTreeHostMus>(
-        CreateInitParamsForTopLevel(window_tree_client_impl()));
-    window_tree_host_->InitHost();
-    window_tree_host_->Show();
-  }
-
  protected:
   ui::GestureRecognizer* gesture_recognizer() {
     return Env::GetInstance()->gesture_recognizer();
   }
 
-  std::unique_ptr<Window> NewWindow() {
-    auto window = std::make_unique<Window>(nullptr);
-    window->Init(ui::LAYER_NOT_DRAWN);
-    window_tree_host_->window()->AddChild(window.get());
-    window->Show();
-    return window;
+  std::unique_ptr<Window> NewWindow(aura::WindowDelegate* delegate = nullptr) {
+    return std::unique_ptr<Window>(aura::test::CreateTestWindowWithDelegate(
+        delegate, 0, gfx::Rect(0, 0, 100, 100), root_window()));
   }
 
  private:
-  std::unique_ptr<WindowTreeHostMus> window_tree_host_;
-
   DISALLOW_COPY_AND_ASSIGN(GestureSynchronizerTest);
 };
 
@@ -61,12 +50,23 @@
 }
 
 TEST_F(GestureSynchronizerTest, CancelActiveTouches) {
-  std::unique_ptr<Window> window = NewWindow();
+  aura::test::TestWindowDelegate delegate;
+  std::unique_ptr<Window> window = NewWindow(&delegate);
+  ui::test::EventGenerator event_generator(root_window());
+  event_generator.MoveTouch(window->GetBoundsInScreen().CenterPoint());
+  event_generator.PressTouch();
   gesture_recognizer()->CancelActiveTouches(window.get());
   EXPECT_EQ(window_tree()->last_cancelled_window_id(),
             WindowMus::Get(window.get())->server_id());
 }
 
+TEST_F(GestureSynchronizerTest, CancelActiveTouchesNotSentWithoutTouches) {
+  aura::test::TestWindowDelegate delegate;
+  std::unique_ptr<Window> window = NewWindow(&delegate);
+  gesture_recognizer()->CancelActiveTouches(window.get());
+  EXPECT_EQ(window_tree()->last_cancelled_window_id(), 0u);
+}
+
 TEST_F(GestureSynchronizerTest, TransferGestureEventsTo) {
   std::unique_ptr<Window> window1 = NewWindow();
   std::unique_ptr<Window> window2 = NewWindow();
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index dbbfe29..4b073ec 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -113,7 +113,6 @@
       device_scale_factor_(1.0f),
       cache_render_surface_requests_(0),
       deferred_paint_requests_(0),
-      backdrop_filter_quality_(1.0f),
       trilinear_filtering_request_(0),
       weak_ptr_factory_(this) {
   CreateCcLayer();
@@ -142,7 +141,6 @@
       device_scale_factor_(1.0f),
       cache_render_surface_requests_(0),
       deferred_paint_requests_(0),
-      backdrop_filter_quality_(1.0f),
       trilinear_filtering_request_(0),
       weak_ptr_factory_(this) {
   CreateCcLayer();
@@ -640,7 +638,6 @@
   cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
   cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
   cc_layer_->SetHideLayerAndSubtree(!visible_);
-  cc_layer_->SetBackdropFilterQuality(backdrop_filter_quality_);
   cc_layer_->SetElementId(cc::ElementId(cc_layer_->id()));
 
   SetLayerFilters();
@@ -676,10 +673,6 @@
     cc_layer_->SetCacheRenderSurface(false);
 }
 
-void Layer::SetBackdropFilterQuality(const float quality) {
-  backdrop_filter_quality_ = quality / GetDeviceScaleFactor();
-  cc_layer_->SetBackdropFilterQuality(backdrop_filter_quality_);
-}
 void Layer::AddDeferredPaintRequest() {
   ++deferred_paint_requests_;
   TRACE_COUNTER_ID1("ui", "DeferredPaintRequests", this,
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 0f9cc33..54c04338 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -428,14 +428,6 @@
   void AddDeferredPaintRequest();
   void RemoveDeferredPaintRequest();
 
-  // |quality| is used as a multiplier to scale the temporary surface
-  // that might be created by the compositor to apply the backdrop filters.
-  // The filter will be applied on a surface |quality|^2 times the area of the
-  // original background.
-  // |quality| lower than one will decrease memory usage and increase
-  // performance.
-  void SetBackdropFilterQuality(const float quality);
-
   bool IsPaintDeferredForTesting() const { return deferred_paint_requests_; }
 
   // Request trilinear filtering for layer.
@@ -632,8 +624,6 @@
   // means we should paint the layer.
   unsigned deferred_paint_requests_;
 
-  float backdrop_filter_quality_;
-
   // The counter to maintain how many trilinear filtering requests we have. If
   // the value > 0, means we need to perform trilinear filtering on the layer.
   // If the value == 0, means we should not perform trilinear filtering on the
diff --git a/ui/events/gestures/gesture_recognizer_impl.cc b/ui/events/gestures/gesture_recognizer_impl.cc
index 6e81131..4a23c0e 100644
--- a/ui/events/gestures/gesture_recognizer_impl.cc
+++ b/ui/events/gestures/gesture_recognizer_impl.cc
@@ -337,13 +337,15 @@
 
   std::vector<std::unique_ptr<TouchEvent>> cancelling_touches =
       GetEventPerPointForConsumer(consumer, ET_TOUCH_CANCELLED);
+  if (cancelling_touches.empty())
+    return false;
   for (const std::unique_ptr<TouchEvent>& cancelling_touch : cancelling_touches)
     helper->DispatchSyntheticTouchEvent(cancelling_touch.get());
   if (should_notify == kNotifyObservers) {
     for (GestureRecognizerObserver& observer : observers())
       observer.OnActiveTouchesCanceled(consumer);
   }
-  return !cancelling_touches.empty();
+  return true;
 }
 
 bool GestureRecognizerImpl::CleanupStateForConsumer(
diff --git a/ui/events/gestures/gesture_recognizer_impl_unittest.cc b/ui/events/gestures/gesture_recognizer_impl_unittest.cc
index 6446df7..35113421 100644
--- a/ui/events/gestures/gesture_recognizer_impl_unittest.cc
+++ b/ui/events/gestures/gesture_recognizer_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ui/events/gestures/gesture_recognizer_impl.h"
 
+#include "base/message_loop/message_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/gestures/gesture_recognizer_observer.h"
 
@@ -118,14 +119,26 @@
   GestureRecognizerImpl gesture_recognizer_;
   TestGestureEventHelper helper_;
   std::unique_ptr<TestGestureRecognizerObserver> observer_;
+  base::MessageLoopForUI message_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(GestureRecognizerImplTest);
 };
 
-TEST_F(GestureRecognizerImplTest, CancelActiveTouchEvents) {
+TEST_F(GestureRecognizerImplTest, CancelActiveTouchesNoCancellations) {
   GestureConsumer consumer;
   gesture_recognizer()->CancelActiveTouches(&consumer);
 
+  EXPECT_EQ(0, observer()->active_touches_cancelled_call_count());
+  EXPECT_FALSE(observer()->last_cancelled());
+}
+
+TEST_F(GestureRecognizerImplTest, CancelActiveTouches) {
+  GestureConsumer consumer;
+  TouchEvent event(ET_TOUCH_PRESSED, gfx::Point(), base::TimeTicks::Now(),
+                   PointerDetails());
+  gesture_recognizer()->ProcessTouchEventPreDispatch(&event, &consumer);
+  gesture_recognizer()->CancelActiveTouches(&consumer);
+
   EXPECT_EQ(1, observer()->active_touches_cancelled_call_count());
   EXPECT_EQ(&consumer, observer()->last_cancelled());
 }
diff --git a/ui/events/gestures/gesture_recognizer_observer.h b/ui/events/gestures/gesture_recognizer_observer.h
index 4826cda..e07a8153 100644
--- a/ui/events/gestures/gesture_recognizer_observer.h
+++ b/ui/events/gestures/gesture_recognizer_observer.h
@@ -13,12 +13,21 @@
 
 class EVENTS_EXPORT GestureRecognizerObserver : public base::CheckedObserver {
  public:
+  // Called when CancelActiveTouchesExcept() is called.
   virtual void OnActiveTouchesCanceledExcept(
       GestureConsumer* not_cancelled) = 0;
+
+  // Called when TransferEventsTo() happened from |current_consumer| to
+  // |new_consumer|.
   virtual void OnEventsTransferred(
       GestureConsumer* current_consumer,
       GestureConsumer* new_consumer,
       TransferTouchesBehavior transfer_touches_behavior) = 0;
+
+  // Called when CancelActiveTouches() cancels touches on |consumer|. This is
+  // not called from CancelActiveTouchesExcept() causes cancel on |consumer|.
+  // Also this is not called when an invocation of CancelActiveTouches() doesn't
+  // cancel anything actually.
   virtual void OnActiveTouchesCanceled(GestureConsumer* consumer) = 0;
 
  protected:
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types.js b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
index c02b0ff2..3dff678 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
@@ -135,12 +135,12 @@
    * never called, it's here to match the signature from the Web Standards.
    */
   readEntries(success, error) {
-    let children = this.children_;
+    const children = this.children_;
     // readEntries is suppose to return empty result when there are no more
     // files to return, so we clear the children_ attribute for next call.
     this.children_ = [];
     // Triggers callback asynchronously.
-    setTimeout(children => success(children), 0, children);
+    setTimeout(success, 0, children);
   }
 }
 
diff --git a/ui/file_manager/file_manager/foreground/js/crostini.js b/ui/file_manager/file_manager/foreground/js/crostini.js
index f9c3ee45..13e746b 100644
--- a/ui/file_manager/file_manager/foreground/js/crostini.js
+++ b/ui/file_manager/file_manager/foreground/js/crostini.js
@@ -16,12 +16,22 @@
  * @private {!Map<VolumeManagerCommon.RootType, string>}
  */
 Crostini.VALID_ROOT_TYPES_FOR_SHARE = new Map([
+  [VolumeManagerCommon.RootType.DOWNLOADS, 'Downloads'],
+  [VolumeManagerCommon.RootType.REMOVABLE, 'Removable'],
+]);
+
+/**
+ * Can be collapsed into VALD_ROOT_TYPES_FOR_SHARE once
+ * DriveFS flag is removed.
+ * Keep in sync with histograms.xml:FileBrowserCrostiniSharedPathsDepth
+ * histogram_suffix.
+ * @private {!Map<VolumeManagerCommon.RootType, string>}
+ */
+Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE = new Map([
   [VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT, 'DriveComputers'],
   [VolumeManagerCommon.RootType.COMPUTER, 'DriveComputers'],
-  [VolumeManagerCommon.RootType.DOWNLOADS, 'Downloads'],
   [VolumeManagerCommon.RootType.DRIVE, 'MyDrive'],
   [VolumeManagerCommon.RootType.TEAM_DRIVE, 'TeamDrive'],
-  [VolumeManagerCommon.RootType.REMOVABLE, 'Removable'],
 ]);
 
 /** @private {string} */
@@ -53,6 +63,7 @@
 
   // Record UMA.
   let suffix = Crostini.VALID_ROOT_TYPES_FOR_SHARE.get(info.rootType) ||
+      Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE.get(info.rootType) ||
       Crostini.UMA_ROOT_TYPE_OTHER;
   metrics.recordSmallCount(
       'CrostiniSharedPaths.Depth.' + suffix,
@@ -118,19 +129,15 @@
   if (!Crostini.IS_CROSTINI_FILES_ENABLED)
     return false;
 
-  // Root of volume not allowed.
-  if (entry.fullPath === '/')
-    return false;
-
   // Only directories for persistent shares.
   if (persist && !entry.isDirectory)
     return false;
 
   // Allow Downloads, and Drive if DriveFS is enabled.
   const rootType = volumeManager.getLocationInfo(entry).rootType;
-  return rootType === VolumeManagerCommon.RootType.DOWNLOADS ||
+  return Crostini.VALID_ROOT_TYPES_FOR_SHARE.has(rootType) ||
       (loadTimeData.getBoolean('DRIVE_FS_ENABLED') &&
-       Crostini.VALID_ROOT_TYPES_FOR_SHARE.has(rootType));
+       Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE.has(rootType));
 };
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/js/crostini_unittest.js b/ui/file_manager/file_manager/foreground/js/crostini_unittest.js
index a22fa6ca..6235e43 100644
--- a/ui/file_manager/file_manager/foreground/js/crostini_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/crostini_unittest.js
@@ -7,8 +7,9 @@
 };
 
 window.loadTimeData = {
-  getBoolean: function() {
-    return true;
+  data: {'DRIVE_FS_ENABLED': false},
+  getBoolean: function(key) {
+    return this.data[key];
   }
 };
 
@@ -46,29 +47,40 @@
 function testCanSharePath() {
   Crostini.IS_CROSTINI_FILES_ENABLED = true;
 
-  const mockFileSystem = new MockFileSystem('volumeId');
+  const mockFileSystem = new MockFileSystem('test');
   const root = new MockDirectoryEntry(mockFileSystem, '/');
   const rootFile = new MockEntry(mockFileSystem, '/file');
   const rootFolder = new MockDirectoryEntry(mockFileSystem, '/folder');
   const fooFile = new MockEntry(mockFileSystem, '/foo/file');
   const fooFolder = new MockDirectoryEntry(mockFileSystem, '/foo/folder');
 
-  assertFalse(Crostini.canSharePath(root, true, volumeManager));
-  assertFalse(Crostini.canSharePath(root, false, volumeManager));
-  assertFalse(Crostini.canSharePath(rootFile, true, volumeManager));
-  assertFalse(Crostini.canSharePath(rootFile, false, volumeManager));
-  assertFalse(Crostini.canSharePath(rootFolder, true, volumeManager));
-  assertFalse(Crostini.canSharePath(rootFolder, false, volumeManager));
-  assertFalse(Crostini.canSharePath(fooFile, true, volumeManager));
-  assertFalse(Crostini.canSharePath(fooFile, false, volumeManager));
-  assertFalse(Crostini.canSharePath(fooFolder, true, volumeManager));
-  assertFalse(Crostini.canSharePath(fooFolder, false, volumeManager));
-
-  for (type in Crostini.VALID_ROOT_TYPES_FOR_SHARE) {
+  window.loadTimeData.data['DRIVE_FS_ENABLED'] = false;
+  const disallowed = new Map(Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE);
+  disallowed['test'] = 'test';
+  for (let type in disallowed) {
     volumeManagerRootType = type;
     assertFalse(Crostini.canSharePath(root, true, volumeManager));
     assertFalse(Crostini.canSharePath(root, false, volumeManager));
     assertFalse(Crostini.canSharePath(rootFile, true, volumeManager));
+    assertFalse(Crostini.canSharePath(rootFile, false, volumeManager));
+    assertFalse(Crostini.canSharePath(rootFolder, true, volumeManager));
+    assertFalse(Crostini.canSharePath(rootFolder, false, volumeManager));
+    assertFalse(Crostini.canSharePath(fooFile, true, volumeManager));
+    assertFalse(Crostini.canSharePath(fooFile, false, volumeManager));
+    assertFalse(Crostini.canSharePath(fooFolder, true, volumeManager));
+    assertFalse(Crostini.canSharePath(fooFolder, false, volumeManager));
+  }
+
+  window.loadTimeData.data['DRIVE_FS_ENABLED'] = true;
+  const allowed = new Map([
+    ...Crostini.VALID_ROOT_TYPES_FOR_SHARE,
+    ...Crostini.VALID_DRIVE_FS_ROOT_TYPES_FOR_SHARE
+  ]);
+  for (let type in allowed) {
+    volumeManagerRootType = type;
+    assertTrue(Crostini.canSharePath(root, true, volumeManager));
+    assertTrue(Crostini.canSharePath(root, false, volumeManager));
+    assertFalse(Crostini.canSharePath(rootFile, true, volumeManager));
     assertTrue(Crostini.canSharePath(rootFile, false, volumeManager));
     assertTrue(Crostini.canSharePath(rootFolder, true, volumeManager));
     assertTrue(Crostini.canSharePath(rootFolder, false, volumeManager));
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index 6adb8ba..7952aef 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -228,6 +228,7 @@
       <cr-menu-item command="#format"></cr-menu-item>
       <cr-menu-item command="#rename"></cr-menu-item>
       <cr-menu-item command="#remove-folder-shortcut"></cr-menu-item>
+      <cr-menu-item command="#share-with-linux"></cr-menu-item>
     </cr-menu>
 
     <cr-menu id="directory-tree-context-menu" class="chrome-menu files-menu"
@@ -236,6 +237,7 @@
       <cr-menu-item command="#cut" visibleif="full-page"></cr-menu-item>
       <cr-menu-item command="#copy" visibleif="full-page"></cr-menu-item>
       <cr-menu-item command="#paste-into-folder" visibleif="full-page"></cr-menu-item>
+      <cr-menu-item command="#share-with-linux"></cr-menu-item>
       <hr visibleif="full-page">
       <cr-menu-item command="#rename"></cr-menu-item>
       <cr-menu-item command="#delete" i18n-content="DELETE_BUTTON_LABEL"></cr-menu-item>
diff --git a/ui/file_manager/file_manager/test/crostini_share.js b/ui/file_manager/file_manager/test/crostini_share.js
index 068d0243..53e5991 100644
--- a/ui/file_manager/file_manager/test/crostini_share.js
+++ b/ui/file_manager/file_manager/test/crostini_share.js
@@ -75,6 +75,13 @@
       '[command="#share-with-linux"][hidden][disabled="disabled"]';
   const menuShareWithLinux = '#file-context-menu:not([hidden]) ' +
       '[command="#share-with-linux"]:not([hidden]):not([disabled])';
+  const downloadsDirTree = '#directory-tree [volume-type-icon="downloads"]';
+  const removableVolumeRoot = '#directory-tree [volume-type-icon="removable"]';
+  const menuShareWithLinuxDirTree =
+      '#directory-tree-context-menu:not([hidden]) ' +
+      '[command="#share-with-linux"]:not([hidden]):not([disabled])';
+  const menuShareWithLinuxVolumeRoot = '#roots-context-menu:not([hidden]) ' +
+      '[command="#share-with-linux"]:not([hidden]):not([disabled])';
   let alreadySharedPhotosDir;
 
   test.setupAndWaitUntilReady()
@@ -106,10 +113,29 @@
       })
       .then(() => {
         // Right-click 'Downloads' directory.
-        // Check 'Share with Linux' is not shown in menu.
+        // Check 'Share with Linux' is shown in menu.
         assertTrue(
             test.fakeMouseRightClick(downloads), 'right-click downloads');
-        return test.waitForElement(menuNoShareWithLinux);
+        return test.waitForElement(menuShareWithLinux);
+      })
+      .then(() => {
+        // Right-click 'Downloads' directory in directory tree.
+        // Check 'Share with Linux' is shown in menu.
+        assertTrue(
+            test.fakeMouseRightClick(downloadsDirTree), 'downloads dirtree');
+        return test.waitForElement(menuShareWithLinuxDirTree);
+      })
+      .then(() => {
+        // Select removable root.
+        test.mountRemovable();
+        return test.waitForElement(removableVolumeRoot);
+      })
+      .then(() => {
+        // Right-click 'MyUSB' removable root.
+        // Check 'Share with Linux' is shown in menu.
+        assertTrue(
+            test.fakeMouseRightClick(removableVolumeRoot), 'removable root');
+        return test.waitForElement(menuShareWithLinuxVolumeRoot);
       })
       .then(() => {
         // Select 'Linux files' in directory tree to show dir A in file list.
diff --git a/ui/file_manager/file_manager/test/js/test_util.js b/ui/file_manager/file_manager/test/js/test_util.js
index 84cc84a..c07d7d0b 100644
--- a/ui/file_manager/file_manager/test/js/test_util.js
+++ b/ui/file_manager/file_manager/test/js/test_util.js
@@ -412,14 +412,14 @@
  * @param {!Array<!test.TestEntryInfo>} crostini Entries for crostini.
  */
 test.addEntries = function(downloads, drive, crostini) {
-  var fsDownloads = /** @type {MockFileSystem} */ (
+  const fsDownloads = /** @type {MockFileSystem} */ (
       mockVolumeManager
           .getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DOWNLOADS)
           .fileSystem);
   fsDownloads.populate(
       test.TestEntryInfo.getMockFileSystemPopulateRows(downloads, '/'), true);
 
-  var fsDrive = /** @type {MockFileSystem} */ (
+  const fsDrive = /** @type {MockFileSystem} */ (
       mockVolumeManager
           .getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DRIVE)
           .fileSystem);
@@ -427,7 +427,7 @@
       test.TestEntryInfo.getMockFileSystemPopulateRows(drive, '/root/'), true);
   fsDrive.populate(['/team_drives/']);
 
-  var fsCrostini = /** @type {MockFileSystem} */ (
+  const fsCrostini = /** @type {MockFileSystem} */ (
       mockVolumeManager
           .createVolumeInfo(
               VolumeManagerCommon.VolumeType.CROSTINI, 'crostini',
@@ -435,6 +435,14 @@
           .fileSystem);
   fsCrostini.populate(
       test.TestEntryInfo.getMockFileSystemPopulateRows(crostini, '/'), true);
+
+  const fsRemovable = /** @type {MockFileSystem} */ (
+      mockVolumeManager
+          .createVolumeInfo(
+              VolumeManagerCommon.VolumeType.REMOVABLE, 'removable:MyUSB',
+              'MyUSB')
+          .fileSystem);
+  fsRemovable.populate([], true);
 };
 
 /**
@@ -456,6 +464,24 @@
 };
 
 /**
+ * Sends mount event for crostini volume.
+ */
+test.mountRemovable = function() {
+  chrome.fileManagerPrivate.onMountCompleted.dispatchEvent({
+    status: 'success',
+    eventType: 'mount',
+    volumeMetadata: {
+      volumeType: VolumeManagerCommon.VolumeType.REMOVABLE,
+      volumeId: 'removable:MyUSB',
+      isReadOnly: false,
+      iconSet: {},
+      profile: {isCurrentProfile: true, displayName: ''},
+      mountContext: 'user',
+    },
+  });
+};
+
+/**
  * Waits for the file list turns to the given contents.
  * @param {!Array<!Array<string>>} expected Expected contents of file list.
  * @param {{orderCheck:boolean, ignoreName:boolean, ignoreSize:boolean,
@@ -528,18 +554,19 @@
   test.inputText = test.util.sync.inputText.bind(null, window);
   test.selectFile = test.util.sync.selectFile.bind(null, window);
 
+  const downloadsElement = '#directory-tree [volume-type-icon="downloads"]';
+
   return test.loadData()
       .then(() => {
         test.addEntries(entriesDownloads, entriesDrive, entriesCrostini);
-        return test.waitForElement(
-            '#directory-tree [volume-type-icon="downloads"]');
+        return test.waitForElement(downloadsElement);
       })
       .then((downloadsIcon) => {
-        // Click Downloads, or refresh button if already on Downloads.
-        assertTrue(test.fakeMouseClick(
-            downloadsIcon.parentElement.hasAttribute('selected') ?
-                '#refresh-button' :
-                '#directory-tree [volume-type-icon="downloads"]'));
+        // Click Downloads if not already on Downloads, then refresh button.
+        if (!downloadsIcon.parentElement.hasAttribute('selected')) {
+          assertTrue(test.fakeMouseClick(downloadsElement), 'click downloads');
+        }
+        assertTrue(test.fakeMouseClick('#refresh-button'), 'click refresh');
         return test.waitForFiles(
             test.TestEntryInfo.getExpectedRows(entriesDownloads));
       });
diff --git a/ui/latency/frame_metrics.cc b/ui/latency/frame_metrics.cc
index dd052be..d4ccf32 100644
--- a/ui/latency/frame_metrics.cc
+++ b/ui/latency/frame_metrics.cc
@@ -425,36 +425,44 @@
   FrameMetricsTraceData() = default;
   ~FrameMetricsTraceData() override = default;
 
-  void AppendAsTraceFormat(std::string* out) const override {
-    base::trace_event::TracedValue state;
+  void ToTracedValue(base::trace_event::TracedValue* state) const {
+    state->BeginDictionary("Source");
+    settings.AsValueInto(state);
+    state->EndDictionary();
 
-    state.BeginDictionary("Source");
-    settings.AsValueInto(&state);
-    state.EndDictionary();
+    state->BeginDictionary("Skips");
+    skips.AsValueInto(state);
+    state->EndDictionary();
 
-    state.BeginDictionary("Skips");
-    skips.AsValueInto(&state);
-    state.EndDictionary();
-
-    state.BeginDictionary("Latency");
-    latency.AsValueInto(&state);
-    state.EndDictionary();
+    state->BeginDictionary("Latency");
+    latency.AsValueInto(state);
+    state->EndDictionary();
 
     if (settings.is_frame_latency_speed_on()) {
-      state.BeginDictionary("Speed");
-      speed.AsValueInto(&state);
-      state.EndDictionary();
+      state->BeginDictionary("Speed");
+      speed.AsValueInto(state);
+      state->EndDictionary();
     }
 
     if (settings.is_frame_latency_acceleration_on()) {
-      state.BeginDictionary("Acceleration");
-      acceleration.AsValueInto(&state);
-      state.EndDictionary();
+      state->BeginDictionary("Acceleration");
+      acceleration.AsValueInto(state);
+      state->EndDictionary();
     }
+  }
 
+  void AppendAsTraceFormat(std::string* out) const override {
+    base::trace_event::TracedValue state;
+    ToTracedValue(&state);
     state.AppendAsTraceFormat(out);
   }
 
+  bool AppendToProto(ProtoAppender* appender) override {
+    base::trace_event::TracedValue state;
+    ToTracedValue(&state);
+    return state.AppendToProto(appender);
+  }
+
   void EstimateTraceMemoryOverhead(
       base::trace_event::TraceEventMemoryOverhead* overhead) override {
     overhead->Add(base::trace_event::TraceEventMemoryOverhead::kFrameMetrics,
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/.eslintrc.js b/ui/webui/resources/cr_components/.eslintrc.js
similarity index 100%
rename from ui/webui/resources/cr_components/chromeos/multidevice_setup/.eslintrc.js
rename to ui/webui/resources/cr_components/.eslintrc.js
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
index 2ec322f4..9be02cb2 100644
--- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
+++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
@@ -161,7 +161,7 @@
 
     /** @private */
     onCancelRequested_: function() {
-      this.exitSetupFlow_();
+      this.exitSetupFlow_(false /* didUserCompleteSetup */);
     },
 
     /** @private */
@@ -196,7 +196,7 @@
           this.setHostDevice_();
           return;
         case PageName.SUCCESS:
-          this.exitSetupFlow_();
+          this.exitSetupFlow_(true /* didUserCompleteSetup */);
           return;
         case PageName.START:
           if (this.delegate.isPasswordRequiredToSetHost())
@@ -221,7 +221,7 @@
             }
 
             if (this.delegate.shouldExitSetupFlowAfterSettingHost()) {
-              this.exitSetupFlow_();
+              this.exitSetupFlow_(true /* didUserCompleteSetup */);
               return;
             }
 
@@ -298,11 +298,11 @@
 
     /**
      * Notifies observers that the setup flow has completed.
-     *
+     * @param {boolean} didUserCompleteSetup
      * @private
      */
-    exitSetupFlow_: function() {
-      this.fire('setup-exited');
+    exitSetupFlow_: function(didUserCompleteSetup) {
+      this.fire('setup-exited', {didUserCompleteSetup: didUserCompleteSetup});
     },
   });
 
diff --git a/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn b/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn
new file mode 100644
index 0000000..916a55b
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn
@@ -0,0 +1,27 @@
+# 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.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+  deps = [
+    ":add_smb_share_dialog",
+    ":smb_browser_proxy",
+  ]
+}
+
+js_library("smb_browser_proxy") {
+  deps = [
+    "//ui/webui/resources/js:cr",
+  ]
+}
+
+js_library("add_smb_share_dialog") {
+  deps = [
+    "//ui/webui/resources/cr_elements/cr_input:cr_input",
+    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:i18n_behavior",
+    "//ui/webui/resources/js:web_ui_listener_behavior",
+  ]
+}
diff --git a/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS b/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS
new file mode 100644
index 0000000..704b95c8
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/OWNERS
@@ -0,0 +1 @@
+khorimoto@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
similarity index 72%
rename from chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html
rename to ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
index 8c30c6d..602e3f34 100644
--- a/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
@@ -3,17 +3,17 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="../settings_vars_css.html">
 <link rel="import" href="smb_browser_proxy.html">
 
-<dom-module id="settings-add-smb-share-dialog">
+<dom-module id="add-smb-share-dialog">
   <template>
-    <style include="settings-shared md-select">
+    <style include="md-select paper-button-style">
       #dialog [slot=body] {
         height: 350px;
       }
@@ -43,47 +43,47 @@
     </style>
 
     <cr-dialog id="dialog">
-      <div slot="title">$i18n{addSmbShare}</div>
+      <div slot="title">[[i18n('addSmbShare')]]</div>
       <div slot="body" spellcheck="false">
-        <cr-searchable-drop-down id="address" label="$i18n{smbShareUrl}"
+        <cr-searchable-drop-down id="address" label="[[i18n('smbShareUrl')]]"
             value="{{mountUrl_}}" items="[[discoveredShares_]]"
             placeholder="\\server\share" on-change="onURLChanged_"
             update-value-on-input autofocus>
         </cr-searchable-drop-down>
-        <cr-input id="name" label="$i18n{smbShareName}" value="{{mountName_}}"
-            maxlength="64">
+        <cr-input id="name" label="[[i18n('smbShareName')]]"
+            value="{{mountName_}}" maxlength="64">
         </cr-input>
         <div id="authentication-method" hidden="[[!isActiveDirectory_]]">
           <div id="authentication-label" class="label">
-              $i18n{smbShareAuthenticationMethod}
+            [[i18n('smbShareAuthenticationMethod')]]
           </div>
           <select class="md-select" aria-labelledby="authentication-label"
               value="{{authenticationMethod_::change}}">
             <option value="kerberos">
-                $i18n{smbShareKerberosAuthentication}
+              [[i18n('smbShareKerberosAuthentication')]]
             </option>
             <option value="credentials">
-                $i18n{smbShareStandardAuthentication}
+              [[i18n('smbShareStandardAuthentication')]]
             </option>
           </select>
         </div>
         <div id="credentials"
             hidden="[[!shouldShowCredentialUI_(authenticationMethod_)]]">
-          <cr-input id="username" label="$i18n{smbShareUsername}"
+          <cr-input id="username" label="[[i18n('smbShareUsername')]]"
               value="{{username_}}">
           </cr-input>
           <cr-input id="password" type="password"
-              label="$i18n{smbSharePassword}" value="{{password_}}">
+              label="[[i18n('smbSharePassword')]]" value="{{password_}}">
           </cr-input>
         </div>
       </div>
       <div slot="button-container">
         <paper-button class="cancel-button" on-click="cancel_" id="cancel">
-            $i18n{cancel}</paper-button>
+          [[i18n('cancel')]]
+        </paper-button>
         <paper-button id="actionButton" class="action-button"
-          on-click="onAddButtonTap_"
-          disabled="[[!canAddShare_(mountUrl_)]]">
-            $i18n{add}
+            on-click="onAddButtonTap_" disabled="[[!canAddShare_(mountUrl_)]]">
+          [[i18n('add')]]
         </paper-button>
       </div>
     </cr-dialog>
diff --git a/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.js
similarity index 88%
rename from chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js
rename to ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.js
index bed31c98..40bf9c6 100644
--- a/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.js
@@ -3,14 +3,13 @@
 // found in the LICENSE file.
 
 /**
- * @fileoverview 'settings-add-smb-share-dialog' is a component for adding
- * an SMB Share.
+ * @fileoverview 'add-smb-share-dialog' is a component for adding an SMB Share.
  */
 
 Polymer({
-  is: 'settings-add-smb-share-dialog',
+  is: 'add-smb-share-dialog',
 
-  behaviors: [WebUIListenerBehavior],
+  behaviors: [I18nBehavior, WebUIListenerBehavior],
 
   properties: {
     /** @private {string} */
@@ -63,12 +62,12 @@
     },
   },
 
-  /** @private {?settings.SmbBrowserProxy} */
+  /** @private {?smb_shares.SmbBrowserProxy} */
   browserProxy_: null,
 
   /** @override */
   created: function() {
-    this.browserProxy_ = settings.SmbBrowserProxyImpl.getInstance();
+    this.browserProxy_ = smb_shares.SmbBrowserProxyImpl.getInstance();
   },
 
   /** @override */
diff --git a/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.html b/ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.html
similarity index 100%
rename from chrome/browser/resources/settings/downloads_page/smb_browser_proxy.html
rename to ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.html
diff --git a/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js b/ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.js
similarity index 90%
rename from chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js
rename to ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.js
index 59ca15f..591768c 100644
--- a/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 /**
- * @fileoverview A helper object used from the "SMB Share" section to
+ * @fileoverview A helper object used from the "add SMB share" dialog to
  * interact with the browser. Used only on Chrome OS.
  */
 
@@ -28,7 +28,7 @@
   CREDENTIALS: 'credentials',
 };
 
-cr.define('settings', function() {
+cr.define('smb_shares', function() {
   /** @interface */
   class SmbBrowserProxy {
     /**
@@ -47,7 +47,7 @@
     startDiscovery() {}
   }
 
-  /** @implements {settings.SmbBrowserProxy} */
+  /** @implements {smb_shares.SmbBrowserProxy} */
   class SmbBrowserProxyImpl {
     /** @override */
     smbMount(smbUrl, smbName, username, password, authMethod) {
diff --git a/ui/webui/resources/cr_components/cr_components_resources.grdp b/ui/webui/resources/cr_components/cr_components_resources.grdp
index 4bee1cd9..2c978f4 100644
--- a/ui/webui/resources/cr_components/cr_components_resources.grdp
+++ b/ui/webui/resources/cr_components/cr_components_resources.grdp
@@ -364,5 +364,23 @@
                file="cr_components/chromeos/multidevice_setup/ui_page.js"
                type="chrome_html"
                compress="gzip" />
+
+    <!-- Shared between settings and add new share flow. -->
+    <structure name="IDR_WEBUI_CHROMEOS_SMB_SHARES_SMB_BROWSER_PROXY_HTML"
+               file="cr_components/chromeos/smb_shares/smb_browser_proxy.html"
+               type="chrome_html"
+               compress="gzip" />
+    <structure name="IDR_WEBUI_CHROMEOS_SMB_SHARES_SMB_BROWSER_PROXY_JS"
+               file="cr_components/chromeos/smb_shares/smb_browser_proxy.js"
+               type="chrome_html"
+               compress="gzip" />
+    <structure name="IDR_WEBUI_CHROMEOS_SMB_SHARES_ADD_SMB_SHARE_DIALOG_HTML"
+               file="cr_components/chromeos/smb_shares/add_smb_share_dialog.html"
+               type="chrome_html"
+               compress="gzip" />
+    <structure name="IDR_WEBUI_CHROMEOS_SMB_SHARES_ADD_SMB_SHARE_DIALOG_JS"
+               file="cr_components/chromeos/smb_shares/add_smb_share_dialog.js"
+               type="chrome_html"
+               compress="gzip" />
   </if>
 </grit-part>
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.html b/ui/webui/resources/cr_elements/cr_input/cr_input.html
index b328ee4..f66e061 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.html
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -40,7 +40,7 @@
 
       /* Margin between <input> and <paper-button> in the 'suffix' slot */
       :host ::slotted(paper-button[slot=suffix]) {
-        margin-inline-start: var(--cr-button-edge-spacing);
+        margin-inline-start: var(--cr-button-edge-spacing) !important;
       }
 
       :host([invalid]) #label {
diff --git a/url/README.md b/url/README.md
index 412bd43b..8d63fda 100644
--- a/url/README.md
+++ b/url/README.md
@@ -8,7 +8,7 @@
 ### Parsing
 
 The `url_parse.*` files are the parser. This code does no string
-transformations. Its only job is to take an input string and splits out the
+transformations. Its only job is to take an input string and split out the
 components of the URL as best as it can deduce them, for a given type of URL.
 Parsing can never fail, it will take its best guess. This layer does not
 have logic for determining the type of URL parsing to apply, that needs to
@@ -53,7 +53,7 @@
 
 The main header to include is `url/url_util.h`.
 
-### GURL and Origin
+### Google URL (GURL) and Origin
 
 At the highest layer, a C++ object for representing URLs is provided. This
 object uses STL. Most uses need only this layer. Include `url/gurl.h`.
diff --git a/url/gurl.h b/url/gurl.h
index 58ab96dc..74ab136 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -20,7 +20,7 @@
 #include "url/url_constants.h"
 #include "url/url_export.h"
 
-// Represents a URL.
+// Represents a URL. GURL is Google's URL parsing library.
 //
 // A parsed canonicalized URL is guaranteed to be UTF-8. Any non-ASCII input
 // characters are UTF-8 encoded and % escaped to ASCII.